pyrip/pyripgui.py

156 lines
5.4 KiB
Python

import argparse
import fstools
from gui import MainWindow, SelectionDialog
import media
import os
from PySide6.QtWidgets import QApplication, QMessageBox
import pyudev
from pyudev.pyside6 import MonitorObserver
import report
import sys
logger = report.app_logging_config()
# TODO: Usage of QThread instead of task.delayed
# TODO: Error handling on cancelling cddb choose Dialog
MEDIA_GUI_DICT = {
MainWindow.KEY_ALBUM_ARTIST: media.KEY_ARTIST,
MainWindow.KEY_ALBUM_ALBUM: media.KEY_ALBUM,
MainWindow.KEY_ALBUM_YEAR: media.KEY_YEAR,
MainWindow.KEY_ALBUM_GENRE: media.KEY_GENRE
}
class RipMainWindow(MainWindow):
def __init__(self, basepath):
super().__init__(basepath)
def clear(self):
self.list_widget.clear()
for key in MEDIA_GUI_DICT:
self.set_album_field(key, "")
def read_it(self):
self.set_status("Reading data from disc...")
disc_data = media.get_media_data(media.get_disc_device(), self.cddb_choose_dialog)
# disc_data = media.metadata.get_disc_data_dummy()
if disc_data is None:
msg = "Could not read disc data!"
logger.error(msg)
self.set_status(msg)
QMessageBox.critical(self, "Error!", msg)
else:
self.clear()
# Set album info to gui
for key in MEDIA_GUI_DICT:
self.set_album_field(key, str(disc_data[MEDIA_GUI_DICT[key]]))
# Set tracks to gui
for track in disc_data[media.KEY_TRACKLIST]:
self.append_title(track[media.KEY_TITLE])
# Enable rip button
self.set_status("Disc data received")
self.button_rip.setEnabled(True)
def cddb_choose_dialog(self, what: int, info: dict):
if what == media.CALLBACK_CDDB_CHOICE:
values = tuple(info.values())
keys = tuple(info.keys())
dlg = SelectionDialog(self, "Multiple CDDB entries found. Choose one.", values)
if dlg.exec():
return keys[dlg.get_selected_index()]
else:
msg = "Invalid cddb selection!"
logger.error(msg)
self.set_status(msg)
QMessageBox.critical(self, "Error!", msg)
def single_track_selected(self, list_item):
self.rip_a_track(self.list_widget.row(list_item))
def rip_a_track(self, track_num):
list_item = self.list_widget.item(track_num)
row_widget = self.list_widget.itemWidget(list_item)
track_info = {}
track_info[media.KEY_TRACK] = track_num + 1
for key in MEDIA_GUI_DICT:
track_info[MEDIA_GUI_DICT[key]] = self.get_album_field(key)
track_info[media.KEY_TITLE] = row_widget.text_edit.toPlainText()
wavfile = media.track_to_targetpath(self.__basepath__, track_info, 'wav')
try:
fstools.mkdir(os.path.dirname(wavfile))
except PermissionError:
msg = f"Unable to create ripping target path: {os.path.dirname(wavfile)}"
logger.exception(msg)
self.set_status(msg)
QMessageBox.critical(self, "Error!", msg)
self.button_rip.setDisabled(False)
self.button_read.setDisabled(False)
return
self.set_status("Ripping track %02d..." % (track_num + 1))
rv = media.disc_track_rip(track_num + 1, wavfile, self.progress_callback_rip)
if rv == 0:
self.set_status("Encoding track %02d..." % (track_num + 1))
rv = media.wav_to_mp3(wavfile, self.__basepath__, track_info, self.progress_callback_enc)
os.remove(wavfile)
if rv != 0:
msg = f"Error while ripping or encoding track {track_num + 1}"
logger.error(msg)
self.set_status(msg)
self.set_title_progress(track_num, 0)
QMessageBox.critical(self, "Error!", msg)
self.button_rip.setDisabled(False)
self.button_read.setDisabled(False)
return rv
def __rip_it__(self):
self.button_rip.setDisabled(True)
self.button_read.setDisabled(True)
for i in range(self.list_widget.count()):
if self.rip_a_track(i) != 0:
return
self.set_status("Ripping finished!")
self.button_rip.setDisabled(False)
self.button_read.setDisabled(False)
def progress_callback_rip(self, p: float, track_num: int = None):
self.set_title_progress(track_num - 1, 50 * p)
def progress_callback_enc(self, p: float, track_num: int = None):
self.set_title_progress(track_num - 1, 50 + 50 * p)
if __name__ == "__main__":
#
# Command line arguments
#
default_baspath = os.path.join(os.getenv("HOME"), "pyrip")
parser = argparse.ArgumentParser(description='Description')
parser.add_argument('-b', '--basepath', help=f'The rip and encode basepath (default is {default_baspath})', default=default_baspath)
args = parser.parse_args()
#
# Initialise GUI
#
app = QApplication(sys.argv)
window = RipMainWindow(args.basepath)
#
# Start media observer
#
context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
observer = MonitorObserver(monitor)
observer.deviceEvent.connect(window.device_callback)
observer.daemon = True
monitor.start()
#
# Start GUI
#
window.show()
try:
window.join()
finally:
window.stop()
sys.exit(app.exec())