Code review for V1.0.0
This commit is contained in:
parent
eff7d0aca9
commit
ee0bfceeae
@ -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}"
|
||||||
|
|||||||
@ -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):
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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__":
|
||||||
|
|||||||
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user