Compare commits

..

4 Commits

Author SHA1 Message Date
Keith Edmunds
89d49f3e34 Merge 2021-08-14 18:44:05 +01:00
Keith Edmunds
e813a01e14 Improve track info box 2021-08-14 18:29:29 +01:00
Keith Edmunds
72e3ef69ff Handle files not found in database update
Fixes #37
Fixes #36
2021-08-14 18:26:59 +01:00
Keith Edmunds
94e7508a24 Default volume to 75 2021-08-14 12:03:46 +01:00
4 changed files with 88 additions and 34 deletions

View File

@ -36,7 +36,7 @@ class Config(object):
ROOT = os.environ.get('ROOT') or "/home/kae/music"
TESTMODE = True
TIMER_MS = 500
VOLUME_VLC_DEFAULT = 81
VOLUME_VLC_DEFAULT = 75
config = Config

View File

@ -2,7 +2,7 @@
import sqlalchemy
from datetime import datetime
from datetime import datetime, time
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import (
Boolean,
@ -119,6 +119,35 @@ class Playdates(Base):
else:
return None
@staticmethod
def remove_track(session, track_id):
"""
Remove all records of track_id
"""
session.query(Playdates).filter(
Playdates.track_id == track_id,
).delete()
session.commit()
@staticmethod
def last_show(session, track):
"""
Return datetime track last played during show time or None
FIXME: hard coded times in here
"""
# dayofweek: 1 = Sunday, 2 = Monday, ..., 7 = Saturday.
friday = 6
after = time(20, 0)
return session.query(Playdates).filter(
(Playdates.track_id == track.id),
(func.dayofweek(Playdates.lastplayed) == friday),
(func.time(Playdates.lastplayed) > after),
).order_by(Playdates.lastplayed.desc()).first()
class Playlists(Base):
"""
@ -293,18 +322,11 @@ class PlaylistTracks(Base):
session.commit()
@staticmethod
def get_playlists_containing_track_id(session, track_id):
def get_track_playlists(session, track_id):
"Return all PlaylistTracks objects with this track_id"
playlists = []
playlist_ids = session.query(PlaylistTracks.playlist_id).filter(
return session.query(PlaylistTracks).filter(
PlaylistTracks.track_id == track_id).all()
for p in playlist_ids:
playlist = session.query(Playlists).filter(
Playlists.id == p[0]).first()
if playlist:
playlists.append(playlist)
return playlists
@staticmethod
def move_track(session, from_playlist_id, row, to_playlist_id):
@ -492,6 +514,29 @@ class Tracks(Base):
ERROR(f"get_track({id}): not found")
return None
@staticmethod
def search(session, title=None, artist=None, duration=None):
"""
Return any tracks matching passed criteria
"""
DEBUG(
f"Tracks.search({title=}, {artist=}), {duration=})"
)
if not title and not artist and not duration:
return None
q = session.query(Tracks).filter(False)
if title:
q = q.filter(Tracks.title == title)
if artist:
q = q.filter(Tracks.artist == artist)
if duration:
q = q.filter(Tracks.duration == duration)
return q.all()
@staticmethod
def get_track_from_filename(session, filename):
"""
@ -527,6 +572,7 @@ class Tracks(Base):
try:
session.query(Tracks).filter(Tracks.path == path).delete()
session.commit()
except IntegrityError as exception:
ERROR(f"Can't remove track with {path=} ({exception=})")

View File

@ -530,6 +530,11 @@ class PlaylistTab(QTableWidget):
duration = Tracks.get_duration(session, self._get_row_id(row))
return start + timedelta(milliseconds=duration)
def _can_read_track(self, track):
"Check track file is readable"
return os.access(track.path, os.R_OK)
def _context_menu(self, pos):
self.menu.exec_(self.mapToGlobal(pos))
@ -617,12 +622,12 @@ class PlaylistTab(QTableWidget):
if not track:
txt = f"Track not found (track.id={id})"
else:
txt = f"""
Title: {track.title}
Artist: {track.artist}
Path: {track.path}
Track ID: {track.id}
"""
txt = (
f"Title: {track.title}\n"
f"Artist: {track.artist}\n"
f"Path: {track.path}\n"
f"Track ID: {track.id}"
)
info = QMessageBox(self)
info.setIcon(QMessageBox.Information)
info.setText(txt)

View File

@ -7,7 +7,7 @@ import tempfile
from config import Config
from log import DEBUG, INFO
from model import Tracks, Playdates, PlaylistTracks, Session
from model import Notes, Playdates, PlaylistTracks, Session, Tracks
from mutagen.flac import FLAC
from mutagen.mp3 import MP3
from pydub import AudioSegment, effects
@ -255,23 +255,26 @@ def update_db(session):
db_paths = set(Tracks.get_all_paths(session))
# Remote any tracks from database whose paths don't exist
for path in list(db_paths - os_paths):
# Manage tracks listed in database but where path is invalid
track = Tracks.get_track_from_path(session, path)
DEBUG(f"songdb.update_db(): remove from database: {path=} {track=}")
played = Playdates.last_played(session, track)
playlists = PlaylistTracks.get_playlists_containing_track_id(
session, track.id)
if played:
INFO(
f"songdb.update_db: Can't remove {track.id=} ({track.path=}) "
f"as it's in playdates.id={played.id}"
)
elif playlists:
INFO(
f"songdb.update_db: Can't remove {track.id=} ({track.path=} "
f"as it's in playlists {[p.name for p in playlists]}"
)
else:
Tracks.remove_path(session, path)
# Remove references from Playdates
Playdates.remove_track(session, track.id)
# Replace playlist entries with a note
note_txt = (
f"File removed: {track.title=}, {track.artist=}, "
f"{track.path=}"
)
for pt in PlaylistTracks.get_track_playlists(session, track.id):
# Create note
Notes.add_note(session, pt.playlist_id, pt.row, note_txt)
# Remove playlist entry
PlaylistTracks.remove_track(session, pt.playlist_id, pt.row)
# Remove Track entry pointing to invalid path
Tracks.remove_path(session, path)
if __name__ == '__main__' and '__file__' in globals():