From 0418761a9d0542d6b5373a43573191e0d215b007 Mon Sep 17 00:00:00 2001 From: Dirk Alders Date: Sat, 2 Aug 2025 15:18:25 +0200 Subject: [PATCH] observation of eject and new disc added --- gui/__init__.py | 38 +++++++++++++++++-- pyripgui.py | 99 ++++++++++++++++++++++++++++--------------------- 2 files changed, 92 insertions(+), 45 deletions(-) diff --git a/gui/__init__.py b/gui/__init__.py index 38bb4b0..65fd9e0 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -1,5 +1,4 @@ import logging -import media from PySide6.QtWidgets import ( QMainWindow, QDialog, @@ -15,7 +14,8 @@ from PySide6.QtWidgets import ( QPushButton, QLineEdit ) -from PySide6.QtCore import Qt +from PySide6.QtCore import Qt, SIGNAL +import task try: from config import APP_NAME as ROOT_LOGGER_NAME @@ -36,7 +36,9 @@ class RowWidget(QWidget): self.number_label = QLabel(f"{number}.") self.text_edit = QPlainTextEdit() + self.text_edit.setTabChangesFocus(True) self.progress_bar = QProgressBar() + self.progress_bar.setMaximumWidth(150) self.text_edit.setFixedHeight(31) self.number_label.setFixedWidth(30) @@ -60,7 +62,9 @@ class MainWindow(QMainWindow): super().__init__() self.__basepath__ = basepath # - self.setWindowTitle("PySide6 Listenanwendung") + self.__rip_task__ = task.delayed(0, self.__rip_it__) + # + self.setWindowTitle("PyRip") self.setGeometry(100, 100, 900, 600) # Fensterbreite angepasst self.set_status("Ready...") @@ -108,6 +112,8 @@ class MainWindow(QMainWindow): self.button_rip.clicked.connect(self.rip_it) button_layout.addWidget(self.button_rip) + self.connect(self.list_widget, SIGNAL("itemDoubleClicked(QListWidgetItem *)"), self.single_track_selected) + def set_album_field(self, key, value): i = self.FIELD_NAMES.index(key) line = self.__album_lines__[i] @@ -142,8 +148,34 @@ class MainWindow(QMainWindow): print("read_it button action not yet implemented...") def rip_it(self): + self.__rip_task__.run() + + def __rip_it__(self): print("rip_it button action not yet implemented...") + def single_track_selected(self, list_item): + print("single_track_selected action not yet implemented...") + + def on_disc_removed(self, device): + self.clear() + + def on_disc_new(self, device): + self.read_it() + + def device_callback(self, device): + action = device.action + if 'ID_CDROM' in device and action == 'change': + if device.properties.get('ID_CDROM_MEDIA') is None: + self.on_disc_removed(device) + if int(device.properties.get('ID_CDROM_MEDIA_TRACK_COUNT_AUDIO', 0)) > 0: + self.on_disc_new(device) + + def join(self): + self.__rip_task__.join + + def stop(self): + self.__rip_task__.stop() + class SelectionDialog(QDialog): """ diff --git a/pyripgui.py b/pyripgui.py index a592a42..8098946 100644 --- a/pyripgui.py +++ b/pyripgui.py @@ -4,9 +4,10 @@ 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 -import task logger = report.app_logging_config() @@ -25,13 +26,6 @@ MEDIA_GUI_DICT = { class RipMainWindow(MainWindow): def __init__(self, basepath): super().__init__(basepath) - self.__rip_task__ = task.delayed(0, self.__rip_it__) - - def join(self): - self.__rip_task__.join - - def stop(self): - self.__rip_task__.stop() def clear(self): self.list_widget.clear() @@ -72,45 +66,49 @@ class RipMainWindow(MainWindow): self.set_status(msg) QMessageBox.critical(self, "Error!", msg) - def rip_it(self): - self.__rip_task__.run() + 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()): - list_item = self.list_widget.item(i) - row_widget = self.list_widget.itemWidget(list_item) - track_info = {} - track_info[media.KEY_TRACK] = i + 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..." % (i + 1)) - rv = media.disc_track_rip(i + 1, wavfile, self.progress_callback_rip) - if rv == 0: - self.set_status("Encoding track %02d..." % (i + 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 {i + 1}" - logger.error(msg) - self.set_status(msg) - self.set_title_progress(i, 0) - QMessageBox.critical(self, "Error!", msg) - self.button_rip.setDisabled(False) - self.button_read.setDisabled(False) + if self.rip_a_track(i) != 0: return self.set_status("Ripping finished!") self.button_rip.setDisabled(False) @@ -124,13 +122,30 @@ class RipMainWindow(MainWindow): 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()