observation of eject and new disc added

This commit is contained in:
Dirk Alders 2025-08-02 15:18:25 +02:00
parent 7622f1fa38
commit 0418761a9d
2 changed files with 92 additions and 45 deletions

View File

@ -1,5 +1,4 @@
import logging import logging
import media
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QMainWindow, QMainWindow,
QDialog, QDialog,
@ -15,7 +14,8 @@ from PySide6.QtWidgets import (
QPushButton, QPushButton,
QLineEdit QLineEdit
) )
from PySide6.QtCore import Qt from PySide6.QtCore import Qt, SIGNAL
import task
try: try:
from config import APP_NAME as ROOT_LOGGER_NAME from config import APP_NAME as ROOT_LOGGER_NAME
@ -36,7 +36,9 @@ class RowWidget(QWidget):
self.number_label = QLabel(f"{number}.") self.number_label = QLabel(f"{number}.")
self.text_edit = QPlainTextEdit() self.text_edit = QPlainTextEdit()
self.text_edit.setTabChangesFocus(True)
self.progress_bar = QProgressBar() self.progress_bar = QProgressBar()
self.progress_bar.setMaximumWidth(150)
self.text_edit.setFixedHeight(31) self.text_edit.setFixedHeight(31)
self.number_label.setFixedWidth(30) self.number_label.setFixedWidth(30)
@ -60,7 +62,9 @@ class MainWindow(QMainWindow):
super().__init__() super().__init__()
self.__basepath__ = basepath 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.setGeometry(100, 100, 900, 600) # Fensterbreite angepasst
self.set_status("Ready...") self.set_status("Ready...")
@ -108,6 +112,8 @@ class MainWindow(QMainWindow):
self.button_rip.clicked.connect(self.rip_it) self.button_rip.clicked.connect(self.rip_it)
button_layout.addWidget(self.button_rip) 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): def set_album_field(self, key, value):
i = self.FIELD_NAMES.index(key) i = self.FIELD_NAMES.index(key)
line = self.__album_lines__[i] line = self.__album_lines__[i]
@ -142,8 +148,34 @@ class MainWindow(QMainWindow):
print("read_it button action not yet implemented...") print("read_it button action not yet implemented...")
def rip_it(self): def rip_it(self):
self.__rip_task__.run()
def __rip_it__(self):
print("rip_it button action not yet implemented...") 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): class SelectionDialog(QDialog):
""" """

View File

@ -4,9 +4,10 @@ from gui import MainWindow, SelectionDialog
import media import media
import os import os
from PySide6.QtWidgets import QApplication, QMessageBox from PySide6.QtWidgets import QApplication, QMessageBox
import pyudev
from pyudev.pyside6 import MonitorObserver
import report import report
import sys import sys
import task
logger = report.app_logging_config() logger = report.app_logging_config()
@ -25,13 +26,6 @@ MEDIA_GUI_DICT = {
class RipMainWindow(MainWindow): class RipMainWindow(MainWindow):
def __init__(self, basepath): def __init__(self, basepath):
super().__init__(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): def clear(self):
self.list_widget.clear() self.list_widget.clear()
@ -72,45 +66,49 @@ class RipMainWindow(MainWindow):
self.set_status(msg) self.set_status(msg)
QMessageBox.critical(self, "Error!", msg) QMessageBox.critical(self, "Error!", msg)
def rip_it(self): def single_track_selected(self, list_item):
self.__rip_task__.run() 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): def __rip_it__(self):
self.button_rip.setDisabled(True) self.button_rip.setDisabled(True)
self.button_read.setDisabled(True) self.button_read.setDisabled(True)
for i in range(self.list_widget.count()): for i in range(self.list_widget.count()):
list_item = self.list_widget.item(i) if self.rip_a_track(i) != 0:
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)
return return
self.set_status("Ripping finished!") self.set_status("Ripping finished!")
self.button_rip.setDisabled(False) self.button_rip.setDisabled(False)
@ -124,13 +122,30 @@ class RipMainWindow(MainWindow):
if __name__ == "__main__": if __name__ == "__main__":
#
# Command line arguments
#
default_baspath = os.path.join(os.getenv("HOME"), "pyrip") default_baspath = os.path.join(os.getenv("HOME"), "pyrip")
parser = argparse.ArgumentParser(description='Description') parser = argparse.ArgumentParser(description='Description')
parser.add_argument('-b', '--basepath', help=f'The rip and encode basepath (default is {default_baspath})', default=default_baspath) parser.add_argument('-b', '--basepath', help=f'The rip and encode basepath (default is {default_baspath})', default=default_baspath)
args = parser.parse_args() args = parser.parse_args()
# #
# Initialise GUI
#
app = QApplication(sys.argv) app = QApplication(sys.argv)
window = RipMainWindow(args.basepath) 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() window.show()
try: try:
window.join() window.join()