| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- """
- Device Panel — UI for selecting audio input/output devices.
- """
- from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout,
- QLabel, QComboBox, QPushButton, QGroupBox,
- QMessageBox)
- from PyQt6.QtCore import pyqtSignal
- from core.audio_device import DeviceManager
- class DevicePanel(QWidget):
- # Signal emitted when devices are successfully applied
- devices_changed = pyqtSignal()
-
- def __init__(self, device_manager: DeviceManager):
- super().__init__()
- self.device_manager = device_manager
- self._init_ui()
- self.refresh_device_lists()
-
- def _init_ui(self):
- layout = QVBoxLayout()
- layout.setSpacing(20)
-
- # --- Audio Hardware Settings Group ---
- hw_group = QGroupBox("Audio Hardware Setup")
- hw_layout = QVBoxLayout()
-
- # Info text
- info_lbl = QLabel(
- "Select the sound card inputs and outputs connected to your cassette deck.\n"
- "• Connect PC Output to Tape Deck REC IN\n"
- "• Connect Tape Deck PLAY OUT to PC Input"
- )
- info_lbl.setWordWrap(True)
- info_lbl.setStyleSheet("color: #a0a0b0; font-style: italic; margin-bottom: 10px;")
- hw_layout.addWidget(info_lbl)
-
- # Input Device Row
- in_row = QHBoxLayout()
- in_lbl = QLabel("Recording Input (From Tape):")
- in_lbl.setFixedWidth(180)
- self.in_combo = QComboBox()
- self.in_combo.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToContents)
- in_row.addWidget(in_lbl)
- in_row.addWidget(self.in_combo, 1)
- hw_layout.addLayout(in_row)
-
- # Output Device Row
- out_row = QHBoxLayout()
- out_lbl = QLabel("Playback Output (To Tape):")
- out_lbl.setFixedWidth(180)
- self.out_combo = QComboBox()
- self.out_combo.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToContents)
- out_row.addWidget(out_lbl)
- out_row.addWidget(self.out_combo, 1)
- hw_layout.addLayout(out_row)
-
- # Sample Rate Row
- sr_row = QHBoxLayout()
- sr_lbl = QLabel("Sample Rate:")
- sr_lbl.setFixedWidth(180)
- self.sr_combo = QComboBox()
- self.sr_combo.addItems(["44100 Hz", "48000 Hz", "96000 Hz"])
- self.sr_combo.setCurrentText("44100 Hz")
- sr_row.addWidget(sr_lbl)
- sr_row.addWidget(self.sr_combo)
- sr_row.addStretch()
- hw_layout.addLayout(sr_row)
-
- hw_group.setLayout(hw_layout)
- layout.addWidget(hw_group)
-
- # --- Actions Row ---
- action_row = QHBoxLayout()
-
- self.refresh_btn = QPushButton("Refresh Devices")
- self.refresh_btn.clicked.connect(self.refresh_device_lists)
-
- self.apply_btn = QPushButton("Apply Settings")
- self.apply_btn.setObjectName("primaryButton")
- self.apply_btn.clicked.connect(self.apply_settings)
-
- action_row.addWidget(self.refresh_btn)
- action_row.addStretch()
- action_row.addWidget(self.apply_btn)
-
- layout.addLayout(action_row)
- layout.addStretch()
-
- self.setLayout(layout)
- def refresh_device_lists(self):
- """Update the dropdowns with available devices."""
- self.device_manager.refresh_devices()
-
- self.in_combo.clear()
- for dev in self.device_manager.get_input_devices():
- self.in_combo.addItem(str(dev), dev.index)
-
- self.out_combo.clear()
- for dev in self.device_manager.get_output_devices():
- self.out_combo.addItem(str(dev), dev.index)
-
- # Try to select current if set
- if self.device_manager.input_device_id is not None:
- idx = self.in_combo.findData(self.device_manager.input_device_id)
- if idx >= 0:
- self.in_combo.setCurrentIndex(idx)
-
- if self.device_manager.output_device_id is not None:
- idx = self.out_combo.findData(self.device_manager.output_device_id)
- if idx >= 0:
- self.out_combo.setCurrentIndex(idx)
- def apply_settings(self):
- """Apply selected devices to the DeviceManager."""
- in_idx = self.in_combo.currentData()
- out_idx = self.out_combo.currentData()
-
- sr_str = self.sr_combo.currentText().split()[0]
- sr = int(sr_str)
-
- try:
- if in_idx is not None:
- self.device_manager.input_device_id = in_idx
- if out_idx is not None:
- self.device_manager.output_device_id = out_idx
-
- self.device_manager.sample_rate = sr
-
- self.devices_changed.emit()
-
- # Change button appearance briefly to show success
- original_text = self.apply_btn.text()
- self.apply_btn.setText("Applied ✓")
- self.apply_btn.setStyleSheet("background-color: #4CAF50; color: white;")
-
- # Reset after 2 seconds
- import PyQt6.QtCore as QtCore
- QtCore.QTimer.singleShot(2000, lambda: self._reset_apply_btn(original_text))
-
- except Exception as e:
- QMessageBox.critical(self, "Device Error", f"Failed to apply audio settings:\n{str(e)}")
-
- def _reset_apply_btn(self, text):
- self.apply_btn.setText(text)
- self.apply_btn.setStyleSheet("") # Revert to stylesheet default
|