From ee0bfceeae57b97c39bdf4179f4eb2df0279902b Mon Sep 17 00:00:00 2001 From: Keith Edmunds Date: Fri, 9 Apr 2021 23:21:42 +0100 Subject: [PATCH] Code review for V1.0.0 --- app/helpers.py | 10 +++---- app/log.py | 2 +- app/model.py | 1 - app/music.py | 7 +++-- app/musicmuster.py | 41 +++++++++++++-------------- app/playlists.py | 70 +++++++++++++++++++++++++--------------------- app/songdb.py | 4 ++- 7 files changed, 70 insertions(+), 65 deletions(-) diff --git a/app/helpers.py b/app/helpers.py index 75469cf..9280648 100644 --- a/app/helpers.py +++ b/app/helpers.py @@ -1,6 +1,3 @@ -from log import DEBUG - - def ms_to_mmss(ms, decimals=0, negative=False): if not ms: return "-" @@ -13,7 +10,10 @@ def ms_to_mmss(ms, decimals=0, negative=False): minutes, remainder = divmod(ms, 60 * 1000) seconds = remainder / 1000 - if int(seconds) == 60: - DEBUG(f"ms_to_mmss({ms}) gave 60 seconds") + + # if seconds >= 59.5, it will be represented as 60, which looks odd. + # So, fake it under those circumstances + if seconds >= 59.5: + seconds = 59.0 return f"{sign}{minutes:.0f}:{seconds:02.{decimals}f}" diff --git a/app/log.py b/app/log.py index d56a11a..55cb845 100644 --- a/app/log.py +++ b/app/log.py @@ -61,7 +61,7 @@ def DEBUG(msg): def EXCEPTION(msg): - log.exception(msg) + log.exception(msg, exc_info=True, stack_info=True) def ERROR(msg): diff --git a/app/model.py b/app/model.py index bdd60b9..2171120 100644 --- a/app/model.py +++ b/app/model.py @@ -22,7 +22,6 @@ from log import DEBUG, ERROR, INFO # https://docs.sqlalchemy.org/en/13/orm/session_basics.html # Set up database connection -INFO("Connect to database") engine = sqlalchemy.create_engine(f"{Config.MYSQL_CONNECT}?charset=utf8", encoding='utf-8', echo=Config.DISPLAY_SQL, diff --git a/app/music.py b/app/music.py index 92f2b29..e2a1108 100644 --- a/app/music.py +++ b/app/music.py @@ -5,7 +5,7 @@ import vlc from config import Config from time import sleep -from log import DEBUG +from log import DEBUG, ERROR class Music: @@ -70,13 +70,14 @@ class Music: """ Start playing the track at path. - Raise AttributeError if path not found. + Log and return if path not found. """ DEBUG(f"play({path})") if not os.access(path, os.R_OK): - raise AttributeError(f"Cannot access {path}") + ERROR(f"play({path}): path not found") + return self.track_path = path diff --git a/app/musicmuster.py b/app/musicmuster.py index 67a7da1..37c725a 100755 --- a/app/musicmuster.py +++ b/app/musicmuster.py @@ -1,11 +1,10 @@ #!/usr/bin/python3 import sys -import music from datetime import datetime, timedelta -# from log import DEBUG +from log import EXCEPTION from PyQt5.QtCore import QTimer from PyQt5.QtWidgets import ( @@ -30,9 +29,7 @@ class Window(QMainWindow, Ui_MainWindow): self.setupUi(self) self.timer = QTimer() self.even_tick = True - self.music = music.Music() self.playing = False - self.playlist.music = self.music self.connect_signals_slots() self.disable_play_next_controls() @@ -46,6 +43,8 @@ class Window(QMainWindow, Ui_MainWindow): height = record.f_int or 981 self.setGeometry(x, y, width, height) + self.playlist.set_column_widths() + # Hard code to the first playlist for now # TODO if self.playlist.load_playlist(1): @@ -84,16 +83,13 @@ class Window(QMainWindow, Ui_MainWindow): if dlg.exec_(): for fname in dlg.selectedFiles(): track = add_path_to_db(fname) - - self.playlist.add_to_playlist(track) - - def clear_selection(self): - self.playlist.clearSelection() + self.playlist.add_to_playlist(track) def connect_signals_slots(self): self.actionAdd_file.triggered.connect(self.add_file) - self.action_Clear_selection.triggered.connect(self.clear_selection) - self.actionFade.triggered.connect(self.fade) + self.action_Clear_selection.triggered.connect( + self.playlist.clearSelection) + self.actionFade.triggered.connect(self.playlist.fade) self.actionNewPlaylist.triggered.connect(self.create_playlist) self.actionPlay_next.triggered.connect(self.play_next) self.actionSearch_database.triggered.connect(self.search_database) @@ -105,7 +101,7 @@ class Window(QMainWindow, Ui_MainWindow): self.btnSearchDatabase.clicked.connect(self.search_database) self.btnSetNextTrack.clicked.connect(self.set_next_track) self.btnSkipNext.clicked.connect(self.play_next) - self.btnStop.clicked.connect(self.fade) + self.btnStop.clicked.connect(self.playlist.fade) self.timer.timeout.connect(self.tick) @@ -126,9 +122,6 @@ class Window(QMainWindow, Ui_MainWindow): def enable_play_next_controls(self): self.actionPlay_next.setEnabled(True) - def fade(self): - self.playlist.fade() - def insert_note(self): "Add non-track row to playlist" @@ -152,7 +145,8 @@ class Window(QMainWindow, Ui_MainWindow): silence_time = now + timedelta(milliseconds=silence_at) self.label_silent_tod.setText(silence_time.strftime("%H:%M:%S")) self.label_fade_length.setText(helpers.ms_to_mmss( - silence_at - self.playlist.get_current_fade_at())) + silence_at - self.playlist.get_current_fade_at() + )) def play_previous(self): "Resume playing last track" @@ -192,9 +186,9 @@ class Window(QMainWindow, Ui_MainWindow): if not self.even_tick: return - if self.music.playing(): + if self.playlist.music.playing(): self.playing = True - playtime = self.music.get_playtime() + playtime = self.playlist.music.get_playtime() time_to_fade = (self.playlist.get_current_fade_at() - playtime) time_to_silence = ( self.playlist.get_current_silence_at() - playtime @@ -262,10 +256,13 @@ class Window(QMainWindow, Ui_MainWindow): def main(): - app = QApplication(sys.argv) - win = Window() - win.show() - sys.exit(app.exec()) + try: + app = QApplication(sys.argv) + win = Window() + win.show() + sys.exit(app.exec()) + except Exception: + EXCEPTION("Unhandled Exception caught by musicmuster.main()") if __name__ == "__main__": diff --git a/app/playlists.py b/app/playlists.py index 6d4abc6..13932d7 100644 --- a/app/playlists.py +++ b/app/playlists.py @@ -16,6 +16,7 @@ from PyQt5.QtWidgets import ( ) import helpers +import music from config import Config from datetime import datetime, timedelta @@ -60,6 +61,7 @@ class Playlist(QTableWidget): self.customContextMenuRequested.connect(self.context_menu) self.viewport().installEventFilter(self) + self.music = music.Music() self.current_track = None self.next_track = None self.playlist_name = None @@ -68,13 +70,6 @@ class Playlist(QTableWidget): self.previous_track_position = None self.played_tracks = [] - # Column widths from settings - for column in range(self.columnCount()): - name = f"playlist_col_{str(column)}_width" - record = Settings.get_int(name) - if record.f_int is not None: - self.setColumnWidth(column, record.f_int) - def __del__(self): "Save column widths" @@ -86,6 +81,8 @@ class Playlist(QTableWidget): record.update({'f_int': width}) def eventFilter(self, source, event): + "Used to process context (right-click) menu" + if(event.type() == QtCore.QEvent.MouseButtonPress and # noqa W504 event.buttons() == QtCore.Qt.RightButton and # noqa W504 source is self.viewport()): @@ -146,15 +143,15 @@ class Playlist(QTableWidget): playlist. """ - DEBUG(f"add_note({text})") + DEBUG(f"add_note({text}): self.currentRow()={self.currentRow()}") - DEBUG(f"self.currentRow()={self.currentRow()}") row = self.currentRow() if row < 0: row = self.rowCount() DEBUG(f"row={row}") note_id = Notes.add_note(self.playlist_id, row, text) + # TODO: this largely duplicates what's in add_to_playlist() self.insertRow(row) item = QTableWidgetItem(str(note_id)) self.setItem(row, self.COL_INDEX, item) @@ -172,9 +169,12 @@ class Playlist(QTableWidget): Notes object. """ - row = self.rowCount() + row = self.currentRow() + if row < 0: + row = self.rowCount() + DEBUG(f"row={row}") self.insertRow(row) - DEBUG(f"Adding to row {row}") + if isinstance(data, Tracks): track = data item = QTableWidgetItem(str(track.id)) @@ -501,7 +501,7 @@ class Playlist(QTableWidget): # Update metadata self.meta_set_current(self.meta_get_next()) - # Set track start time + # Set track end time current_row = self.meta_get_current() endtime = datetime.now() + timedelta( milliseconds=self.current_track.silence_at) @@ -582,20 +582,19 @@ class Playlist(QTableWidget): # Set colours and start times running_end_time = None + if current: + self.set_row_colour( + current, QColor(Config.COLOUR_CURRENT_PLAYLIST) + ) + try: + running_end_time = datetime.strptime(self.item( + row, self.COL_ENDTIME).text(), "%H:%M:%S") + except AttributeError: + pass + self.set_row_bold(row) + for row in range(self.rowCount()): - - if row == current: - self.set_row_colour( - row, QColor(Config.COLOUR_CURRENT_PLAYLIST) - ) - try: - running_end_time = datetime.strptime(self.item( - row, self.COL_ENDTIME).text(), "%H:%M:%S") - except AttributeError: - pass - self.set_row_bold(row) - - elif row == next: + if row == next: self.set_row_colour( row, QColor(Config.COLOUR_NEXT_PLAYLIST) ) @@ -709,9 +708,20 @@ class Playlist(QTableWidget): old_row=db_tracks[id], new_row=tracks[id] ) - def set_row_bold(self, row): + def set_column_widths(self): + + # Column widths from settings + for column in range(self.columnCount()): + name = f"playlist_col_{str(column)}_width" + record = Settings.get_int(name) + DEBUG(f"column={column}, name={name}, record.f_int={record.f_int}") + if record.f_int is not None: + print("setting column width") + self.setColumnWidth(column, record.f_int) + + def set_row_bold(self, row, bold=True): bold = QFont() - bold.setBold(True) + bold.setBold(bold) for j in range(self.columnCount()): if self.item(row, j): self.item(row, j).setFont(bold) @@ -722,11 +732,7 @@ class Playlist(QTableWidget): self.item(row, j).setBackground(colour) def set_row_not_bold(self, row): - normal = QFont() - normal.setBold(False) - for j in range(self.columnCount()): - if self.item(row, j): - self.item(row, j).setFont(normal) + self.set_row_bold(row, False) def tracks_changed(self): """ diff --git a/app/songdb.py b/app/songdb.py index d09d478..84a03e9 100755 --- a/app/songdb.py +++ b/app/songdb.py @@ -132,10 +132,12 @@ def update_db(): os_paths = set(os_paths_list) for path in list(db_paths - os_paths): + # TODO INFO(f"To remove from database: {path}") for path in list(os_paths - db_paths): - INFO(f"Adding to datbase: {path}") + # TODO + INFO(f"Adding to dataabase: {path}") add_path_to_db(path)