Compare commits

...

3 Commits

Author SHA1 Message Date
Keith Edmunds
ad717aeb2c Fix error inserting note (and track?) above selected row 2021-06-02 08:27:45 +01:00
Keith Edmunds
4984ddec98 Use sessions correctly (fixes #5) 2021-06-02 08:26:54 +01:00
Keith Edmunds
caa13b6693 Update database when playlist closed. Fixes #8 2021-06-01 21:20:32 +01:00
4 changed files with 339 additions and 301 deletions

View File

@ -31,9 +31,8 @@ engine = sqlalchemy.create_engine(f"{Config.MYSQL_CONNECT}?charset=utf8",
Base = declarative_base()
Base.metadata.create_all(engine)
# Create a Session
# Create a Session factory
Session = sessionmaker(bind=engine)
session = Session()
# Database classes
@ -52,7 +51,7 @@ class Notes(Base):
)
@staticmethod
def add_note(playlist_id, row, text):
def add_note(session, playlist_id, row, text):
DEBUG(f"add_note(playlist_id={playlist_id}, row={row}, text={text})")
note = Notes()
note.playlist_id = playlist_id
@ -63,18 +62,19 @@ class Notes(Base):
return note
@staticmethod
def delete_note(id):
def delete_note(session, id):
DEBUG(f"delete_note(id={id}")
session.query(Notes).filter(Notes.id == id).delete()
session.commit()
@staticmethod
def get_note(id):
return session.query(Notes).filter(Notes.id == id).one()
# Not currently used 1 June 2021
# @staticmethod
# def get_note(session, id):
# return session.query(Notes).filter(Notes.id == id).one()
@classmethod
def update_note(cls, id, row, text=None):
def update_note(cls, session, id, row, text=None):
"""
Update note details. If text=None, don't change text.
"""
@ -97,7 +97,7 @@ class Playdates(Base):
tracks = relationship("Tracks", back_populates="playdates")
@staticmethod
def add_playdate(track):
def add_playdate(session, track):
DEBUG(f"add_playdate(track={track})")
pd = Playdates()
pd.lastplayed = datetime.now()
@ -167,7 +167,7 @@ class Playlists(Base):
return (f"<Playlist(id={self.id}, name={self.name}>")
@staticmethod
def new(name):
def new(session, name):
DEBUG(f"Playlists.new(name={name})")
playlist = Playlists()
playlist.name = name
@ -176,7 +176,7 @@ class Playlists(Base):
return playlist
@staticmethod
def open(plid):
def open(session, plid):
"Record playlist as loaded and used now"
p = session.query(Playlists).filter(Playlists.id == plid).one()
@ -186,14 +186,15 @@ class Playlists(Base):
return p
def close(self):
def close(self, session):
"Record playlist as no longer loaded"
self.loaded = False
session.add(self)
session.commit()
@staticmethod
def get_last_used():
def get_last_used(session):
"""
Return a list of playlists marked "loaded", ordered by loaded date.
"""
@ -205,13 +206,13 @@ class Playlists(Base):
).all()
@staticmethod
def get_all_playlists():
def get_all_playlists(session):
"Returns a list of all playlists"
return session.query(Playlists).all()
@staticmethod
def get_all_closed_playlists():
def get_all_closed_playlists(session):
"Returns a list of all playlists not currently open"
return (
@ -223,25 +224,26 @@ class Playlists(Base):
.order_by(Playlists.last_used.desc())
).all()
@staticmethod
def get_name(plid):
"""
Return name of playlist with id 'plid'
"""
# Not currently used 1 June 2021
# @staticmethod
# def get_name(session, plid):
# """
# Return name of playlist with id 'plid'
# """
return (
session.query(Playlists.name)
.filter(Playlists.id == plid)
).one()[0]
# return (
# session.query(Playlists.name)
# .filter(Playlists.id == plid)
# ).one()[0]
def add_track(self, track, row=None):
def add_track(self, session, track, row=None):
"""
Add track to playlist at given row.
If row=None, add to end of playlist
"""
if not row:
row = PlaylistTracks.new_row(self.id)
row = PlaylistTracks.new_row(session, self.id)
glue = PlaylistTracks(row=row)
glue.track_id = track.id
@ -265,14 +267,14 @@ class PlaylistTracks(Base):
playlists = relationship("Playlists", back_populates="tracks")
@staticmethod
def new_row(playlist_id):
def new_row(session, playlist_id):
"Return row number > largest existing row number"
last_row = session.query(func.max(PlaylistTracks.row)).one()[0]
return last_row + 1
@staticmethod
def add_track(playlist_id, track_id, row):
def add_track(session, playlist_id, track_id, row):
DEBUG(
f"PlaylistTracks.add_track(playlist_id={playlist_id}, "
f"track_id={track_id}, row={row})"
@ -285,7 +287,7 @@ class PlaylistTracks(Base):
session.commit()
@staticmethod
def move_track(from_playlist_id, row, to_playlist_id):
def move_track(session, from_playlist_id, row, to_playlist_id):
DEBUG(
"PlaylistTracks.move_tracks(from_playlist_id="
f"{from_playlist_id}, row={row}, "
@ -304,7 +306,7 @@ class PlaylistTracks(Base):
session.commit()
@staticmethod
def remove_track(playlist_id, row):
def remove_track(session, playlist_id, row):
DEBUG(
f"PlaylistTracks.remove_track(playlist_id={playlist_id}, "
f"row={row})"
@ -316,7 +318,7 @@ class PlaylistTracks(Base):
session.commit()
@staticmethod
def update_row_track(playlist_id, row, track_id):
def update_row_track(session, playlist_id, row, track_id):
DEBUG(
f"PlaylistTracks.update_track_row(playlist_id={playlist_id}, "
f"row={row}, track_id={track_id})"
@ -334,6 +336,13 @@ class PlaylistTracks(Base):
f"PlaylistTracks.row == {row}"
)
return
except NoResultFound:
ERROR(
f"No rows matched in query: "
f"PlaylistTracks.playlist_id == {playlist_id}, "
f"PlaylistTracks.row == {row}"
)
return
plt.track_id = track_id
session.commit()
@ -349,7 +358,7 @@ class Settings(Base):
f_string = Column(String(128), default=None, nullable=True)
@classmethod
def get_int(cls, name):
def get_int(cls, session, name):
try:
int_setting = session.query(cls).filter(
cls.name == name).one()
@ -361,7 +370,7 @@ class Settings(Base):
session.commit()
return int_setting
def update(self, data):
def update(self, session, data):
for key, value in data.items():
assert hasattr(self, key)
setattr(self, key, value)
@ -391,7 +400,7 @@ class Tracks(Base):
)
@classmethod
def get_or_create(cls, path):
def get_or_create(cls, session, path):
DEBUG(f"Tracks.get_or_create(path={path})")
try:
track = session.query(cls).filter(cls.path == path).one()
@ -402,7 +411,7 @@ class Tracks(Base):
return track
@staticmethod
def get_duration(id):
def get_duration(session, id):
try:
return session.query(
Tracks.duration).filter(Tracks.id == id).one()[0]
@ -411,19 +420,20 @@ class Tracks(Base):
return None
@staticmethod
def get_all_paths():
def get_all_paths(session):
"Return a list of paths of all tracks"
return [a[0] for a in session.query(Tracks.path).all()]
@classmethod
def get_all_tracks(cls):
"Return a list of all tracks"
# Not used as of 1 June 2021
# @classmethod
# def get_all_tracks(cls):
# "Return a list of all tracks"
return session.query(cls).all()
# return session.query(cls).all()
@staticmethod
def get_path(id):
def get_path(session, id):
try:
return session.query(Tracks.path).filter(Tracks.id == id).one()[0]
except NoResultFound:
@ -431,7 +441,7 @@ class Tracks(Base):
return None
@staticmethod
def get_track(id):
def get_track(session, id):
try:
DEBUG(f"Tracks.get_track(track_id={id})")
track = session.query(Tracks).filter(Tracks.id == id).one()
@ -441,7 +451,7 @@ class Tracks(Base):
return None
@staticmethod
def search_titles(text):
def search_titles(session, text):
return (
session.query(Tracks)
.filter(Tracks.title.ilike(f"%{text}%"))
@ -449,7 +459,7 @@ class Tracks(Base):
).all()
@staticmethod
def track_from_id(id):
def track_from_id(session, id):
return session.query(Tracks).filter(
Tracks.id == id).one()

View File

@ -25,7 +25,8 @@ import helpers
import music
from config import Config
from model import Notes, Playdates, Playlists, PlaylistTracks, Settings, Tracks
from model import (Notes, Playdates, Playlists, PlaylistTracks,
Session, Settings, Tracks)
from playlists import Playlist
from songdb import add_path_to_db
from ui.dlg_search_database_ui import Ui_Dialog
@ -70,19 +71,21 @@ class Window(QMainWindow, Ui_MainWindow):
dlg.setNameFilter("Music files (*.flac *.mp3)")
if dlg.exec_():
with Session() as session:
for fname in dlg.selectedFiles():
track = add_path_to_db(fname)
track = add_path_to_db(session, fname)
self.visible_playlist()._add_to_playlist(track)
def set_main_window_size(self):
record = Settings.get_int("mainwindow_x")
with Session() as session:
record = Settings.get_int(session, "mainwindow_x")
x = record.f_int or 1
record = Settings.get_int("mainwindow_y")
record = Settings.get_int(session, "mainwindow_y")
y = record.f_int or 1
record = Settings.get_int("mainwindow_width")
record = Settings.get_int(session, "mainwindow_width")
width = record.f_int or 1599
record = Settings.get_int("mainwindow_height")
record = Settings.get_int(session, "mainwindow_height")
height = record.f_int or 981
self.setGeometry(x, y, width, height)
@ -100,21 +103,22 @@ class Window(QMainWindow, Ui_MainWindow):
else:
DEBUG("closeEvent() accepted")
record = Settings.get_int("mainwindow_height")
with Session() as session:
record = Settings.get_int(session, "mainwindow_height")
if record.f_int != self.height():
record.update({'f_int': self.height()})
record.update(session, {'f_int': self.height()})
record = Settings.get_int("mainwindow_width")
record = Settings.get_int(session, "mainwindow_width")
if record.f_int != self.width():
record.update({'f_int': self.width()})
record.update(session, {'f_int': self.width()})
record = Settings.get_int("mainwindow_x")
record = Settings.get_int(session, "mainwindow_x")
if record.f_int != self.x():
record.update({'f_int': self.x()})
record.update(session, {'f_int': self.x()})
record = Settings.get_int("mainwindow_y")
record = Settings.get_int(session, "mainwindow_y")
if record.f_int != self.y():
record.update({'f_int': self.y()})
record.update(session, {'f_int': self.y()})
event.accept()
@ -159,8 +163,9 @@ class Window(QMainWindow, Ui_MainWindow):
dlg.resize(500, 100)
ok = dlg.exec()
if ok:
playlist = Playlists.new(dlg.textValue())
self.load_playlist(playlist)
with Session() as session:
playlist = Playlists.new(session, dlg.textValue())
self.load_playlist(session, playlist)
def change_volume(self, volume):
"Change player maximum volume"
@ -170,11 +175,12 @@ class Window(QMainWindow, Ui_MainWindow):
self.music.set_volume(volume)
def close_playlist(self):
self.visible_playlist().db.close()
with Session() as session:
self.visible_playlist().db.close(session)
index = self.tabPlaylist.currentIndex()
self.tabPlaylist.removeTab(index)
def create_note(self, text):
def create_note(self, session, text):
"""
Create note
@ -189,7 +195,10 @@ class Window(QMainWindow, Ui_MainWindow):
row = self.visible_playlist().rowCount()
DEBUG(f"musicmuster.create_note(text={text}): row={row}")
return Notes.add_note(self.visible_playlist().db.id, row, text)
note = Notes.add_note(
session, self.visible_playlist().db.id, row, text)
return note
def disable_play_next_controls(self):
DEBUG("disable_play_next_controls()")
@ -250,19 +259,21 @@ class Window(QMainWindow, Ui_MainWindow):
dlg.resize(500, 100)
ok = dlg.exec()
if ok:
note = self.create_note(dlg.textValue())
with Session() as session:
note = self.create_note(session, dlg.textValue())
self.visible_playlist().add_note(note)
def load_last_playlists(self):
"Load the playlists that we loaded at end of last session"
for playlist in Playlists.get_last_used():
with Session() as session:
for playlist in Playlists.get_last_used(session):
DEBUG(
f"load_last_playlists(), playlist.name={playlist.name}, "
f"playlist.id={playlist.id}")
self.load_playlist(playlist)
self.load_playlist(session, playlist)
def load_playlist(self, playlist_db):
def load_playlist(self, session, playlist_db):
"""
Take the passed database object, create a playlist display, attach
the database object, get it populated and then add tab.
@ -270,15 +281,17 @@ class Window(QMainWindow, Ui_MainWindow):
playlist_table = Playlist(self)
playlist_table.db = playlist_db
playlist_table.populate()
playlist_table.populate(session)
idx = self.tabPlaylist.addTab(playlist_table, playlist_db.name)
self.tabPlaylist.setCurrentIndex(idx)
def move_selected(self):
"Move selected rows to another playlist"
with Session() as session:
playlists = list(
set(Playlists.get_all_playlists()) - {self.visible_playlist().db}
set(Playlists.get_all_playlists(session)) -
{self.visible_playlist().db}
)
dlg = SelectPlaylistDialog(self, playlists=playlists)
dlg.exec()
@ -300,10 +313,11 @@ class Window(QMainWindow, Ui_MainWindow):
rows.append(row)
# Update database
PlaylistTracks.move_track(
self.visible_playlist().db.id, row, dlg.plid)
session, self.visible_playlist().db.id, row, dlg.plid)
# Update destination playlist if visible
if destination_playlist:
destination_playlist.add_track(Tracks.track_from_id(track_id))
destination_playlist.add_track(
session, Tracks.track_from_id(session, track_id))
# Update source playlist
self.visible_playlist().remove_rows(rows)
@ -334,6 +348,7 @@ class Window(QMainWindow, Ui_MainWindow):
f"{self.current_track.title if self.current_track else None}"
)
with Session() as session:
# Stop current track, if any
self.stop_playing()
@ -348,7 +363,7 @@ class Window(QMainWindow, Ui_MainWindow):
next_track_id = self.current_track_playlist.play_started()
if next_track_id is not None:
self.next_track = Tracks.get_track(next_track_id)
self.next_track = Tracks.get_track(session, next_track_id)
self.next_track_playlist = self.current_track_playlist
# Check we can read it
if not os.access(self.next_track.path, os.R_OK):
@ -360,7 +375,7 @@ class Window(QMainWindow, Ui_MainWindow):
# Tell database to record it as played
self.current_track.update_lastplayed()
Playdates.add_playdate(self.current_track)
Playdates.add_playdate(session, self.current_track)
self.disable_play_next_controls()
self.update_headers()
@ -386,12 +401,13 @@ class Window(QMainWindow, Ui_MainWindow):
dlg.exec()
def open_playlist(self):
playlists = Playlists.get_all_closed_playlists()
with Session() as session:
playlists = Playlists.get_all_closed_playlists(session)
dlg = SelectPlaylistDialog(self, playlists=playlists)
dlg.exec()
if dlg.plid:
playlist = Playlists.open(dlg.plid)
self.load_playlist(playlist)
playlist = Playlists.open(session, dlg.plid)
self.load_playlist(session, playlist)
def select_next_track(self):
"Select next or first track in playlist"
@ -406,6 +422,7 @@ class Window(QMainWindow, Ui_MainWindow):
def set_next_track(self, next_track_id=None):
"Set selected track as next"
with Session() as session:
if not next_track_id:
next_track_id = self.visible_playlist().set_selected_as_next()
if next_track_id:
@ -413,7 +430,7 @@ class Window(QMainWindow, Ui_MainWindow):
if self.next_track_playlist:
self.next_track_playlist.clear_next()
self.next_track_playlist = self.visible_playlist()
self.next_track = Tracks.get_track(next_track_id)
self.next_track = Tracks.get_track(session, next_track_id)
self.update_headers()
def show_warning(self, title, msg):
@ -605,6 +622,7 @@ class Window(QMainWindow, Ui_MainWindow):
class DbDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.session = Session()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.searchString.textEdited.connect(self.chars_typed)
@ -614,20 +632,20 @@ class DbDialog(QDialog):
self.ui.btnClose.clicked.connect(self.close)
self.ui.matchList.itemSelectionChanged.connect(self.selection_changed)
record = Settings.get_int("dbdialog_width")
record = Settings.get_int(self.session, "dbdialog_width")
width = record.f_int or 800
record = Settings.get_int("dbdialog_height")
record = Settings.get_int(self.session, "dbdialog_height")
height = record.f_int or 600
self.resize(width, height)
def __del__(self):
record = Settings.get_int("dbdialog_height")
record = Settings.get_int(self.session, "dbdialog_height")
if record.f_int != self.height():
record.update({'f_int': self.height()})
record.update(self.session, {'f_int': self.height()})
record = Settings.get_int("dbdialog_width")
record = Settings.get_int(self.session, "dbdialog_width")
if record.f_int != self.width():
record.update({'f_int': self.width()})
record.update(self.session, {'f_int': self.width()})
def add_selected(self):
if not self.ui.matchList.selectedItems():
@ -643,7 +661,7 @@ class DbDialog(QDialog):
def chars_typed(self, s):
if len(s) >= 3:
matches = Tracks.search_titles(s)
matches = Tracks.search_titles(self.session, s)
self.ui.matchList.clear()
if matches:
for track in matches:
@ -662,7 +680,7 @@ class DbDialog(QDialog):
self.select_searchtext()
def add_track(self, track_id):
track = Tracks.track_from_id(track_id)
track = Tracks.track_from_id(self.session, track_id)
self.parent().visible_playlist()._add_to_playlist(track)
# Select search text to make it easier for next search
self.select_searchtext()
@ -677,7 +695,7 @@ class DbDialog(QDialog):
item = self.ui.matchList.currentItem()
track_id = item.data(Qt.UserRole)
self.ui.dbPath.setText(Tracks.get_path(track_id))
self.ui.dbPath.setText(Tracks.get_path(self.session, track_id))
class SelectPlaylistDialog(QDialog):
@ -693,9 +711,10 @@ class SelectPlaylistDialog(QDialog):
self.ui.buttonBox.rejected.connect(self.close)
self.plid = None
record = Settings.get_int("select_playlist_dialog_width")
with Session() as session:
record = Settings.get_int(session, "select_playlist_dialog_width")
width = record.f_int or 800
record = Settings.get_int("select_playlist_dialog_height")
record = Settings.get_int(session, "select_playlist_dialog_height")
height = record.f_int or 600
self.resize(width, height)
@ -706,13 +725,14 @@ class SelectPlaylistDialog(QDialog):
self.ui.lstPlaylists.addItem(p)
def __del__(self):
record = Settings.get_int("select_playlist_dialog_height")
with Session() as session:
record = Settings.get_int(session, "select_playlist_dialog_height")
if record.f_int != self.height():
record.update({'f_int': self.height()})
record.update(session, {'f_int': self.height()})
record = Settings.get_int("select_playlist_dialog_width")
record = Settings.get_int(session, "select_playlist_dialog_width")
if record.f_int != self.width():
record.update({'f_int': self.width()})
record.update(session, {'f_int': self.width()})
def list_doubleclick(self, entry):
self.plid = entry.data(Qt.UserRole)

View File

@ -17,7 +17,7 @@ import os
from config import Config
from datetime import datetime, timedelta
from log import DEBUG, ERROR
from model import Notes, PlaylistTracks, Settings, Tracks
from model import Notes, PlaylistTracks, Session, Settings, Tracks
class Playlist(QTableWidget):
@ -94,9 +94,10 @@ class Playlist(QTableWidget):
for column in range(self.columnCount()):
width = self.columnWidth(column)
name = f"playlist_col_{str(column)}_width"
record = Settings.get_int(name)
with Session() as session:
record = Settings.get_int(session, name)
if record.f_int != self.columnWidth(column):
record.update({'f_int': width})
record.update(session, {'f_int': width})
event.accept()
@ -275,7 +276,7 @@ class Playlist(QTableWidget):
if not self.selectionModel().hasSelection():
return None
else:
return self.selectionModel().selectedRows()[0]
return self.selectionModel().selectedRows()[0].row()
def get_selected_rows_and_tracks(self):
"Return a list of selected (rows, track_id) tuples"
@ -336,7 +337,7 @@ class Playlist(QTableWidget):
self.current_track_start_time = None
self._repaint(save_playlist=False)
def populate(self):
def populate(self, session):
# add them in row order. We don't mandate that an item will be
# on its specified row, only that it will be above
# larger-numbered row items, and below lower-numbered ones.
@ -454,7 +455,7 @@ class Playlist(QTableWidget):
elif isinstance(data, Notes):
self.add_note(data, repaint=repaint)
def _calculate_next_start_time(self, row, start):
def _calculate_next_start_time(self, session, row, start):
"Return this row's end time given its start time"
if start is None:
@ -463,7 +464,7 @@ class Playlist(QTableWidget):
DEBUG("_calculate_next_start_time() called with row=None")
return None
duration = Tracks.get_duration(self._get_row_id(row))
duration = Tracks.get_duration(session, self._get_row_id(row))
return start + timedelta(milliseconds=duration)
def _can_read_track(self, track):
@ -499,11 +500,12 @@ class Playlist(QTableWidget):
msg.setDefaultButton(QMessageBox.Cancel)
msg.setWindowTitle("Delete row")
if msg.exec() == QMessageBox.Yes:
with Session() as session:
id = self._get_row_id(row)
if row in self._meta_get_notes():
Notes.delete_note(id)
Notes.delete_note(session, id)
else:
PlaylistTracks.remove_track(self.db.id, row)
PlaylistTracks.remove_track(session, self.db.id, row)
self.removeRow(row)
self._repaint()
@ -723,10 +725,11 @@ class Playlist(QTableWidget):
f"save_playlist={save_playlist})"
)
with Session() as session:
if clear_selection:
self.clearSelection()
if save_playlist:
self._save_playlist()
self._save_playlist(session)
current = self._meta_get_current()
next = self._meta_get_next()
@ -756,7 +759,7 @@ class Playlist(QTableWidget):
self._set_row_time(row, self.current_track_start_time)
# Calculate next_start_time
next_start_time = self._calculate_next_start_time(
row, self.current_track_start_time)
session, row, self.current_track_start_time)
# Set colour
self._set_row_colour(row, QColor(
Config.COLOUR_CURRENT_PLAYLIST))
@ -764,10 +767,10 @@ class Playlist(QTableWidget):
self._set_row_bold(row)
elif row == next:
# if there's a current track playing, set start time from that
# if there's a track playing, set start time from that
if self.current_track_start_time:
start_time = self._calculate_next_start_time(
current, self.current_track_start_time)
session, current, self.current_track_start_time)
else:
# No current track to base from, but don't change
# time if it's already set
@ -777,9 +780,10 @@ class Playlist(QTableWidget):
# Now set it
self._set_row_time(row, start_time)
next_start_time = self._calculate_next_start_time(
row, start_time)
session, row, start_time)
# Set colour
self._set_row_colour(row, QColor(Config.COLOUR_NEXT_PLAYLIST))
self._set_row_colour(
row, QColor(Config.COLOUR_NEXT_PLAYLIST))
# Make bold
self._set_row_bold(row)
@ -798,11 +802,11 @@ class Playlist(QTableWidget):
if next_start_time:
self._set_row_time(row, next_start_time)
next_start_time = self._calculate_next_start_time(
row, next_start_time)
session, row, next_start_time)
# Don't dim unplayed tracks
self._set_row_bold(row)
def _save_playlist(self):
def _save_playlist(self, session):
"""
Save playlist to database. We do this by correcting differences
between the on-screen (definitive) playlist and that in the
@ -846,7 +850,7 @@ class Playlist(QTableWidget):
f"_save_playlist(): Delete note note_id={note_id} "
f"from playlist {self} in database"
)
Notes.delete_note(note_id)
Notes.delete_note(session, note_id)
# Note rows to update in playlist database
for note_id in set(playlist_notes.keys()) & set(database_notes.keys()):
@ -856,7 +860,7 @@ class Playlist(QTableWidget):
f"from row={database_notes[note_id]} to "
f"row={playlist_notes[note_id]}"
)
Notes.update_note(note_id, playlist_notes[note_id])
Notes.update_note(session, note_id, playlist_notes[note_id])
# Now check tracks
# Create dictionaries indexed by row
@ -878,7 +882,8 @@ class Playlist(QTableWidget):
set(set(playlist_tracks.keys()) - set(database_tracks.keys()))
):
DEBUG(f"_save_playlist(): row {row} missing from database")
PlaylistTracks.add_track(self.db.id, playlist_tracks[row], row)
PlaylistTracks.add_track(session, self.db.id,
playlist_tracks[row], row)
# Track rows to remove from database
for row in (
@ -889,7 +894,7 @@ class Playlist(QTableWidget):
f"_save_playlist(): row {row} in database not playlist "
f"(track={track})"
)
PlaylistTracks.remove_track(self.db.id, row)
PlaylistTracks.remove_track(session, self.db.id, row)
# Track rows to update in database
for row in (
@ -902,18 +907,19 @@ class Playlist(QTableWidget):
f"to track={playlist_tracks[row]}"
)
PlaylistTracks.update_row_track(
self.db.id, row, playlist_tracks[row])
session, self.db.id, row, playlist_tracks[row])
def _set_column_widths(self):
# Column widths from settings
with Session() as session:
for column in range(self.columnCount()):
# Only show column 0 in test mode
if (column == 0 and not Config.TESTMODE):
self.setColumnWidth(0, 0)
else:
name = f"playlist_col_{str(column)}_width"
record = Settings.get_int(name)
record = Settings.get_int(session, name)
if record.f_int is not None:
self.setColumnWidth(column, record.f_int)

View File

@ -7,7 +7,7 @@ import tempfile
from config import Config
from log import DEBUG, INFO
from model import Tracks, session
from model import Tracks, Session
from mutagen.flac import FLAC
from pydub import AudioSegment, effects
from tinytag import TinyTag
@ -28,15 +28,16 @@ def main():
# Run as required
if args.update:
INFO("Updating database")
update_db()
with Session() as session:
update_db(session)
INFO("Finished")
def add_path_to_db(path):
def add_path_to_db(session, path):
"Add passed path to database along with metadata"
track = Tracks.get_or_create(path)
track = Tracks.get_or_create(session, path)
tag = TinyTag.get(path)
audio = get_audio_segment(path)
@ -143,19 +144,20 @@ def fade_point(audio_segment, fade_threshold=Config.DBFS_FADE,
return int(trim_ms)
def rescan_database():
tracks = Tracks.get_all_tracks()
total_tracks = len(tracks)
track_count = 0
for track in tracks:
track_count += 1
print(f"Track {track_count} of {total_tracks}")
audio = get_audio_segment(track.path)
track.start_gap = leading_silence(audio)
track.fade_at = fade_point(audio)
track.silence_at = trailing_silence(audio)
session.commit()
# Current unused (1 June 2021)
# def rescan_database(session):
#
# tracks = Tracks.get_all_tracks(session)
# total_tracks = len(tracks)
# track_count = 0
# for track in tracks:
# track_count += 1
# print(f"Track {track_count} of {total_tracks}")
# audio = get_audio_segment(track.path)
# track.start_gap = leading_silence(audio)
# track.fade_at = fade_point(audio)
# track.silence_at = trailing_silence(audio)
# session.commit()
def trailing_silence(audio_segment, silence_threshold=-50.0,
@ -163,14 +165,14 @@ def trailing_silence(audio_segment, silence_threshold=-50.0,
return fade_point(audio_segment, silence_threshold, chunk_size)
def update_db():
def update_db(session):
"""
Repopulate database
"""
# Search for tracks in only one of directory and database
db_paths = set(Tracks.get_all_paths())
db_paths = set(Tracks.get_all_paths(session))
os_paths_list = []
for root, dirs, files in os.walk(Config.ROOT):
@ -188,7 +190,7 @@ def update_db():
for path in list(os_paths - db_paths):
# TODO
INFO(f"Adding to dataabase: {path}")
add_path_to_db(path)
add_path_to_db(session, path)
if __name__ == '__main__' and '__file__' in globals():