Compare commits

...

4 Commits

Author SHA1 Message Date
Keith Edmunds
04788ef923 Implement copy track path
Fixes #30
2021-08-21 22:58:01 +01:00
Keith Edmunds
79f9a49659 Remove debug statement 2021-08-21 22:44:14 +01:00
Keith Edmunds
834ad68e00 Tab info for previous / current / next track 2021-08-21 20:47:55 +01:00
Keith Edmunds
8fa85dd47f Import multiple tracks from command line 2021-08-21 18:14:47 +01:00
5 changed files with 83 additions and 10 deletions

View File

@ -22,6 +22,7 @@ class Config(object):
ERRORS_TO = ['kae@midnighthax.com'] ERRORS_TO = ['kae@midnighthax.com']
FADE_STEPS = 20 FADE_STEPS = 20
FADE_TIME = 3000 FADE_TIME = 3000
INFO_TAB_TITLE_LENGTH = 15
LOG_LEVEL_STDERR = logging.INFO LOG_LEVEL_STDERR = logging.INFO
LOG_LEVEL_SYSLOG = logging.DEBUG LOG_LEVEL_SYSLOG = logging.DEBUG
LOG_NAME = "musicmuster" LOG_NAME = "musicmuster"
@ -30,6 +31,7 @@ class Config(object):
MAIL_SERVER = os.environ.get('MAIL_SERVER') or "woodlands.midnighthax.com" MAIL_SERVER = os.environ.get('MAIL_SERVER') or "woodlands.midnighthax.com"
MAIL_USERNAME = os.environ.get('MAIL_USERNAME') MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS') is not None MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS') is not None
MAX_INFO_TABS = 3
MILLISECOND_SIGFIGS = 0 MILLISECOND_SIGFIGS = 0
MYSQL_CONNECT = os.environ.get('MYSQL_CONNECT') or "mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_dev" # noqa E501 MYSQL_CONNECT = os.environ.get('MYSQL_CONNECT') or "mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_dev" # noqa E501
NORMALISE_ON_IMPORT = True NORMALISE_ON_IMPORT = True

View File

@ -9,8 +9,9 @@ import urllib.parse
from datetime import datetime, timedelta from datetime import datetime, timedelta
from log import DEBUG, EXCEPTION from log import DEBUG, EXCEPTION
from PyQt5.QtCore import Qt, QTimer from PyQt5.QtCore import Qt, QTimer, QUrl
from PyQt5.QtGui import QFontMetrics, QPainter from PyQt5.QtGui import QFontMetrics, QPainter
from PyQt5.QtWebEngineWidgets import QWebEngineView as QWebView
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QApplication, QApplication,
QDialog, QDialog,
@ -63,6 +64,7 @@ class Window(QMainWindow, Ui_MainWindow):
self.music = music.Music() self.music = music.Music()
self.current_track = None self.current_track = None
self.current_track_playlist_tab = None self.current_track_playlist_tab = None
self.info_tabs = {}
self.next_track = None self.next_track = None
self.next_track_playlist_tab = None self.next_track_playlist_tab = None
self.previous_track = None self.previous_track = None
@ -263,6 +265,41 @@ class Window(QMainWindow, Ui_MainWindow):
# Enable controls # Enable controls
self.enable_play_next_controls() self.enable_play_next_controls()
def ensure_info_tabs(self, title_list):
"""
Ensure we have info tabs for each of the passed titles
"""
for title in title_list:
if title in self.info_tabs.keys():
# We already have a tab for this track
continue
if len(self.info_tabs) >= Config.MAX_INFO_TABS:
# Find an unneeded info tab
try:
old_title = list(
set(self.info_tabs.keys()) - set(title_list)
)[0]
except IndexError:
DEBUG(
f"ensure_info_tabs({title_list}): unable to add "
f"{title=}"
)
return
# Assign redundant widget a new title
widget = self.info_tabs[title] = self.info_tabs[old_title]
idx = self.tabPlaylist.indexOf(widget)
self.tabPlaylist.setTabText(
idx, title[:Config.INFO_TAB_TITLE_LENGTH])
del self.info_tabs[old_title]
else:
widget = self.info_tabs[title] = QWebView()
self.tabPlaylist.addTab(
widget, title[:Config.INFO_TAB_TITLE_LENGTH])
str = urllib.parse.quote_plus(title)
url = f"https://www.wikipedia.org/w/index.php?search={str}"
widget.setUrl(QUrl(url))
def export_playlist_tab(self): def export_playlist_tab(self):
"Export the current playlist to an m3u file" "Export the current playlist to an m3u file"
@ -667,32 +704,39 @@ class Window(QMainWindow, Ui_MainWindow):
self.stop_playing() self.stop_playing()
def update_headers(self): def update_headers(self):
"Update last / current / next track headers" """
Update last / current / next track headers.
Ensure a Wikipedia tab for each title.
"""
titles = []
try: try:
self.hdrPreviousTrack.setText( self.hdrPreviousTrack.setText(
f"{self.previous_track.title} - " f"{self.previous_track.title} - {self.previous_track.artist}"
f"{self.previous_track.artist}"
) )
titles.append(self.previous_track.title)
except AttributeError: except AttributeError:
self.hdrPreviousTrack.setText("") self.hdrPreviousTrack.setText("")
try: try:
self.hdrCurrentTrack.setText( self.hdrCurrentTrack.setText(
f"{self.current_track.title} - " f"{self.current_track.title} - {self.current_track.artist}"
f"{self.current_track.artist}"
) )
titles.append(self.current_track.title)
except AttributeError: except AttributeError:
self.hdrCurrentTrack.setText("") self.hdrCurrentTrack.setText("")
try: try:
self.hdrNextTrack.setText( self.hdrNextTrack.setText(
f"{self.next_track.title} - " f"{self.next_track.title} - {self.next_track.artist}"
f"{self.next_track.artist}"
) )
titles.append(self.next_track.title)
except AttributeError: except AttributeError:
self.hdrNextTrack.setText("") self.hdrNextTrack.setText("")
self.ensure_info_tabs(titles)
class DbDialog(QDialog): class DbDialog(QDialog):
def __init__(self, parent, session): def __init__(self, parent, session):

View File

@ -5,6 +5,7 @@ from PyQt5.QtGui import QColor, QDropEvent
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QAbstractItemView, QAbstractItemView,
QApplication,
QMenu, QMenu,
QMessageBox, QMessageBox,
QTableWidget, QTableWidget,
@ -154,6 +155,9 @@ class PlaylistTab(QTableWidget):
if row not in self._meta_get_notes(): if row not in self._meta_get_notes():
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.triggered.connect(
lambda: self._copy_path(row))
self.menu.addSeparator() self.menu.addSeparator()
act_delete = self.menu.addAction('Delete') act_delete = self.menu.addAction('Delete')
act_delete.triggered.connect(lambda: self._delete_row(row)) act_delete.triggered.connect(lambda: self._delete_row(row))
@ -545,6 +549,25 @@ class PlaylistTab(QTableWidget):
self.menu.exec_(self.mapToGlobal(pos)) self.menu.exec_(self.mapToGlobal(pos))
def _copy_path(self, row):
"""
If passed row is track row, copy the track path to the clipboard.
Otherwise return None.
"""
DEBUG(f"_copy_path({row})")
if row in self._meta_get_notes():
return None
track_id = self._get_row_id(row)
if track_id:
with Session() as session:
path = Tracks.get_path(session, track_id)
cb = QApplication.clipboard()
cb.clear(mode=cb.Clipboard)
cb.setText(path, mode=cb.Clipboard)
def _delete_row(self, row): def _delete_row(self, row):
"Delete row" "Delete row"

View File

@ -62,7 +62,9 @@ def create_track_from_file(session, path, verbose=False):
""" """
if verbose: if verbose:
INFO(f"Importing {path}...") str = f"Importing {path}"
INFO(str)
INFO("-" * len(str))
track = Tracks.get_or_create(session, path) track = Tracks.get_or_create(session, path)
if verbose: if verbose:
INFO("Get track info...") INFO("Get track info...")

View File

@ -1,4 +1,6 @@
#!/bin/bash #!/bin/bash
# cd /home/kae/mm # cd /home/kae/mm
# MYSQL_CONNECT="mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_prod" ROOT="/home/kae/music" direnv exec . # MYSQL_CONNECT="mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_prod" ROOT="/home/kae/music" direnv exec .
app/songdb.py -i "$1" for file in "$@"; do
app/songdb.py -i "$file"
done