Compare commits
No commits in common. "b46830f010bac4cee57c3428f3d461c9b3c02433" and "c5f094443a493ac9a20c355ab51953c09373660f" have entirely different histories.
b46830f010
...
c5f094443a
@ -6,15 +6,12 @@ class Config(object):
|
|||||||
AUDIO_SEGMENT_CHUNK_SIZE = 10
|
AUDIO_SEGMENT_CHUNK_SIZE = 10
|
||||||
COLOUR_CURRENT_HEADER = "#d4edda"
|
COLOUR_CURRENT_HEADER = "#d4edda"
|
||||||
COLOUR_CURRENT_PLAYLIST = "#28a745"
|
COLOUR_CURRENT_PLAYLIST = "#28a745"
|
||||||
COLOUR_CURRENT_TAB = "#248f24"
|
|
||||||
COLOUR_ODD_PLAYLIST = "#f2f2f2"
|
COLOUR_ODD_PLAYLIST = "#f2f2f2"
|
||||||
COLOUR_ENDING_TIMER = "#dc3545"
|
COLOUR_ENDING_TIMER = "#dc3545"
|
||||||
COLOUR_EVEN_PLAYLIST = "#d9d9d9"
|
COLOUR_EVEN_PLAYLIST = "#d9d9d9"
|
||||||
COLOUR_LONG_START = "#dc3545"
|
COLOUR_LONG_START = "#dc3545"
|
||||||
COLOUR_NORMAL_TAB = "#000000"
|
|
||||||
COLOUR_NEXT_HEADER = "#fff3cd"
|
COLOUR_NEXT_HEADER = "#fff3cd"
|
||||||
COLOUR_NEXT_PLAYLIST = "#ffc107"
|
COLOUR_NEXT_PLAYLIST = "#ffc107"
|
||||||
COLOUR_NEXT_TAB = "#b38600"
|
|
||||||
COLOUR_NOTES_PLAYLIST = "#b8daff"
|
COLOUR_NOTES_PLAYLIST = "#b8daff"
|
||||||
COLOUR_PREVIOUS_HEADER = "#f8d7da"
|
COLOUR_PREVIOUS_HEADER = "#f8d7da"
|
||||||
COLOUR_UNREADABLE = "#dc3545"
|
COLOUR_UNREADABLE = "#dc3545"
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
|
||||||
import os.path
|
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@ -80,7 +79,7 @@ class Notes(Base):
|
|||||||
Update note details. If text=None, don't change text.
|
Update note details. If text=None, don't change text.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DEBUG(f"Notes.update_note(id={id}, row={row}, text={text})")
|
DEBUG(f"update_note(id={id}, row={row}, text={text})")
|
||||||
|
|
||||||
note = session.query(cls).filter(cls.id == id).one()
|
note = session.query(cls).filter(cls.id == id).one()
|
||||||
note.row = row
|
note.row = row
|
||||||
@ -501,7 +500,8 @@ class Tracks(Base):
|
|||||||
DEBUG(f"Tracks.get_track_from_filename({filename=})")
|
DEBUG(f"Tracks.get_track_from_filename({filename=})")
|
||||||
try:
|
try:
|
||||||
track = session.query(Tracks).filter(Tracks.path.ilike(
|
track = session.query(Tracks).filter(Tracks.path.ilike(
|
||||||
f'%{os.path.sep}{filename}')).one()
|
# TODO: filename separator is hardcoded here
|
||||||
|
f'%/{filename}')).one()
|
||||||
return track
|
return track
|
||||||
except (NoResultFound, MultipleResultsFound):
|
except (NoResultFound, MultipleResultsFound):
|
||||||
return None
|
return None
|
||||||
|
|||||||
@ -11,7 +11,7 @@ from datetime import datetime, timedelta
|
|||||||
from log import DEBUG, EXCEPTION
|
from log import DEBUG, EXCEPTION
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QTimer, QUrl
|
from PyQt5.QtCore import Qt, QTimer, QUrl
|
||||||
from PyQt5.QtGui import QColor, QFontMetrics, QPainter
|
from PyQt5.QtGui import QFontMetrics, QPainter
|
||||||
from PyQt5.QtWebEngineWidgets import QWebEngineView as QWebView
|
from PyQt5.QtWebEngineWidgets import QWebEngineView as QWebView
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QApplication,
|
QApplication,
|
||||||
@ -132,9 +132,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
if self.music.playing():
|
if self.music.playing():
|
||||||
DEBUG("closeEvent() ignored as music is playing")
|
DEBUG("closeEvent() ignored as music is playing")
|
||||||
event.ignore()
|
event.ignore()
|
||||||
helpers.show_warning(
|
# TODO notify user
|
||||||
"Track playing",
|
|
||||||
"Can't close application while track is playing")
|
|
||||||
else:
|
else:
|
||||||
DEBUG("closeEvent() accepted")
|
DEBUG("closeEvent() accepted")
|
||||||
|
|
||||||
@ -155,12 +153,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
if record.f_int != self.y():
|
if record.f_int != self.y():
|
||||||
record.update(session, {'f_int': self.y()})
|
record.update(session, {'f_int': self.y()})
|
||||||
|
|
||||||
# Find a playlist tab (as opposed to an info tab) and
|
self.visible_playlist_tab().close(session)
|
||||||
# save column widths
|
|
||||||
if self.current_track_playlist_tab:
|
|
||||||
self.current_track_playlist_tab.close(session)
|
|
||||||
elif self.next_track_playlist_tab:
|
|
||||||
self.next_track_playlist_tab.close(session)
|
|
||||||
|
|
||||||
event.accept()
|
event.accept()
|
||||||
|
|
||||||
@ -480,8 +473,6 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
# Play next track
|
# Play next track
|
||||||
self.current_track = self.next_track
|
self.current_track = self.next_track
|
||||||
self.current_track_playlist_tab = self.next_track_playlist_tab
|
self.current_track_playlist_tab = self.next_track_playlist_tab
|
||||||
self.set_tab_colour(self.current_track_playlist_tab,
|
|
||||||
QColor(Config.COLOUR_CURRENT_TAB))
|
|
||||||
self.next_track = None
|
self.next_track = None
|
||||||
self.next_track_playlist_tab = None
|
self.next_track_playlist_tab = None
|
||||||
DEBUG(
|
DEBUG(
|
||||||
@ -503,12 +494,6 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
else:
|
else:
|
||||||
self.next_track = self.next_track_playlist_tab = None
|
self.next_track = self.next_track_playlist_tab = None
|
||||||
|
|
||||||
if self.next_track_playlist_tab and (
|
|
||||||
self.current_track_playlist_tab !=
|
|
||||||
self.next_track_playlist_tab):
|
|
||||||
self.set_tab_colour(self.next_track_playlist_tab,
|
|
||||||
QColor(Config.COLOUR_NEXT_TAB))
|
|
||||||
|
|
||||||
# Tell database to record it as played
|
# Tell database to record it as played
|
||||||
self.current_track.update_lastplayed()
|
self.current_track.update_lastplayed()
|
||||||
Playdates.add_playdate(session, self.current_track)
|
Playdates.add_playdate(session, self.current_track)
|
||||||
@ -526,6 +511,12 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
silence_at - self.current_track.fade_at
|
silence_at - self.current_track.fade_at
|
||||||
))
|
))
|
||||||
|
|
||||||
|
def play_previous(self):
|
||||||
|
"Resume playing last track"
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
pass
|
||||||
|
|
||||||
def search_database(self):
|
def search_database(self):
|
||||||
with Session() as session:
|
with Session() as session:
|
||||||
dlg = DbDialog(self, session)
|
dlg = DbDialog(self, session)
|
||||||
@ -562,32 +553,12 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
if not next_track_id:
|
if not next_track_id:
|
||||||
next_track_id = (
|
next_track_id = (
|
||||||
self.visible_playlist_tab().set_selected_as_next())
|
self.visible_playlist_tab().set_selected_as_next())
|
||||||
if not next_track_id:
|
if next_track_id:
|
||||||
return
|
if self.next_track_playlist_tab != self.visible_playlist_tab():
|
||||||
|
if self.next_track_playlist_tab:
|
||||||
# The next track has been selected on the currently-visible
|
self.next_track_playlist_tab.clear_next()
|
||||||
# playlist. However, there may already be a 'next track'
|
self.next_track_playlist_tab = self.visible_playlist_tab()
|
||||||
# selected on another playlist that the user is overriding,
|
self.next_track = Tracks.get_track(session, next_track_id)
|
||||||
# in which case we need to reset that playlist.
|
|
||||||
if self.next_track_playlist_tab != self.visible_playlist_tab():
|
|
||||||
# We need to reset the ex-next-track playlist
|
|
||||||
if self.next_track_playlist_tab:
|
|
||||||
self.next_track_playlist_tab.clear_next()
|
|
||||||
# Reset tab colour if it NOT the current playing tab
|
|
||||||
if (self.next_track_playlist_tab !=
|
|
||||||
self.current_track_playlist_tab):
|
|
||||||
self.set_tab_colour(self.next_track_playlist_tab,
|
|
||||||
QColor(Config.COLOUR_NORMAL_TAB))
|
|
||||||
self.next_track_playlist_tab = self.visible_playlist_tab()
|
|
||||||
# self.next_track_playlist_tab is now set to correct
|
|
||||||
# playlist
|
|
||||||
if (self.next_track_playlist_tab !=
|
|
||||||
self.current_track_playlist_tab):
|
|
||||||
self.set_tab_colour(self.next_track_playlist_tab,
|
|
||||||
QColor(Config.COLOUR_NEXT_TAB))
|
|
||||||
|
|
||||||
self.next_track = Tracks.get_track(session, next_track_id)
|
|
||||||
|
|
||||||
self.update_headers()
|
self.update_headers()
|
||||||
|
|
||||||
def select_unplayed(self):
|
def select_unplayed(self):
|
||||||
@ -595,14 +566,6 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
self.visible_playlist_tab().select_unplayed_tracks()
|
self.visible_playlist_tab().select_unplayed_tracks()
|
||||||
|
|
||||||
def set_tab_colour(self, widget, colour):
|
|
||||||
"""
|
|
||||||
Find the tab containing the widget and set the text colour
|
|
||||||
"""
|
|
||||||
|
|
||||||
idx = self.tabPlaylist.indexOf(widget)
|
|
||||||
self.tabPlaylist.tabBar().setTabTextColor(idx, colour)
|
|
||||||
|
|
||||||
def song_info_search(self):
|
def song_info_search(self):
|
||||||
"""
|
"""
|
||||||
Open browser tabs for Wikipedia, searching for
|
Open browser tabs for Wikipedia, searching for
|
||||||
@ -637,13 +600,6 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
DEBUG(f"musicmuster.stop_playing({fade=})", True)
|
DEBUG(f"musicmuster.stop_playing({fade=})", True)
|
||||||
|
|
||||||
if self.current_track_playlist_tab == self.next_track_playlist_tab:
|
|
||||||
self.set_tab_colour(self.current_track_playlist_tab,
|
|
||||||
QColor(Config.COLOUR_NEXT_TAB))
|
|
||||||
else:
|
|
||||||
self.set_tab_colour(self.current_track_playlist_tab,
|
|
||||||
QColor(Config.COLOUR_NORMAL_TAB))
|
|
||||||
|
|
||||||
if not self.music.playing():
|
if not self.music.playing():
|
||||||
DEBUG("musicmuster.stop_playing(): not playing", True)
|
DEBUG("musicmuster.stop_playing(): not playing", True)
|
||||||
self.end_of_track_actions()
|
self.end_of_track_actions()
|
||||||
@ -675,7 +631,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
if not self.playing():
|
if not self.playing():
|
||||||
return
|
return
|
||||||
|
|
||||||
self.music.set_position(self.current_track.silence_at - 1000)
|
self.music.set_position(self.get_current_silence_at() - 1000)
|
||||||
|
|
||||||
def test_skip_to_fade(self):
|
def test_skip_to_fade(self):
|
||||||
"Skip current track to 1 second before fade"
|
"Skip current track to 1 second before fade"
|
||||||
@ -683,7 +639,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
if not self.music.playing():
|
if not self.music.playing():
|
||||||
return
|
return
|
||||||
|
|
||||||
self.music.set_position(self.current_track.fade_at - 1000)
|
self.music.set_position(self.get_current_fade_at() - 1000)
|
||||||
|
|
||||||
def tick(self):
|
def tick(self):
|
||||||
"""
|
"""
|
||||||
|
|||||||
118
app/playlists.py
118
app/playlists.py
@ -17,7 +17,7 @@ import os
|
|||||||
|
|
||||||
from config import Config
|
from config import Config
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from helpers import get_relative_date, open_in_audacity
|
from helpers import get_relative_date, open_in_audacity, show_warning
|
||||||
from log import DEBUG, ERROR
|
from log import DEBUG, ERROR
|
||||||
from model import (
|
from model import (
|
||||||
Notes, Playdates, Playlists, PlaylistTracks, Session, Settings, Tracks
|
Notes, Playdates, Playlists, PlaylistTracks, Session, Settings, Tracks
|
||||||
@ -172,31 +172,23 @@ class PlaylistTab(QTableWidget):
|
|||||||
if item is not None:
|
if item is not None:
|
||||||
row = item.row()
|
row = item.row()
|
||||||
DEBUG(f"playlist.eventFilter(): Right-click on row {row}")
|
DEBUG(f"playlist.eventFilter(): Right-click on row {row}")
|
||||||
current = row == self._meta_get_current()
|
|
||||||
next = row == self._meta_get_next()
|
|
||||||
self.menu = QMenu(self)
|
self.menu = QMenu(self)
|
||||||
act_info = self.menu.addAction('Info')
|
|
||||||
act_info.triggered.connect(lambda: self._info_row(row))
|
|
||||||
self.menu.addSeparator()
|
|
||||||
if row not in self._meta_get_notes():
|
if row not in self._meta_get_notes():
|
||||||
if not current and not next:
|
act_setnext = self.menu.addAction("Set next")
|
||||||
act_setnext = self.menu.addAction("Set next")
|
act_setnext.triggered.connect(lambda: self._set_next(row))
|
||||||
act_setnext.triggered.connect(
|
|
||||||
lambda: self._set_next(row))
|
|
||||||
act_copypath = self.menu.addAction("Copy track path")
|
act_copypath = self.menu.addAction("Copy track path")
|
||||||
act_copypath.triggered.connect(
|
act_copypath.triggered.connect(
|
||||||
lambda: self._copy_path(row))
|
lambda: self._copy_path(row))
|
||||||
if not current:
|
act_rescan = self.menu.addAction("Rescan track")
|
||||||
act_rescan = self.menu.addAction("Rescan track")
|
act_rescan.triggered.connect(lambda: self._rescan(row))
|
||||||
act_rescan.triggered.connect(lambda: self._rescan(row))
|
act_audacity = self.menu.addAction(
|
||||||
act_audacity = self.menu.addAction(
|
"Open track in Audacity")
|
||||||
"Open track in Audacity")
|
act_audacity.triggered.connect(lambda: self._audacity(row))
|
||||||
act_audacity.triggered.connect(
|
|
||||||
lambda: self._audacity(row))
|
|
||||||
if not current and not next:
|
|
||||||
self.menu.addSeparator()
|
self.menu.addSeparator()
|
||||||
act_delete = self.menu.addAction('Delete')
|
act_delete = self.menu.addAction('Delete')
|
||||||
act_delete.triggered.connect(self._delete_rows)
|
act_delete.triggered.connect(self._delete_rows)
|
||||||
|
act_info = self.menu.addAction('Info')
|
||||||
|
act_info.triggered.connect(lambda: self._info_row(row))
|
||||||
|
|
||||||
return super(PlaylistTab, self).eventFilter(source, event)
|
return super(PlaylistTab, self).eventFilter(source, event)
|
||||||
|
|
||||||
@ -232,12 +224,10 @@ class PlaylistTab(QTableWidget):
|
|||||||
start_time = None
|
start_time = None
|
||||||
try:
|
try:
|
||||||
start_time = datetime.strptime(note.note[-9:], " %H:%M:%S").time()
|
start_time = datetime.strptime(note.note[-9:], " %H:%M:%S").time()
|
||||||
DEBUG(
|
DEBUG(f"Note contains valid time={start_time}")
|
||||||
f"playlist.inset_note(): Note contains valid time={start_time}"
|
|
||||||
)
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
DEBUG(
|
DEBUG(
|
||||||
f"playlist.inset_note(): Note on row {row} ('{note.note}') "
|
f"Note on row {row} ('{note.note}') "
|
||||||
"does not contain valid time"
|
"does not contain valid time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -623,9 +613,6 @@ class PlaylistTab(QTableWidget):
|
|||||||
|
|
||||||
if not self.editing_cell:
|
if not self.editing_cell:
|
||||||
return
|
return
|
||||||
# If we update start time, _cell_changed will be called
|
|
||||||
if column not in [self.COL_TITLE, self.COL_ARTIST]:
|
|
||||||
return
|
|
||||||
|
|
||||||
new = self.item(row, column).text()
|
new = self.item(row, column).text()
|
||||||
|
|
||||||
@ -634,28 +621,7 @@ class PlaylistTab(QTableWidget):
|
|||||||
row_id = self._get_row_id(row)
|
row_id = self._get_row_id(row)
|
||||||
with Session() as session:
|
with Session() as session:
|
||||||
if row in self._meta_get_notes():
|
if row in self._meta_get_notes():
|
||||||
# Save change to database
|
|
||||||
DEBUG(
|
|
||||||
f"Notes.update_note: saving new note text '{new=}'",
|
|
||||||
True
|
|
||||||
)
|
|
||||||
Notes.update_note(session, row_id, row, new)
|
Notes.update_note(session, row_id, row, new)
|
||||||
# Set/clear row start time accordingly
|
|
||||||
try:
|
|
||||||
start_dt = datetime.strptime(new[-9:], " %H:%M:%S")
|
|
||||||
start_time = start_dt.time()
|
|
||||||
self._set_row_start_time(row, start_time)
|
|
||||||
DEBUG(
|
|
||||||
f"_cell_changed:Note {new} contains valid "
|
|
||||||
f"time={start_time}"
|
|
||||||
)
|
|
||||||
except ValueError:
|
|
||||||
# Reset row start time in case it used to have one
|
|
||||||
self._set_row_start_time(row, None)
|
|
||||||
DEBUG(
|
|
||||||
f"_cell_changed:Note {new} does not contain "
|
|
||||||
"start time"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
track = Tracks.get_track(session, row_id)
|
track = Tracks.get_track(session, row_id)
|
||||||
if column == self.COL_ARTIST:
|
if column == self.COL_ARTIST:
|
||||||
@ -673,11 +639,6 @@ class PlaylistTab(QTableWidget):
|
|||||||
def _cell_edit_ended(self):
|
def _cell_edit_ended(self):
|
||||||
DEBUG("_cell_edit_ended()")
|
DEBUG("_cell_edit_ended()")
|
||||||
self.editing_cell = False
|
self.editing_cell = False
|
||||||
|
|
||||||
# Call repaint to update start times, such as when a note has
|
|
||||||
# been edited
|
|
||||||
self._repaint()
|
|
||||||
|
|
||||||
self.master_process.enable_play_next_controls()
|
self.master_process.enable_play_next_controls()
|
||||||
|
|
||||||
def _delete_rows(self):
|
def _delete_rows(self):
|
||||||
@ -691,14 +652,22 @@ class PlaylistTab(QTableWidget):
|
|||||||
|
|
||||||
with Session() as session:
|
with Session() as session:
|
||||||
for row in rows:
|
for row in rows:
|
||||||
|
if row == self._meta_get_current():
|
||||||
|
show_warning("Silly", "Can't delete playing track")
|
||||||
|
return
|
||||||
|
elif row == self._meta_get_next():
|
||||||
|
show_warning("Safety", "Can't delete next track")
|
||||||
|
return
|
||||||
|
|
||||||
title = self.item(row, self.COL_TITLE).text()
|
title = self.item(row, self.COL_TITLE).text()
|
||||||
|
|
||||||
msg = QMessageBox(self)
|
msg = QMessageBox(self)
|
||||||
msg.setIcon(QMessageBox.Warning)
|
msg.setIcon(QMessageBox.Warning)
|
||||||
msg.setText(f"Delete '{title}'?")
|
msg.setText(f"Delete '{title}'?")
|
||||||
msg.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel)
|
msg.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel)
|
||||||
msg.setDefaultButton(QMessageBox.Cancel)
|
msg.setDefaultButton(QMessageBox.Cancel)
|
||||||
msg.setWindowTitle("Delete row")
|
msg.setWindowTitle("Delete row")
|
||||||
# Store list of rows to delete
|
# Store list of notes
|
||||||
if msg.exec() == QMessageBox.Yes:
|
if msg.exec() == QMessageBox.Yes:
|
||||||
rows_to_delete.append(row)
|
rows_to_delete.append(row)
|
||||||
|
|
||||||
@ -965,17 +934,13 @@ class PlaylistTab(QTableWidget):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
track_id = self._get_row_id(row)
|
track_id = self._get_row_id(row)
|
||||||
if not track_id:
|
if track_id:
|
||||||
return None
|
if self._track_path_is_readable(track_id):
|
||||||
|
self._meta_set_next(row)
|
||||||
if self._track_path_is_readable(track_id):
|
self.master_process.set_next_track(track_id)
|
||||||
self._meta_set_next(row)
|
else:
|
||||||
self.master_process.set_next_track(track_id)
|
self._meta_set_unreadable(row)
|
||||||
else:
|
track_id = None
|
||||||
self._meta_set_unreadable(row)
|
|
||||||
track_id = None
|
|
||||||
self._repaint()
|
|
||||||
|
|
||||||
return track_id
|
return track_id
|
||||||
|
|
||||||
def _repaint(self, clear_selection=True):
|
def _repaint(self, clear_selection=True):
|
||||||
@ -998,18 +963,6 @@ class PlaylistTab(QTableWidget):
|
|||||||
# Set colours and start times
|
# Set colours and start times
|
||||||
next_start_time = None
|
next_start_time = None
|
||||||
|
|
||||||
# Don't change start times for tracks that have been played.
|
|
||||||
# For unplayed tracks, if there's a 'current' or 'next'
|
|
||||||
# track marked, populate start times from then onwards. If
|
|
||||||
# neither, populate start times from first note with a start
|
|
||||||
# time.
|
|
||||||
if current and next:
|
|
||||||
start_times_row = min(current, next)
|
|
||||||
else:
|
|
||||||
start_times_row = current or next
|
|
||||||
if not start_times_row:
|
|
||||||
start_times_row = 0
|
|
||||||
|
|
||||||
# Cycle through all rows
|
# Cycle through all rows
|
||||||
for row in range(self.rowCount()):
|
for row in range(self.rowCount()):
|
||||||
# We can't calculate start times until next_start_time is
|
# We can't calculate start times until next_start_time is
|
||||||
@ -1090,16 +1043,12 @@ class PlaylistTab(QTableWidget):
|
|||||||
self._set_row_not_bold(row)
|
self._set_row_not_bold(row)
|
||||||
else:
|
else:
|
||||||
# Set start/end times only if we haven't played it yet
|
# Set start/end times only if we haven't played it yet
|
||||||
if next_start_time and row >= start_times_row:
|
if next_start_time:
|
||||||
self._set_row_start_time(row, next_start_time)
|
self._set_row_start_time(row, next_start_time)
|
||||||
next_start_time = self._calculate_next_start_time(
|
next_start_time = self._calculate_next_start_time(
|
||||||
session, row, next_start_time)
|
session, row, next_start_time)
|
||||||
# Set end time
|
# Set end time
|
||||||
self._set_row_end_time(row, next_start_time)
|
self._set_row_end_time(row, next_start_time)
|
||||||
else:
|
|
||||||
# Clear start and end time
|
|
||||||
self._set_row_start_time(row, None)
|
|
||||||
self._set_row_end_time(row, None)
|
|
||||||
# Don't dim unplayed tracks
|
# Don't dim unplayed tracks
|
||||||
self._set_row_bold(row)
|
self._set_row_bold(row)
|
||||||
|
|
||||||
@ -1199,6 +1148,9 @@ class PlaylistTab(QTableWidget):
|
|||||||
If multiple rows are selected, display sum of durations in status bar.
|
If multiple rows are selected, display sum of durations in status bar.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Clear label
|
||||||
|
self.master_process.lblSumPlaytime.setText("")
|
||||||
|
|
||||||
rows = set([item.row() for item in self.selectedItems()])
|
rows = set([item.row() for item in self.selectedItems()])
|
||||||
notes = self._meta_get_notes()
|
notes = self._meta_get_notes()
|
||||||
ms = 0
|
ms = 0
|
||||||
@ -1211,8 +1163,6 @@ class PlaylistTab(QTableWidget):
|
|||||||
if ms > 0:
|
if ms > 0:
|
||||||
self.master_process.lblSumPlaytime.setText(
|
self.master_process.lblSumPlaytime.setText(
|
||||||
f"Selected duration: {helpers.ms_to_mmss(ms)}")
|
f"Selected duration: {helpers.ms_to_mmss(ms)}")
|
||||||
else:
|
|
||||||
self.master_process.lblSumPlaytime.setText("")
|
|
||||||
|
|
||||||
def _set_column_widths(self):
|
def _set_column_widths(self):
|
||||||
# Column widths from settings
|
# Column widths from settings
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import shutil
|
|||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from config import Config
|
from config import Config
|
||||||
from helpers import show_warning
|
|
||||||
from log import DEBUG, INFO
|
from log import DEBUG, INFO
|
||||||
from model import Notes, Playdates, PlaylistTracks, Session, Tracks
|
from model import Notes, Playdates, PlaylistTracks, Session, Tracks
|
||||||
from mutagen.flac import FLAC
|
from mutagen.flac import FLAC
|
||||||
@ -370,23 +369,15 @@ def update_meta(session, track, artist=None, title=None):
|
|||||||
INFO(f"File type {ftype} not implemented")
|
INFO(f"File type {ftype} not implemented")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Update tags
|
|
||||||
f = tag_handler(track.path)
|
f = tag_handler(track.path)
|
||||||
try:
|
|
||||||
if artist:
|
|
||||||
f["artist"] = artist
|
|
||||||
if title:
|
|
||||||
f["title"] = title
|
|
||||||
f.save()
|
|
||||||
except TypeError:
|
|
||||||
show_warning("TAG error", "Can't update tag. Try editing in Audacity")
|
|
||||||
|
|
||||||
# Update database
|
|
||||||
with Session() as session:
|
with Session() as session:
|
||||||
if artist:
|
if artist:
|
||||||
|
f["artist"] = artist
|
||||||
Tracks.update_artist(session, track.id, artist)
|
Tracks.update_artist(session, track.id, artist)
|
||||||
if title:
|
if title:
|
||||||
|
f["title"] = title
|
||||||
Tracks.update_title(session, track.id, title)
|
Tracks.update_title(session, track.id, title)
|
||||||
|
f.save()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__' and '__file__' in globals():
|
if __name__ == '__main__' and '__file__' in globals():
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user