Add bitrates to database and display
This commit is contained in:
parent
0e9461e0df
commit
140722217b
@ -6,7 +6,12 @@ from typing import List, Optional
|
||||
class Config(object):
|
||||
AUDACITY_COMMAND = "/usr/bin/audacity"
|
||||
AUDIO_SEGMENT_CHUNK_SIZE = 10
|
||||
BITRATE_LOW_THRESHOLD = 192
|
||||
BITRATE_OK_THRESHOLD = 300
|
||||
CHECK_AUDACITY_AT_STARTUP = True
|
||||
COLOUR_BITRATE_LOW = "#ffcdd2"
|
||||
COLOUR_BITRATE_MEDIUM = "#ffeb6f"
|
||||
COLOUR_BITRATE_OK = "#dcedc8"
|
||||
COLOUR_CURRENT_HEADER = "#d4edda"
|
||||
COLOUR_CURRENT_PLAYLIST = "#7eca8f"
|
||||
COLOUR_CURRENT_TAB = "#248f24"
|
||||
@ -24,6 +29,7 @@ class Config(object):
|
||||
COLOUR_WARNING_TIMER = "#ffc107"
|
||||
COLUMN_NAME_ARTIST = "Artist"
|
||||
COLUMN_NAME_AUTOPLAY = "A"
|
||||
COLUMN_NAME_BITRATE = "bps"
|
||||
COLUMN_NAME_END_TIME = "End"
|
||||
COLUMN_NAME_LAST_PLAYED = "Last played"
|
||||
COLUMN_NAME_LEADING_SILENCE = "Gap"
|
||||
|
||||
@ -86,6 +86,7 @@ def get_tags(path: str) -> Dict[str, Union[str, int]]:
|
||||
return dict(
|
||||
title=tag.title,
|
||||
artist=tag.artist,
|
||||
bitrate=round(tag.bitrate),
|
||||
duration=int(round(tag.duration, Config.MILLISECOND_SIGFIGS) * 1000),
|
||||
path=path
|
||||
)
|
||||
|
||||
@ -510,6 +510,7 @@ class Tracks(Base):
|
||||
silence_at = Column(Integer, index=False)
|
||||
path = Column(String(2048), index=False, nullable=False, unique=True)
|
||||
mtime = Column(Float, index=True)
|
||||
bitrate = Column(Integer, nullable=True, default=None)
|
||||
playlistrows = relationship("PlaylistRows", back_populates="track")
|
||||
playlists = association_proxy("playlistrows", "playlist")
|
||||
playdates = relationship("Playdates", back_populates="track")
|
||||
@ -546,11 +547,11 @@ class Tracks(Base):
|
||||
session.add(self)
|
||||
session.commit()
|
||||
|
||||
@staticmethod
|
||||
def get_all_paths(session) -> List[str]:
|
||||
"""Return a list of paths of all tracks"""
|
||||
@classmethod
|
||||
def get_all(cls, session) -> List["Tracks"]:
|
||||
"""Return a list of all tracks"""
|
||||
|
||||
return session.execute(select(Tracks.path)).scalars().all()
|
||||
return session.execute(select(cls)).scalars().all()
|
||||
|
||||
@classmethod
|
||||
def get_or_create(cls, session: Session, path: str) -> "Tracks":
|
||||
|
||||
@ -41,7 +41,7 @@ from ui.dlg_SelectPlaylist_ui import Ui_dlgSelectPlaylist # type: ignore
|
||||
from ui.downloadcsv_ui import Ui_DateSelect # type: ignore
|
||||
from config import Config
|
||||
from ui.main_window_ui import Ui_MainWindow # type: ignore
|
||||
from utilities import create_track_from_file, check_db
|
||||
from utilities import create_track_from_file, check_db, update_bitrates
|
||||
|
||||
|
||||
class TrackData:
|
||||
@ -1134,6 +1134,9 @@ if __name__ == "__main__":
|
||||
p = argparse.ArgumentParser()
|
||||
# Only allow at most one option to be specified
|
||||
group = p.add_mutually_exclusive_group()
|
||||
group.add_argument('-b', '--bitrates',
|
||||
action="store_true", dest="update_bitrates",
|
||||
default=False, help="Update bitrates in database")
|
||||
group.add_argument('-c', '--check-database',
|
||||
action="store_true", dest="check_db",
|
||||
default=False, help="Check and report on database")
|
||||
@ -1144,6 +1147,10 @@ if __name__ == "__main__":
|
||||
log.debug("Updating database")
|
||||
with Session() as session:
|
||||
check_db(session)
|
||||
elif args.update_bitrates:
|
||||
log.debug("Update bitrates")
|
||||
with Session() as session:
|
||||
update_bitrates(session)
|
||||
else:
|
||||
# Normal run
|
||||
try:
|
||||
|
||||
@ -77,7 +77,8 @@ columns["duration"] = Column(idx=4, heading=Config.COLUMN_NAME_LENGTH)
|
||||
columns["start_time"] = Column(idx=5, heading=Config.COLUMN_NAME_START_TIME)
|
||||
columns["end_time"] = Column(idx=6, heading=Config.COLUMN_NAME_END_TIME)
|
||||
columns["lastplayed"] = Column(idx=7, heading=Config.COLUMN_NAME_LAST_PLAYED)
|
||||
columns["row_notes"] = Column(idx=8, heading=Config.COLUMN_NAME_NOTES)
|
||||
columns["bitrate"] = Column(idx=8, heading=Config.COLUMN_NAME_BITRATE)
|
||||
columns["row_notes"] = Column(idx=9, heading=Config.COLUMN_NAME_NOTES)
|
||||
|
||||
|
||||
class NoSelectDelegate(QStyledItemDelegate):
|
||||
@ -95,6 +96,7 @@ class NoSelectDelegate(QStyledItemDelegate):
|
||||
return QPlainTextEdit(parent)
|
||||
return super().createEditor(parent, option, index)
|
||||
|
||||
|
||||
class PlaylistTab(QTableWidget):
|
||||
# Qt.UserRoles
|
||||
ROW_FLAGS = Qt.UserRole
|
||||
@ -582,6 +584,13 @@ class PlaylistTab(QTableWidget):
|
||||
end_item = QTableWidgetItem()
|
||||
self.setItem(row, columns['end_time'].idx, end_item)
|
||||
|
||||
if row_data.track.bitrate:
|
||||
bitrate = str(row_data.track.bitrate)
|
||||
else:
|
||||
bitrate = ""
|
||||
bitrate_item = QTableWidgetItem(bitrate)
|
||||
self.setItem(row, columns['bitrate'].idx, bitrate_item)
|
||||
|
||||
# As we have track info, any notes should be contained in
|
||||
# the notes column
|
||||
notes_item = QTableWidgetItem(row_data.note)
|
||||
@ -995,6 +1004,17 @@ class PlaylistTab(QTableWidget):
|
||||
# Ensure content is visible by wrapping cells
|
||||
self.resizeRowToContents(row)
|
||||
|
||||
# Highlight low bitrates
|
||||
if track.bitrate:
|
||||
if track.bitrate < Config.BITRATE_LOW_THRESHOLD:
|
||||
cell_colour = Config.COLOUR_BITRATE_LOW
|
||||
elif track.bitrate < Config.BITRATE_OK_THRESHOLD:
|
||||
cell_colour = Config.COLOUR_BITRATE_MEDIUM
|
||||
else:
|
||||
cell_colour = Config.COLOUR_BITRATE_OK
|
||||
brush = QBrush(QColor(cell_colour))
|
||||
self.item(row, columns['bitrate'].idx).setBackground(brush)
|
||||
|
||||
# Render playing track
|
||||
if row == current_row:
|
||||
# Set start time
|
||||
@ -1421,6 +1441,7 @@ class PlaylistTab(QTableWidget):
|
||||
f"Artist: {track.artist}\n"
|
||||
f"Track ID: {track.id}\n"
|
||||
f"Track duration: {ms_to_mmss(track.duration)}\n"
|
||||
f"Track bitrate: {track.bitrate}\n"
|
||||
f"Track fade at: {ms_to_mmss(track.fade_at)}\n"
|
||||
f"Track silence at: {ms_to_mmss(track.silence_at)}"
|
||||
"\n\n"
|
||||
|
||||
@ -43,6 +43,7 @@ def create_track_from_file(session, path, normalise=None, tags=None):
|
||||
track.silence_at = round(trailing_silence(audio) / 1000,
|
||||
Config.MILLISECOND_SIGFIGS) * 1000
|
||||
track.mtime = os.path.getmtime(path)
|
||||
track.bitrate = t['bitrate']
|
||||
session.commit()
|
||||
|
||||
if normalise or normalise is None and Config.NORMALISE_ON_IMPORT:
|
||||
@ -107,7 +108,7 @@ def check_db(session):
|
||||
Check all paths in database exist
|
||||
"""
|
||||
|
||||
db_paths = set(Tracks.get_all_paths(session))
|
||||
db_paths = set([a.path for a in Tracks.get_all(session)])
|
||||
|
||||
os_paths_list = []
|
||||
for root, dirs, files in os.walk(Config.ROOT):
|
||||
@ -162,6 +163,19 @@ def check_db(session):
|
||||
print("There were more paths than listed that were not found")
|
||||
|
||||
|
||||
def update_bitrates(session):
|
||||
"""
|
||||
Update bitrates on all tracks in database
|
||||
"""
|
||||
|
||||
for track in Tracks.get_all(session):
|
||||
try:
|
||||
t = get_tags(track.path)
|
||||
track.bitrate = t["bitrate"]
|
||||
except FileNotFoundError:
|
||||
continue
|
||||
|
||||
|
||||
# # Spike
|
||||
# #
|
||||
# # # Manage tracks listed in database but where path is invalid
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
"""Add column for bitrate in Tracks
|
||||
|
||||
Revision ID: ed3100326c38
|
||||
Revises: fe2e127b3332
|
||||
Create Date: 2022-08-22 16:16:42.181848
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'ed3100326c38'
|
||||
down_revision = 'fe2e127b3332'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('tracks', sa.Column('bitrate', sa.Integer(), nullable=True))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('tracks', 'bitrate')
|
||||
# ### end Alembic commands ###
|
||||
Loading…
Reference in New Issue
Block a user