Code review for V1.0.0

This commit is contained in:
Keith Edmunds 2021-04-09 23:21:42 +01:00
parent eff7d0aca9
commit ee0bfceeae
7 changed files with 70 additions and 65 deletions

View File

@ -1,6 +1,3 @@
from log import DEBUG
def ms_to_mmss(ms, decimals=0, negative=False): def ms_to_mmss(ms, decimals=0, negative=False):
if not ms: if not ms:
return "-" return "-"
@ -13,7 +10,10 @@ def ms_to_mmss(ms, decimals=0, negative=False):
minutes, remainder = divmod(ms, 60 * 1000) minutes, remainder = divmod(ms, 60 * 1000)
seconds = remainder / 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}" return f"{sign}{minutes:.0f}:{seconds:02.{decimals}f}"

View File

@ -61,7 +61,7 @@ def DEBUG(msg):
def EXCEPTION(msg): def EXCEPTION(msg):
log.exception(msg) log.exception(msg, exc_info=True, stack_info=True)
def ERROR(msg): def ERROR(msg):

View File

@ -22,7 +22,6 @@ from log import DEBUG, ERROR, INFO
# https://docs.sqlalchemy.org/en/13/orm/session_basics.html # https://docs.sqlalchemy.org/en/13/orm/session_basics.html
# Set up database connection # Set up database connection
INFO("Connect to database")
engine = sqlalchemy.create_engine(f"{Config.MYSQL_CONNECT}?charset=utf8", engine = sqlalchemy.create_engine(f"{Config.MYSQL_CONNECT}?charset=utf8",
encoding='utf-8', encoding='utf-8',
echo=Config.DISPLAY_SQL, echo=Config.DISPLAY_SQL,

View File

@ -5,7 +5,7 @@ import vlc
from config import Config from config import Config
from time import sleep from time import sleep
from log import DEBUG from log import DEBUG, ERROR
class Music: class Music:
@ -70,13 +70,14 @@ class Music:
""" """
Start playing the track at path. Start playing the track at path.
Raise AttributeError if path not found. Log and return if path not found.
""" """
DEBUG(f"play({path})") DEBUG(f"play({path})")
if not os.access(path, os.R_OK): 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 self.track_path = path

View File

@ -1,11 +1,10 @@
#!/usr/bin/python3 #!/usr/bin/python3
import sys import sys
import music
from datetime import datetime, timedelta from datetime import datetime, timedelta
# from log import DEBUG from log import EXCEPTION
from PyQt5.QtCore import QTimer from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
@ -30,9 +29,7 @@ class Window(QMainWindow, Ui_MainWindow):
self.setupUi(self) self.setupUi(self)
self.timer = QTimer() self.timer = QTimer()
self.even_tick = True self.even_tick = True
self.music = music.Music()
self.playing = False self.playing = False
self.playlist.music = self.music
self.connect_signals_slots() self.connect_signals_slots()
self.disable_play_next_controls() self.disable_play_next_controls()
@ -46,6 +43,8 @@ class Window(QMainWindow, Ui_MainWindow):
height = record.f_int or 981 height = record.f_int or 981
self.setGeometry(x, y, width, height) self.setGeometry(x, y, width, height)
self.playlist.set_column_widths()
# Hard code to the first playlist for now # Hard code to the first playlist for now
# TODO # TODO
if self.playlist.load_playlist(1): if self.playlist.load_playlist(1):
@ -84,16 +83,13 @@ class Window(QMainWindow, Ui_MainWindow):
if dlg.exec_(): if dlg.exec_():
for fname in dlg.selectedFiles(): for fname in dlg.selectedFiles():
track = add_path_to_db(fname) track = add_path_to_db(fname)
self.playlist.add_to_playlist(track)
self.playlist.add_to_playlist(track)
def clear_selection(self):
self.playlist.clearSelection()
def connect_signals_slots(self): def connect_signals_slots(self):
self.actionAdd_file.triggered.connect(self.add_file) self.actionAdd_file.triggered.connect(self.add_file)
self.action_Clear_selection.triggered.connect(self.clear_selection) self.action_Clear_selection.triggered.connect(
self.actionFade.triggered.connect(self.fade) self.playlist.clearSelection)
self.actionFade.triggered.connect(self.playlist.fade)
self.actionNewPlaylist.triggered.connect(self.create_playlist) self.actionNewPlaylist.triggered.connect(self.create_playlist)
self.actionPlay_next.triggered.connect(self.play_next) self.actionPlay_next.triggered.connect(self.play_next)
self.actionSearch_database.triggered.connect(self.search_database) 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.btnSearchDatabase.clicked.connect(self.search_database)
self.btnSetNextTrack.clicked.connect(self.set_next_track) self.btnSetNextTrack.clicked.connect(self.set_next_track)
self.btnSkipNext.clicked.connect(self.play_next) 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) self.timer.timeout.connect(self.tick)
@ -126,9 +122,6 @@ class Window(QMainWindow, Ui_MainWindow):
def enable_play_next_controls(self): def enable_play_next_controls(self):
self.actionPlay_next.setEnabled(True) self.actionPlay_next.setEnabled(True)
def fade(self):
self.playlist.fade()
def insert_note(self): def insert_note(self):
"Add non-track row to playlist" "Add non-track row to playlist"
@ -152,7 +145,8 @@ class Window(QMainWindow, Ui_MainWindow):
silence_time = now + timedelta(milliseconds=silence_at) silence_time = now + timedelta(milliseconds=silence_at)
self.label_silent_tod.setText(silence_time.strftime("%H:%M:%S")) self.label_silent_tod.setText(silence_time.strftime("%H:%M:%S"))
self.label_fade_length.setText(helpers.ms_to_mmss( 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): def play_previous(self):
"Resume playing last track" "Resume playing last track"
@ -192,9 +186,9 @@ class Window(QMainWindow, Ui_MainWindow):
if not self.even_tick: if not self.even_tick:
return return
if self.music.playing(): if self.playlist.music.playing():
self.playing = True 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_fade = (self.playlist.get_current_fade_at() - playtime)
time_to_silence = ( time_to_silence = (
self.playlist.get_current_silence_at() - playtime self.playlist.get_current_silence_at() - playtime
@ -262,10 +256,13 @@ class Window(QMainWindow, Ui_MainWindow):
def main(): def main():
app = QApplication(sys.argv) try:
win = Window() app = QApplication(sys.argv)
win.show() win = Window()
sys.exit(app.exec()) win.show()
sys.exit(app.exec())
except Exception:
EXCEPTION("Unhandled Exception caught by musicmuster.main()")
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -16,6 +16,7 @@ from PyQt5.QtWidgets import (
) )
import helpers import helpers
import music
from config import Config from config import Config
from datetime import datetime, timedelta from datetime import datetime, timedelta
@ -60,6 +61,7 @@ class Playlist(QTableWidget):
self.customContextMenuRequested.connect(self.context_menu) self.customContextMenuRequested.connect(self.context_menu)
self.viewport().installEventFilter(self) self.viewport().installEventFilter(self)
self.music = music.Music()
self.current_track = None self.current_track = None
self.next_track = None self.next_track = None
self.playlist_name = None self.playlist_name = None
@ -68,13 +70,6 @@ class Playlist(QTableWidget):
self.previous_track_position = None self.previous_track_position = None
self.played_tracks = [] 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): def __del__(self):
"Save column widths" "Save column widths"
@ -86,6 +81,8 @@ class Playlist(QTableWidget):
record.update({'f_int': width}) record.update({'f_int': width})
def eventFilter(self, source, event): def eventFilter(self, source, event):
"Used to process context (right-click) menu"
if(event.type() == QtCore.QEvent.MouseButtonPress and # noqa W504 if(event.type() == QtCore.QEvent.MouseButtonPress and # noqa W504
event.buttons() == QtCore.Qt.RightButton and # noqa W504 event.buttons() == QtCore.Qt.RightButton and # noqa W504
source is self.viewport()): source is self.viewport()):
@ -146,15 +143,15 @@ class Playlist(QTableWidget):
playlist. playlist.
""" """
DEBUG(f"add_note({text})") DEBUG(f"add_note({text}): self.currentRow()={self.currentRow()}")
DEBUG(f"self.currentRow()={self.currentRow()}")
row = self.currentRow() row = self.currentRow()
if row < 0: if row < 0:
row = self.rowCount() row = self.rowCount()
DEBUG(f"row={row}") DEBUG(f"row={row}")
note_id = Notes.add_note(self.playlist_id, row, text) note_id = Notes.add_note(self.playlist_id, row, text)
# TODO: this largely duplicates what's in add_to_playlist()
self.insertRow(row) self.insertRow(row)
item = QTableWidgetItem(str(note_id)) item = QTableWidgetItem(str(note_id))
self.setItem(row, self.COL_INDEX, item) self.setItem(row, self.COL_INDEX, item)
@ -172,9 +169,12 @@ class Playlist(QTableWidget):
Notes object. Notes object.
""" """
row = self.rowCount() row = self.currentRow()
if row < 0:
row = self.rowCount()
DEBUG(f"row={row}")
self.insertRow(row) self.insertRow(row)
DEBUG(f"Adding to row {row}")
if isinstance(data, Tracks): if isinstance(data, Tracks):
track = data track = data
item = QTableWidgetItem(str(track.id)) item = QTableWidgetItem(str(track.id))
@ -501,7 +501,7 @@ class Playlist(QTableWidget):
# Update metadata # Update metadata
self.meta_set_current(self.meta_get_next()) self.meta_set_current(self.meta_get_next())
# Set track start time # Set track end time
current_row = self.meta_get_current() current_row = self.meta_get_current()
endtime = datetime.now() + timedelta( endtime = datetime.now() + timedelta(
milliseconds=self.current_track.silence_at) milliseconds=self.current_track.silence_at)
@ -582,20 +582,19 @@ class Playlist(QTableWidget):
# Set colours and start times # Set colours and start times
running_end_time = None 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()): for row in range(self.rowCount()):
if row == next:
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:
self.set_row_colour( self.set_row_colour(
row, QColor(Config.COLOUR_NEXT_PLAYLIST) row, QColor(Config.COLOUR_NEXT_PLAYLIST)
) )
@ -709,9 +708,20 @@ class Playlist(QTableWidget):
old_row=db_tracks[id], new_row=tracks[id] 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 = QFont()
bold.setBold(True) bold.setBold(bold)
for j in range(self.columnCount()): for j in range(self.columnCount()):
if self.item(row, j): if self.item(row, j):
self.item(row, j).setFont(bold) self.item(row, j).setFont(bold)
@ -722,11 +732,7 @@ class Playlist(QTableWidget):
self.item(row, j).setBackground(colour) self.item(row, j).setBackground(colour)
def set_row_not_bold(self, row): def set_row_not_bold(self, row):
normal = QFont() self.set_row_bold(row, False)
normal.setBold(False)
for j in range(self.columnCount()):
if self.item(row, j):
self.item(row, j).setFont(normal)
def tracks_changed(self): def tracks_changed(self):
""" """

View File

@ -132,10 +132,12 @@ def update_db():
os_paths = set(os_paths_list) os_paths = set(os_paths_list)
for path in list(db_paths - os_paths): for path in list(db_paths - os_paths):
# TODO
INFO(f"To remove from database: {path}") INFO(f"To remove from database: {path}")
for path in list(os_paths - db_paths): 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) add_path_to_db(path)