Headers, timer colours, all looking good
This commit is contained in:
parent
ba9b9cc936
commit
233cce7800
@ -7,11 +7,13 @@ class Config(object):
|
||||
COLOUR_CURRENT_HEADER = "#d4edda"
|
||||
COLOUR_CURRENT_PLAYLIST = "#28a745"
|
||||
COLOUR_ODD_PLAYLIST = "#f2f2f2"
|
||||
COLOUR_ENDING_TIMER = "#dc3545"
|
||||
COLOUR_EVEN_PLAYLIST = "#d9d9d9"
|
||||
COLOUR_NEXT_HEADER = "#fff3cd"
|
||||
COLOUR_NEXT_PLAYLIST = "#ffc107"
|
||||
COLOUR_NOTES_PLAYLIST = "#802020"
|
||||
COLOUR_NOTES_PLAYLIST = "#dc3545"
|
||||
COLOUR_PREVIOUS_HEADER = "#f8d7da"
|
||||
COLOUR_WARNING_TIMER = "#ffc107"
|
||||
DBFS_FADE = -12
|
||||
DBFS_SILENCE = -50
|
||||
DISPLAY_SQL = False
|
||||
|
||||
@ -22,7 +22,7 @@ class Music:
|
||||
"""
|
||||
Fade the currently playing track.
|
||||
|
||||
Return the current track path and position.
|
||||
Return the current track position.
|
||||
|
||||
The actual management of fading runs in its own thread so as not
|
||||
to hold up the UI during the fade.
|
||||
@ -31,15 +31,14 @@ class Music:
|
||||
DEBUG("fade()")
|
||||
|
||||
if not self.playing():
|
||||
return (None, None)
|
||||
return None
|
||||
|
||||
path = self.track_path
|
||||
position = self.player.get_position()
|
||||
|
||||
thread = threading.Thread(target=self._fade)
|
||||
thread.start()
|
||||
|
||||
return (path, position)
|
||||
return position
|
||||
|
||||
def _fade(self):
|
||||
"""
|
||||
|
||||
@ -31,6 +31,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
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()
|
||||
@ -47,6 +48,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
|
||||
# Hard code to the only playlist we have for now
|
||||
if self.playlist.load_playlist("Default"):
|
||||
self.update_headers()
|
||||
self.enable_play_next_controls()
|
||||
self.timer.start(Config.TIMER_MS)
|
||||
|
||||
@ -91,7 +93,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
self.actionSearch_database.triggered.connect(self.search_database)
|
||||
self.btnPrevious.clicked.connect(self.play_previous)
|
||||
self.btnSearchDatabase.clicked.connect(self.search_database)
|
||||
self.btnSetNextTrack.clicked.connect(self.playlist.set_next_track)
|
||||
self.btnSetNextTrack.clicked.connect(self.set_next_track)
|
||||
self.btnSkipNext.clicked.connect(self.play_next)
|
||||
self.btnStop.clicked.connect(self.fade)
|
||||
|
||||
@ -109,18 +111,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
def play_next(self):
|
||||
self.playlist.play_next()
|
||||
self.disable_play_next_controls()
|
||||
self.previous_track.setText(
|
||||
f"{self.playlist.get_previous_title()} - "
|
||||
f"{self.playlist.get_previous_artist()}"
|
||||
)
|
||||
self.current_track.setText(
|
||||
f"{self.playlist.get_current_title()} - "
|
||||
f"{self.playlist.get_current_artist()}"
|
||||
)
|
||||
self.next_track.setText(
|
||||
f"{self.playlist.get_next_title()} - "
|
||||
f"{self.playlist.get_next_artist()}"
|
||||
)
|
||||
self.update_headers()
|
||||
|
||||
# Set time clocks
|
||||
now = datetime.now()
|
||||
@ -142,8 +133,10 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
dlg.exec()
|
||||
|
||||
def set_next_track(self):
|
||||
# TODO
|
||||
pass
|
||||
"Set selected track as next"
|
||||
|
||||
self.playlist.set_selected_as_next()
|
||||
self.update_headers()
|
||||
|
||||
def tick(self):
|
||||
"""
|
||||
@ -166,28 +159,69 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
return
|
||||
|
||||
if self.music.playing():
|
||||
self.playing = True
|
||||
playtime = self.music.get_playtime()
|
||||
self.label_elapsed_timer.setText(helpers.ms_to_mmss(playtime))
|
||||
self.label_fade_timer.setText(
|
||||
helpers.ms_to_mmss(
|
||||
self.playlist.get_current_fade_at() - playtime)
|
||||
)
|
||||
time_to_fade = (self.playlist.get_current_fade_at() - playtime)
|
||||
time_to_silence = (
|
||||
self.playlist.get_current_silence_at() - playtime
|
||||
)
|
||||
if time_to_silence < 500:
|
||||
self.label_silent_timer.setText("00:00")
|
||||
time_to_end = (self.playlist.get_current_duration() - playtime)
|
||||
|
||||
# Elapsed time
|
||||
if time_to_end < 500:
|
||||
self.label_elapsed_timer.setText(
|
||||
helpers.ms_to_mmss(self.playlist.get_current_duration())
|
||||
)
|
||||
else:
|
||||
self.label_elapsed_timer.setText(helpers.ms_to_mmss(playtime))
|
||||
|
||||
# Time to fade
|
||||
self.label_fade_timer.setText(helpers.ms_to_mmss(time_to_fade))
|
||||
|
||||
# Time to silence
|
||||
if time_to_silence < 5000:
|
||||
self.frame_silent.setStyleSheet(
|
||||
f"background: {Config.COLOUR_ENDING_TIMER}"
|
||||
)
|
||||
self.enable_play_next_controls()
|
||||
elif time_to_fade < 500:
|
||||
self.frame_silent.setStyleSheet(
|
||||
f"background: {Config.COLOUR_WARNING_TIMER}"
|
||||
)
|
||||
self.enable_play_next_controls()
|
||||
else:
|
||||
self.frame_silent.setStyleSheet("")
|
||||
|
||||
self.label_silent_timer.setText(
|
||||
helpers.ms_to_mmss(time_to_silence)
|
||||
)
|
||||
self.label_end_timer.setText(
|
||||
helpers.ms_to_mmss(
|
||||
self.playlist.get_current_duration() - playtime))
|
||||
|
||||
# Time to end
|
||||
self.label_end_timer.setText(helpers.ms_to_mmss(time_to_end))
|
||||
|
||||
else:
|
||||
# When music ends, update playlist display
|
||||
self.playlist.update_playlist_colours()
|
||||
if self.playing:
|
||||
self.label_end_timer.setText("00:00")
|
||||
self.frame_silent.setStyleSheet("")
|
||||
self.playing = False
|
||||
self.playlist.music_ended()
|
||||
self.update_headers()
|
||||
|
||||
def update_headers(self):
|
||||
"Update last / current / next track headers"
|
||||
|
||||
self.previous_track.setText(
|
||||
f"{self.playlist.get_previous_title()} - "
|
||||
f"{self.playlist.get_previous_artist()}"
|
||||
)
|
||||
self.current_track.setText(
|
||||
f"{self.playlist.get_current_title()} - "
|
||||
f"{self.playlist.get_current_artist()}"
|
||||
)
|
||||
self.next_track.setText(
|
||||
f"{self.playlist.get_next_title()} - "
|
||||
f"{self.playlist.get_next_artist()}"
|
||||
)
|
||||
|
||||
|
||||
class DbDialog(QDialog):
|
||||
|
||||
149
app/playlists.py
149
app/playlists.py
@ -42,7 +42,7 @@ class Playlist(QTableWidget):
|
||||
|
||||
self.current_track = None
|
||||
self.next_track = None
|
||||
self.previous_track_path = None
|
||||
self.previous_track = None
|
||||
self.previous_track_position = None
|
||||
self.played_tracks = []
|
||||
|
||||
@ -66,10 +66,11 @@ class Playlist(QTableWidget):
|
||||
"Save column widths"
|
||||
|
||||
for column in range(self.columnCount()):
|
||||
width = self.columnWidth(column)
|
||||
name = f"playlist_col_{str(column)}_width"
|
||||
record = Settings.get_int(name)
|
||||
if record.f_int != self.columnWidth(column):
|
||||
record.update({'f_int': self.columnWidth(column)})
|
||||
record.update({'f_int': width})
|
||||
|
||||
def add_to_playlist(self, track):
|
||||
"""
|
||||
@ -133,7 +134,7 @@ class Playlist(QTableWidget):
|
||||
DEBUG(f"Moved row(s) {rows} to become row {drop_row}")
|
||||
|
||||
self.clearSelection()
|
||||
self.update_playlist_colours()
|
||||
self.repaint()
|
||||
|
||||
def fade(self):
|
||||
self.music.fade()
|
||||
@ -225,17 +226,18 @@ class Playlist(QTableWidget):
|
||||
Return True if successful else False.
|
||||
"""
|
||||
|
||||
DEBUG(f"load_playlist({name})")
|
||||
|
||||
for track in Playlists.get_playlist_by_name(name).get_tracks():
|
||||
self.add_to_playlist(track)
|
||||
|
||||
# Set the first playable track as next to play
|
||||
for row in range(self.rowCount()):
|
||||
if self.set_row_as_next_track(row):
|
||||
if self.item(row, self.COL_INDEX):
|
||||
self.meta_set_next(row)
|
||||
self.tracks_changed()
|
||||
return True
|
||||
|
||||
self.update_playlist_colours()
|
||||
|
||||
return False
|
||||
|
||||
def meta_clear(self, row):
|
||||
@ -295,11 +297,21 @@ class Playlist(QTableWidget):
|
||||
def meta_set_current(self, row):
|
||||
"Mark row as current track"
|
||||
|
||||
DEBUG(f"meta_set_current({row})")
|
||||
|
||||
old_current = self.meta_get_current()
|
||||
if old_current is not None:
|
||||
self.meta_clear(old_current)
|
||||
self.meta_set(row, "current")
|
||||
|
||||
def meta_set_next(self, row):
|
||||
"Mark row as next track"
|
||||
|
||||
DEBUG(f"meta_set_next({row})")
|
||||
|
||||
old_next = self.meta_get_next()
|
||||
if old_next is not None:
|
||||
self.meta_clear(old_next)
|
||||
self.meta_set(row, "next")
|
||||
|
||||
def meta_set_note(self, row):
|
||||
@ -322,10 +334,9 @@ class Playlist(QTableWidget):
|
||||
Play (new) current.
|
||||
Update playlist "current track" metadata
|
||||
Cue up next track in playlist if there is one.
|
||||
Update playlist "next track" metadata
|
||||
Tell database to record it as played
|
||||
Remember it was played for this session
|
||||
Update playlist appearance.
|
||||
Update metadata and headers, and repaint
|
||||
"""
|
||||
|
||||
# If there is no next track set, return.
|
||||
@ -334,43 +345,30 @@ class Playlist(QTableWidget):
|
||||
|
||||
# If there's currently a track playing, fade it.
|
||||
if self.music.playing():
|
||||
path, position = self.music.fade()
|
||||
self.previous_track_path = path
|
||||
self.previous_track_position = position
|
||||
self.previous_track_position = self.music.fade()
|
||||
self.previous_track = self.current_track
|
||||
|
||||
# Move next track to current track.
|
||||
# Shuffle tracks along
|
||||
self.current_track = self.next_track
|
||||
self.next_track = None
|
||||
|
||||
# Play (new) current.
|
||||
self.music.play(self.current_track.path)
|
||||
|
||||
# Update playlist "current track" metadata
|
||||
old_current = self.meta_get_current()
|
||||
if old_current is not None:
|
||||
self.meta_clear(old_current)
|
||||
current = self.meta_get_next()
|
||||
if current is not None:
|
||||
self.meta_set_current(current)
|
||||
# Update metadata
|
||||
self.meta_set_current(self.meta_get_next())
|
||||
|
||||
# Cue up next track in playlist if there is one.
|
||||
track_id = 0
|
||||
next_row = 0
|
||||
if current is not None:
|
||||
start = current + 1
|
||||
# Set up metadata for next track in playlist if there is one.
|
||||
current_row = self.meta_get_current()
|
||||
if current_row is not None:
|
||||
start = current_row + 1
|
||||
else:
|
||||
start = 0
|
||||
for row in range(start, self.rowCount()):
|
||||
if self.item(row, self.COL_INDEX):
|
||||
if int(self.item(row, self.COL_INDEX).text()) > 0:
|
||||
track_id = int(self.item(row, self.COL_INDEX).text())
|
||||
next_row = row
|
||||
self.meta_set_next(row)
|
||||
break
|
||||
if track_id:
|
||||
self.next_track = Tracks.get_track(track_id)
|
||||
|
||||
# Update playlist "next track" metadata
|
||||
if next_row:
|
||||
self.meta_set_next(next_row)
|
||||
|
||||
# Tell database to record it as played
|
||||
self.current_track.update_lastplayed()
|
||||
@ -379,33 +377,15 @@ class Playlist(QTableWidget):
|
||||
# Remember it was played for this session
|
||||
self.played_tracks.append(self.current_track.id)
|
||||
|
||||
# Update playlist appearance.
|
||||
self.update_playlist_colours()
|
||||
# Update display
|
||||
self.tracks_changed()
|
||||
|
||||
def set_next_track(self):
|
||||
def set_selected_as_next(self):
|
||||
"""
|
||||
Sets the selected track as the next track.
|
||||
"""
|
||||
|
||||
# TODO
|
||||
pass
|
||||
|
||||
# if self.selectionModel().hasSelection():
|
||||
# self.set_next_track_row(self.playlist.currentRow())
|
||||
# if self.selectionModel().hasSelection():
|
||||
# row = self.currentRow()
|
||||
# track_id = int(self.item(row, 0).text())
|
||||
# DEBUG(f"play_selected: track_id={track_id}")
|
||||
# # TODO: get_path may raise exception
|
||||
# music.play_track(track_id)
|
||||
# track = Tracks.get_track(id)
|
||||
# if not track:
|
||||
# ERROR(f"set_next_track({id}): can't find track")
|
||||
# return None
|
||||
|
||||
# # self.next_track['player'] = vlc.MediaPlayer(track.path)
|
||||
# self.next_track = track
|
||||
# return track.id
|
||||
self.set_row_as_next_track(self.currentRow())
|
||||
|
||||
def set_row_as_next_track(self, row):
|
||||
"""
|
||||
@ -415,16 +395,21 @@ class Playlist(QTableWidget):
|
||||
"""
|
||||
|
||||
if self.item(row, self.COL_INDEX):
|
||||
track_id = int(self.item(row, self.COL_INDEX).text())
|
||||
DEBUG(f"set_row_as_next_track: track_id={track_id}")
|
||||
self.next_track = Tracks.get_track(track_id)
|
||||
# Mark row as next track
|
||||
self.meta_set_next(row)
|
||||
self.meta_set_current(row)
|
||||
self.tracks_changed()
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def update_playlist_colours(self):
|
||||
def music_ended(self):
|
||||
"Update display"
|
||||
|
||||
self.previous_track = self.current_track
|
||||
self.previous_track_position = 0
|
||||
self.meta_clear(self.meta_get_current())
|
||||
self.tracks_changed()
|
||||
|
||||
def repaint(self):
|
||||
"Set row colours, fonts, etc"
|
||||
|
||||
self.clearSelection()
|
||||
@ -481,6 +466,50 @@ class Playlist(QTableWidget):
|
||||
if self.item(row, j):
|
||||
self.item(row, j).setFont(normal)
|
||||
|
||||
def tracks_changed(self):
|
||||
"""
|
||||
One or more of current or next track has changed.
|
||||
|
||||
The row metadata is definitive because the same track may appear
|
||||
more than once in the playlist, but only one track may be marked
|
||||
as current or next.
|
||||
|
||||
Update self.current_track and self.next_track.
|
||||
"""
|
||||
|
||||
# Update instance variables
|
||||
current_row = self.meta_get_current()
|
||||
if current_row is not None:
|
||||
track_id = int(self.item(current_row, self.COL_INDEX).text())
|
||||
if not self.current_track or self.current_track.id != track_id:
|
||||
self.current_track = Tracks.get_track(track_id)
|
||||
else:
|
||||
self.current_track = None
|
||||
|
||||
next_row = self.meta_get_next()
|
||||
if next_row is not None:
|
||||
track_id = int(self.item(next_row, self.COL_INDEX).text())
|
||||
if not self.next_track or self.next_track.id != track_id:
|
||||
self.next_track = Tracks.get_track(track_id)
|
||||
else:
|
||||
self.next_track = None
|
||||
|
||||
try:
|
||||
DEBUG(f"tracks_changed() previous={self.previous_track.id}")
|
||||
except AttributeError:
|
||||
DEBUG("tracks_changed() previous=None")
|
||||
try:
|
||||
DEBUG(f"tracks_changed() current={self.current_track.id}")
|
||||
except AttributeError:
|
||||
DEBUG("tracks_changed() current=None")
|
||||
try:
|
||||
DEBUG(f"tracks_changed() next={self.next_track.id}")
|
||||
except AttributeError:
|
||||
DEBUG("tracks_changed() next=None")
|
||||
|
||||
# Update display
|
||||
self.repaint()
|
||||
|
||||
|
||||
class Window(QWidget):
|
||||
def __init__(self):
|
||||
|
||||
@ -491,7 +491,7 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_elapsed_2">
|
||||
<widget class="QFrame" name="frame_fade">
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -547,7 +547,7 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_elapsed_3">
|
||||
<widget class="QFrame" name="frame_silent">
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -603,7 +603,7 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_elapsed_4">
|
||||
<widget class="QFrame" name="frame_end">
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user