musicmuster/app/musicmuster.py
2021-03-26 09:19:04 +00:00

178 lines
5.1 KiB
Python
Executable File

#!/usr/bin/python3
import vlc
import sys
from log import INFO, ERROR, DEBUG
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow
from PyQt5.QtWidgets import QTableWidgetItem, QFileDialog, QListWidgetItem
from threading import Timer
from tinytag import TinyTag
from ui.main_window_ui import Ui_MainWindow
from ui.dlg_search_database_ui import Ui_Dialog
from config import Config
from model import Tracks
class RepeatedTimer:
def __init__(self, interval, function, *args, **kwargs):
self._timer = None
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.is_running = False
self.start()
def _run(self):
self.is_running = False
self.start()
self.function(*self.args, **self.kwargs)
def start(self):
if not self.is_running:
self._timer = Timer(self.interval, self._run)
self._timer.start()
self.is_running = True
def stop(self):
self._timer.cancel()
self.is_running = False
def ms_to_mmss(ms, decimals=0):
if not ms:
return "-"
if ms < 0:
sign = "-"
else:
sign = ""
minutes, remainder = divmod(ms, 60 * 1000)
seconds = remainder / 1000
return f"{sign}{minutes:.0f}:{seconds:02.{decimals}f}"
class Window(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.connectSignalsSlots()
self.resize(1599, 981)
self.playlist.setColumnWidth(0, 0)
self.playlist.setColumnWidth(1, 70)
self.playlist.setColumnWidth(2, 381)
self.playlist.setColumnWidth(3, 322)
self.playlist.setColumnWidth(4, 78)
self.playlist.setColumnWidth(5, 68)
self.playlist.setColumnWidth(6, 47)
self.playlist.setColumnWidth(7, 577)
def __del__(self):
for column in range(self.playlist.columnCount()):
print(f"Column {column}: {self.playlist.columnWidth(column)}")
print(f"Window height: {self.height()} Window width: {self.width()}")
def connectSignalsSlots(self):
self.fileButton.clicked.connect(self.selectFile)
self.databaseButton.clicked.connect(self.selectDatabase)
self.actionPlay_selected.triggered.connect(self.play_selected)
def selectDatabase(self):
dlg = DbDialog(self)
dlg.exec()
def play_selected(self):
if self.playlist.selectionModel().hasSelection():
row = self.playlist.currentRow()
track_id = int(self.playlist.item(row, 0).text())
# TODO: get_path may raise exception
track_path = Tracks.get_path(track_id)
if track_path:
INFO(f"play: {track_path}")
player = vlc.MediaPlayer(track_path)
player.play()
def selectFile(self):
dlg = QFileDialog()
dlg.setFileMode(QFileDialog.ExistingFile)
dlg.setViewMode(QFileDialog.Detail)
dlg.setDirectory(Config.ROOT)
dlg.setNameFilter("Music files (*.flac *.mp3)")
if dlg.exec_():
pass
# TODO Add to database
# for fname in dlg.selectedFiles():
# track = Track(fname)
# self.add_to_playlist(track)
def add_to_playlist(self, track):
"""
Add track to playlist
track is an instance of Track
"""
pl = self.playlist
row = pl.rowCount()
pl.insertRow(row)
item = QTableWidgetItem(str(track.id))
pl.setItem(row, 0, item)
item = QTableWidgetItem(str(track.start_gap))
pl.setItem(row, 1, item)
item = QTableWidgetItem(track.title)
pl.setItem(row, 2, item)
item = QTableWidgetItem(track.artist)
pl.setItem(row, 3, item)
item = QTableWidgetItem(ms_to_mmss(track.duration))
pl.setItem(row, 4, item)
item = QTableWidgetItem(track.path)
pl.setItem(row, 7, item)
class DbDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.lineEdit.textEdited.connect(self.chars_typed)
self.ui.listWidget.itemDoubleClicked.connect(self.listdclick)
def chars_typed(self, s):
if len(s) >= 3:
matches = Tracks.search_titles(s)
self.ui.listWidget.clear()
if matches:
for track in matches:
t = QListWidgetItem()
t.setText(
f"{track.title} - {track.artist} "
f"[{ms_to_mmss(track.duration)}]"
)
t.setData(Qt.UserRole, track.id)
self.ui.listWidget.addItem(t)
def listdclick(self, entry):
track_id = entry.data(Qt.UserRole)
track = Tracks.track_from_id(track_id)
self.parent().add_to_playlist(track)
def main():
app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()