Compare commits
10 Commits
b42ffcec69
...
1da0668807
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1da0668807 | ||
|
|
1ce009ee73 | ||
|
|
5d1078dea0 | ||
|
|
e1ceb5e8e3 | ||
|
|
912ed0b1eb | ||
|
|
d670f397fc | ||
|
|
7829186d55 | ||
|
|
0c37eccb76 | ||
|
|
7601c7dc4c | ||
|
|
84d746bd2f |
@ -6,6 +6,7 @@ import tempfile
|
||||
from mutagen.flac import FLAC # type: ignore
|
||||
from mutagen.mp3 import MP3 # type: ignore
|
||||
from pydub import effects
|
||||
from pydub.utils import mediainfo
|
||||
|
||||
from config import Config
|
||||
from datetime import datetime
|
||||
@ -202,6 +203,7 @@ def normalise_track(path):
|
||||
f"File type {ftype} not implemented"
|
||||
)
|
||||
|
||||
bitrate = mediainfo(path)['bit_rate']
|
||||
audio = get_audio_segment(path)
|
||||
if not audio:
|
||||
return
|
||||
@ -221,7 +223,8 @@ def normalise_track(path):
|
||||
# Overwrite original file with normalised output
|
||||
normalised = effects.normalize(audio)
|
||||
try:
|
||||
normalised.export(path, format=os.path.splitext(path)[1][1:])
|
||||
normalised.export(path, format=os.path.splitext(path)[1][1:],
|
||||
bitrate=bitrate)
|
||||
# Fix up permssions and ownership
|
||||
os.chown(path, stats.st_uid, stats.st_gid)
|
||||
os.chmod(path, stats.st_mode)
|
||||
|
||||
@ -453,9 +453,9 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
return
|
||||
|
||||
with Session() as session:
|
||||
txt = ""
|
||||
new_tracks = []
|
||||
for fname in dlg.selectedFiles():
|
||||
txt = ""
|
||||
tags = helpers.get_tags(fname)
|
||||
new_tracks.append((fname, tags))
|
||||
title = tags['title']
|
||||
|
||||
161
app/playlists.py
161
app/playlists.py
@ -74,8 +74,8 @@ class RowMeta:
|
||||
Column = namedtuple("Column", ['idx', 'heading'])
|
||||
columns = {}
|
||||
columns["userdata"] = Column(idx=0, heading=Config.COLUMN_NAME_AUTOPLAY)
|
||||
columns["start_gap"] = Column(
|
||||
idx=1, heading=Config.COLUMN_NAME_LEADING_SILENCE)
|
||||
columns["start_gap"] = Column(idx=1,
|
||||
heading=Config.COLUMN_NAME_LEADING_SILENCE)
|
||||
columns["title"] = Column(idx=2, heading=Config.COLUMN_NAME_TITLE)
|
||||
columns["artist"] = Column(idx=3, heading=Config.COLUMN_NAME_ARTIST)
|
||||
columns["duration"] = Column(idx=4, heading=Config.COLUMN_NAME_LENGTH)
|
||||
@ -85,6 +85,17 @@ columns["lastplayed"] = Column(idx=7, heading=Config.COLUMN_NAME_LAST_PLAYED)
|
||||
columns["bitrate"] = Column(idx=8, heading=Config.COLUMN_NAME_BITRATE)
|
||||
columns["row_notes"] = Column(idx=9, heading=Config.COLUMN_NAME_NOTES)
|
||||
|
||||
USERDATA = columns["userdata"].idx
|
||||
START_GAP = columns["start_gap"].idx
|
||||
TITLE = columns["title"].idx
|
||||
ARTIST = columns["artist"].idx
|
||||
DURATION = columns["duration"].idx
|
||||
START_TIME = columns["start_time"].idx
|
||||
END_TIME = columns["end_time"].idx
|
||||
LASTPLAYED = columns["lastplayed"].idx
|
||||
BITRATE = columns["bitrate"].idx
|
||||
ROW_NOTES = columns["row_notes"].idx
|
||||
|
||||
|
||||
class NoSelectDelegate(QStyledItemDelegate):
|
||||
"""
|
||||
@ -395,7 +406,11 @@ class PlaylistTab(QTableWidget):
|
||||
# change cell again (metadata)
|
||||
self.cellChanged.disconnect(self._cell_changed)
|
||||
|
||||
new_text = self.item(row, column).text()
|
||||
new_text = self.item(row, column).text().strip()
|
||||
|
||||
# Update cell with strip()'d text
|
||||
self.item(row, column).setText(new_text)
|
||||
|
||||
track_id = self._get_row_track_id(row)
|
||||
|
||||
# Determin cell type changed
|
||||
@ -465,11 +480,11 @@ class PlaylistTab(QTableWidget):
|
||||
# If a track row, we only allow editing of title, artist and
|
||||
# note. Check that this column is one of those.
|
||||
self.edit_cell_type = None
|
||||
if column == columns['title'].idx:
|
||||
if column == TITLE:
|
||||
self.edit_cell_type = "title"
|
||||
elif column == columns['artist'].idx:
|
||||
elif column == ARTIST:
|
||||
self.edit_cell_type = "artist"
|
||||
elif column == columns['row_notes'].idx:
|
||||
elif column == ROW_NOTES:
|
||||
self.edit_cell_type = "row_notes"
|
||||
else:
|
||||
# Can't edit other columns
|
||||
@ -477,7 +492,7 @@ class PlaylistTab(QTableWidget):
|
||||
|
||||
# Check whether we're editing a notes row for later
|
||||
if self.edit_cell_type == "row_notes":
|
||||
note_column = columns['row_notes'].idx
|
||||
note_column = ROW_NOTES
|
||||
else:
|
||||
# This is a section header.
|
||||
if column != HEADER_NOTES_COLUMN:
|
||||
@ -555,7 +570,7 @@ class PlaylistTab(QTableWidget):
|
||||
self.insert_row(session, plr)
|
||||
PlaylistRows.fixup_rownumbers(session, self.playlist_id)
|
||||
if repaint:
|
||||
self.update_display(session)
|
||||
self.update_display(session, clear_selection=False)
|
||||
|
||||
def insert_row(self, session: Session, row_data: PlaylistRows,
|
||||
repaint: bool = True) -> None:
|
||||
@ -580,7 +595,7 @@ class PlaylistTab(QTableWidget):
|
||||
userdata_item.setData(self.ROW_FLAGS, 0)
|
||||
userdata_item.setData(self.PLAYLISTROW_ID, row_data.id)
|
||||
userdata_item.setData(self.ROW_TRACK_ID, row_data.track_id)
|
||||
self.setItem(row, columns['userdata'].idx, userdata_item)
|
||||
self.setItem(row, USERDATA, userdata_item)
|
||||
|
||||
if row_data.track_id:
|
||||
# Add track details to items
|
||||
@ -591,41 +606,41 @@ class PlaylistTab(QTableWidget):
|
||||
start_gap_item = QTableWidgetItem(str(start_gap))
|
||||
if start_gap and start_gap >= 500:
|
||||
start_gap_item.setBackground(QColor(Config.COLOUR_LONG_START))
|
||||
self.setItem(row, columns['start_gap'].idx, start_gap_item)
|
||||
self.setItem(row, START_GAP, start_gap_item)
|
||||
|
||||
title_item = QTableWidgetItem(row_data.track.title)
|
||||
self.setItem(row, columns['title'].idx, title_item)
|
||||
self.setItem(row, TITLE, title_item)
|
||||
|
||||
artist_item = QTableWidgetItem(row_data.track.artist)
|
||||
self.setItem(row, columns['artist'].idx, artist_item)
|
||||
self.setItem(row, ARTIST, artist_item)
|
||||
|
||||
duration_item = QTableWidgetItem(
|
||||
ms_to_mmss(row_data.track.duration))
|
||||
self.setItem(row, columns['duration'].idx, duration_item)
|
||||
self.setItem(row, DURATION, duration_item)
|
||||
self._set_row_duration(row, row_data.track.duration)
|
||||
|
||||
start_item = QTableWidgetItem()
|
||||
self.setItem(row, columns['start_time'].idx, start_item)
|
||||
self.setItem(row, START_TIME, start_item)
|
||||
|
||||
end_item = QTableWidgetItem()
|
||||
self.setItem(row, columns['end_time'].idx, end_item)
|
||||
self.setItem(row, END_TIME, 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)
|
||||
self.setItem(row, BITRATE, bitrate_item)
|
||||
|
||||
# As we have track info, any notes should be contained in
|
||||
# the notes column
|
||||
notes_item = QTableWidgetItem(row_data.note)
|
||||
self.setItem(row, columns['row_notes'].idx, notes_item)
|
||||
self.setItem(row, ROW_NOTES, notes_item)
|
||||
|
||||
last_playtime = Playdates.last_played(session, row_data.track.id)
|
||||
last_played_str = get_relative_date(last_playtime)
|
||||
last_played_item = QTableWidgetItem(last_played_str)
|
||||
self.setItem(row, columns['lastplayed'].idx, last_played_item)
|
||||
self.setItem(row, LASTPLAYED, last_played_item)
|
||||
|
||||
# Mark track if file is unreadable
|
||||
if not file_is_readable(row_data.track.path):
|
||||
@ -1036,6 +1051,19 @@ class PlaylistTab(QTableWidget):
|
||||
track = None
|
||||
if track_id:
|
||||
track = session.get(Tracks, track_id)
|
||||
if not track:
|
||||
# We have a track_id but we can't find the track.
|
||||
# Update playlist_row accordingly
|
||||
missing_track = playlist_row.track_id
|
||||
playlist_row.track_id = None
|
||||
if note_text:
|
||||
note_text += f"track_id {missing_track} not found"
|
||||
else:
|
||||
note_text = f"track_id {missing_track} not found"
|
||||
playlist_row.note = note_text
|
||||
session.commit()
|
||||
note_item = QTableWidgetItem(note_text)
|
||||
self.setItem(row, HEADER_NOTES_COLUMN, note_item)
|
||||
|
||||
if track:
|
||||
# Reset colour in case it was current/next/unplayable
|
||||
@ -1053,11 +1081,15 @@ class PlaylistTab(QTableWidget):
|
||||
|
||||
# Colour any note
|
||||
if note_colour:
|
||||
(self.item(row, columns['row_notes'].idx)
|
||||
(self.item(row, ROW_NOTES)
|
||||
.setBackground(QColor(note_colour)))
|
||||
|
||||
# Highlight low bitrates
|
||||
if track.bitrate:
|
||||
bitrate_str = str(track.bitrate)
|
||||
bitrate_item = self.item(row, BITRATE)
|
||||
if bitrate_item.text() != bitrate_str:
|
||||
bitrate_item.setText(bitrate_str)
|
||||
if track.bitrate < Config.BITRATE_LOW_THRESHOLD:
|
||||
cell_colour = Config.COLOUR_BITRATE_LOW
|
||||
elif track.bitrate < Config.BITRATE_OK_THRESHOLD:
|
||||
@ -1065,7 +1097,7 @@ class PlaylistTab(QTableWidget):
|
||||
else:
|
||||
cell_colour = Config.COLOUR_BITRATE_OK
|
||||
brush = QBrush(QColor(cell_colour))
|
||||
self.item(row, columns['bitrate'].idx).setBackground(brush)
|
||||
self.item(row, BITRATE).setBackground(brush)
|
||||
|
||||
# Render playing track
|
||||
if row == current_row:
|
||||
@ -1073,7 +1105,7 @@ class PlaylistTab(QTableWidget):
|
||||
self._set_row_start_time(
|
||||
row, self.current_track_start_time)
|
||||
# Set last played time to "Today"
|
||||
self.item(row, columns['lastplayed'].idx).setText("Today")
|
||||
self.item(row, LASTPLAYED).setText("Today")
|
||||
# Calculate next_start_time
|
||||
next_start_time = self._calculate_end_time(
|
||||
self.current_track_start_time, track.duration)
|
||||
@ -1114,7 +1146,7 @@ class PlaylistTab(QTableWidget):
|
||||
|
||||
if row in played:
|
||||
# Played today, so update last played column
|
||||
self.item(row, columns['lastplayed'].idx).setText(
|
||||
self.item(row, LASTPLAYED).setText(
|
||||
Config.LAST_PLAYED_TODAY_STRING)
|
||||
if self.musicmuster.hide_played_tracks:
|
||||
self.hideRow(row)
|
||||
@ -1146,6 +1178,11 @@ class PlaylistTab(QTableWidget):
|
||||
# Does it delimit a section?
|
||||
if section_start_plr is not None:
|
||||
if note_text.endswith("-"):
|
||||
log.debug(
|
||||
"line 1165: "
|
||||
f"self._update_note_text({section_start_plr=},"
|
||||
f"self._get_section_timing_string({section_time=})"
|
||||
)
|
||||
self._update_note_text(
|
||||
section_start_plr,
|
||||
self._get_section_timing_string(section_time)
|
||||
@ -1164,16 +1201,19 @@ class PlaylistTab(QTableWidget):
|
||||
|
||||
# Set row heights
|
||||
self.resizeRowsToContents()
|
||||
self.setColumnWidth(len(columns) - 1, 0)
|
||||
|
||||
# Have we had a section start but not end?
|
||||
if section_start_plr is not None:
|
||||
log.debug(
|
||||
"line 1191: "
|
||||
f"self._update_note_text({section_start_plr=},"
|
||||
f"self._get_section_timing_string({section_time=})"
|
||||
)
|
||||
self._update_note_text(
|
||||
section_start_plr,
|
||||
self._get_section_timing_string(section_time, no_end=True)
|
||||
)
|
||||
|
||||
#
|
||||
# # ########## Internally called functions ##########
|
||||
|
||||
def _add_track(self, row: int) -> None:
|
||||
@ -1189,17 +1229,14 @@ class PlaylistTab(QTableWidget):
|
||||
plr.track_id = track.id
|
||||
session.commit()
|
||||
# Update attributes of row
|
||||
self.item(row, columns["userdata"].idx).setData(
|
||||
self.ROW_TRACK_ID, track.id)
|
||||
self.item(row, columns["start_gap"].idx).setText(
|
||||
str(track.start_gap))
|
||||
self.item(row, columns["title"].idx).setText(str(track.title))
|
||||
self.item(row, columns["artist"].idx).setText(str(track.artist))
|
||||
self.item(row, columns["duration"].idx).setText(
|
||||
ms_to_mmss(track.duration))
|
||||
self.item(row, USERDATA).setData(self.ROW_TRACK_ID, track.id)
|
||||
self.item(row, START_GAP).setText(str(track.start_gap))
|
||||
self.item(row, TITLE).setText(str(track.title))
|
||||
self.item(row, ARTIST).setText(str(track.artist))
|
||||
self.item(row, DURATION).setText(ms_to_mmss(track.duration))
|
||||
last_playtime = Playdates.last_played(session, track.id)
|
||||
last_played_str = get_relative_date(last_playtime)
|
||||
self.item(row, columns['lastplayed'].idx).setText(last_played_str)
|
||||
self.item(row, LASTPLAYED).setText(last_played_str)
|
||||
|
||||
# Reset row span
|
||||
self.setSpan(row, 1, 1, 1)
|
||||
@ -1378,7 +1415,10 @@ class PlaylistTab(QTableWidget):
|
||||
def _get_note_text_time(text: str) -> Optional[datetime]:
|
||||
"""Return time specified as @hh:mm:ss in text"""
|
||||
|
||||
match = start_time_re.search(text)
|
||||
try:
|
||||
match = start_time_re.search(text)
|
||||
except TypeError:
|
||||
return None
|
||||
if not match:
|
||||
return None
|
||||
|
||||
@ -1391,8 +1431,7 @@ class PlaylistTab(QTableWidget):
|
||||
def _get_playlistrow_id(self, row: int) -> int:
|
||||
"""Return the playlistrow_id associated with this row"""
|
||||
|
||||
playlistrow_id = (self.item(row, columns['userdata'].idx)
|
||||
.data(self.PLAYLISTROW_ID))
|
||||
playlistrow_id = (self.item(row, USERDATA).data(self.PLAYLISTROW_ID))
|
||||
|
||||
return playlistrow_id
|
||||
|
||||
@ -1403,14 +1442,13 @@ class PlaylistTab(QTableWidget):
|
||||
if not track_id:
|
||||
return None
|
||||
|
||||
item_artist = self.item(row, columns['artist'].idx)
|
||||
item_artist = self.item(row, ARTIST)
|
||||
return item_artist.text()
|
||||
|
||||
def _get_row_duration(self, row: int) -> int:
|
||||
"""Return duration associated with this row"""
|
||||
|
||||
duration = (self.item(row, columns['userdata'].idx)
|
||||
.data(self.ROW_DURATION))
|
||||
duration = (self.item(row, USERDATA).data(self.ROW_DURATION))
|
||||
if duration:
|
||||
return duration
|
||||
else:
|
||||
@ -1421,16 +1459,16 @@ class PlaylistTab(QTableWidget):
|
||||
|
||||
track_id = self._get_row_track_id(row)
|
||||
if track_id:
|
||||
item_note = self.item(row, columns['row_notes'].idx)
|
||||
item_note = self.item(row, ROW_NOTES)
|
||||
else:
|
||||
item_note = self.item(row, HEADER_NOTES_COLUMN)
|
||||
return item_note.text()
|
||||
|
||||
def _get_row_start_time(self, row: int) -> Optional[datetime]:
|
||||
try:
|
||||
if self.item(row, columns['start_time'].idx):
|
||||
if self.item(row, START_TIME):
|
||||
return datetime.strptime(self.item(
|
||||
row, columns['start_time'].idx).text(),
|
||||
row, START_TIME).text(),
|
||||
Config.NOTE_TIME_FORMAT
|
||||
)
|
||||
else:
|
||||
@ -1445,14 +1483,14 @@ class PlaylistTab(QTableWidget):
|
||||
if not track_id:
|
||||
return None
|
||||
|
||||
item_title = self.item(row, columns['title'].idx)
|
||||
item_title = self.item(row, TITLE)
|
||||
return item_title.text()
|
||||
|
||||
def _get_row_track_id(self, row: int) -> int:
|
||||
"""Return the track_id associated with this row or None"""
|
||||
|
||||
try:
|
||||
track_id = (self.item(row, columns['userdata'].idx)
|
||||
track_id = (self.item(row, USERDATA)
|
||||
.data(self.ROW_TRACK_ID))
|
||||
except AttributeError:
|
||||
return None
|
||||
@ -1535,8 +1573,7 @@ class PlaylistTab(QTableWidget):
|
||||
raise ValueError(f"_meta_clear_attribute({row=}, {attribute=})")
|
||||
|
||||
new_metadata: int = self._meta_get(row) & ~(1 << attribute)
|
||||
self.item(row, columns['userdata'].idx).setData(
|
||||
self.ROW_FLAGS, new_metadata)
|
||||
self.item(row, USERDATA).setData(self.ROW_FLAGS, new_metadata)
|
||||
|
||||
def _meta_clear_next(self) -> None:
|
||||
"""
|
||||
@ -1550,8 +1587,7 @@ class PlaylistTab(QTableWidget):
|
||||
def _meta_get(self, row: int) -> int:
|
||||
"""Return row metadata"""
|
||||
|
||||
return (self.item(row, columns['userdata'].idx)
|
||||
.data(self.ROW_FLAGS))
|
||||
return (self.item(row, USERDATA).data(self.ROW_FLAGS))
|
||||
|
||||
def _meta_search(self, metadata: int, one: bool = True) -> List[int]:
|
||||
"""
|
||||
@ -1592,8 +1628,7 @@ class PlaylistTab(QTableWidget):
|
||||
new_metadata: int = (1 << attribute)
|
||||
else:
|
||||
new_metadata = self._meta_get(row) | (1 << attribute)
|
||||
self.item(row, columns['userdata'].idx).setData(
|
||||
self.ROW_FLAGS, new_metadata)
|
||||
self.item(row, USERDATA).setData(self.ROW_FLAGS, new_metadata)
|
||||
|
||||
def _mplayer_play(self, track_id: int) -> None:
|
||||
"""Play track with mplayer"""
|
||||
@ -1651,8 +1686,7 @@ class PlaylistTab(QTableWidget):
|
||||
# Remove row duration
|
||||
self._set_row_duration(row, 0)
|
||||
# Remote track_id from row
|
||||
self.item(row, columns['userdata'].idx).setData(
|
||||
self.ROW_TRACK_ID, 0)
|
||||
self.item(row, USERDATA).setData(self.ROW_TRACK_ID, 0)
|
||||
# Span the rows
|
||||
self.setSpan(row, 1, 1, len(columns))
|
||||
# And refresh display
|
||||
@ -1800,7 +1834,7 @@ class PlaylistTab(QTableWidget):
|
||||
boldfont = QFont()
|
||||
boldfont.setBold(bold)
|
||||
for column in range(self.columnCount()):
|
||||
if column == columns['row_notes'].idx:
|
||||
if column == ROW_NOTES:
|
||||
continue
|
||||
if self.item(row, column):
|
||||
self.item(row, column).setFont(boldfont)
|
||||
@ -1820,7 +1854,7 @@ class PlaylistTab(QTableWidget):
|
||||
|
||||
for column in range(1, self.columnCount()):
|
||||
# Don't change colour on start gap columns
|
||||
if column == columns['start_gap'].idx:
|
||||
if column == START_GAP:
|
||||
continue
|
||||
if self.item(row, column):
|
||||
self.item(row, column).setBackground(brush)
|
||||
@ -1828,7 +1862,7 @@ class PlaylistTab(QTableWidget):
|
||||
def _set_row_duration(self, row: int, ms: int) -> None:
|
||||
"""Set duration of this row in row metadata"""
|
||||
|
||||
self.item(row, columns['userdata'].idx).setData(self.ROW_DURATION, ms)
|
||||
self.item(row, USERDATA).setData(self.ROW_DURATION, ms)
|
||||
|
||||
def _set_row_end_time(self, row: int, time: Optional[datetime]) -> None:
|
||||
"""Set passed row end time to passed time"""
|
||||
@ -1838,7 +1872,7 @@ class PlaylistTab(QTableWidget):
|
||||
except AttributeError:
|
||||
time_str = ""
|
||||
item = QTableWidgetItem(time_str)
|
||||
self.setItem(row, columns['end_time'].idx, item)
|
||||
self.setItem(row, END_TIME, item)
|
||||
|
||||
def _set_row_not_bold(self, row: int) -> None:
|
||||
"""Set row to not be bold"""
|
||||
@ -1853,7 +1887,7 @@ class PlaylistTab(QTableWidget):
|
||||
except AttributeError:
|
||||
time_str = ""
|
||||
item = QTableWidgetItem(time_str)
|
||||
self.setItem(row, columns['start_time'].idx, item)
|
||||
self.setItem(row, START_TIME, item)
|
||||
|
||||
def _set_unreadable_row(self, row: int) -> None:
|
||||
"""Mark this row as unreadable"""
|
||||
@ -1884,7 +1918,7 @@ class PlaylistTab(QTableWidget):
|
||||
# Column to update is either HEADER_NOTES_COLUMN for a section
|
||||
# header or the appropriate row_notes column for a track row
|
||||
if playlist_row.track_id:
|
||||
column = columns['row_notes'].idx
|
||||
column = ROW_NOTES
|
||||
else:
|
||||
column = HEADER_NOTES_COLUMN
|
||||
|
||||
@ -1897,24 +1931,23 @@ class PlaylistTab(QTableWidget):
|
||||
Update the passed row with info from the passed track.
|
||||
"""
|
||||
|
||||
columns['start_time'].idx
|
||||
item_startgap = self.item(row, columns['start_gap'].idx)
|
||||
item_startgap = self.item(row, START_GAP)
|
||||
item_startgap.setText(str(track.start_gap))
|
||||
if track.start_gap >= 500:
|
||||
item_startgap.setBackground(QColor(Config.COLOUR_LONG_START))
|
||||
else:
|
||||
item_startgap.setBackground(QColor("white"))
|
||||
|
||||
item_title = self.item(row, columns['title'].idx)
|
||||
item_title = self.item(row, TITLE)
|
||||
item_title.setText(track.title)
|
||||
|
||||
item_artist = self.item(row, columns['artist'].idx)
|
||||
item_artist = self.item(row, ARTIST)
|
||||
item_artist.setText(track.artist)
|
||||
|
||||
item_duration = self.item(row, columns['duration'].idx)
|
||||
item_duration = self.item(row, DURATION)
|
||||
item_duration.setText(ms_to_mmss(track.duration))
|
||||
|
||||
item_bitrate = self.item(row, columns['bitrate'].idx)
|
||||
item_bitrate = self.item(row, BITRATE)
|
||||
item_bitrate.setText(str(track.bitrate))
|
||||
|
||||
self.update_display(session)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user