Overhaul: 5-task implementation
- Remove TURN decks (3/4), clean up MIDI, layout - Single cart player with 3-item autoload queue + continue toggle - Event logging (SessionLogger), mic tracking, large mic timer widget - LUFS metering moved from external ports to internal master mix - Master output WAV recording with top-bar REC toggle - Music mix output (ch 3-8 only, no mics) - Preview bar for playlist auditioning - Merged show log with [SONG][CART][TALK] prefixes - Live CSV writer for OBS song display (~/live_songs.csv) - Misc fixes: preview race condition, datetime import for recording
This commit is contained in:
@@ -16,12 +16,13 @@ from PySide6.QtGui import QFont, QColor, QPalette
|
||||
|
||||
from audio_engine import AudioEngine
|
||||
from deck_widget import DeckWidget
|
||||
from cart_widget import CartBankWidget
|
||||
from cart_widget import CartPlayerWidget
|
||||
from playlist_widget import PlaylistWidget
|
||||
from midi_engine import MidiEngine
|
||||
from top_bar_widget import TopBarWidget, THEMES
|
||||
from history_widget import HistoryWidget
|
||||
from mixer_widget import MixerWidget
|
||||
from history_widget import ShowHistoryWidget
|
||||
from mixer_widget import MixerWidget, MicTimerWidget, LUFSExpandedSection
|
||||
from event_logger import SessionLogger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -31,6 +32,8 @@ class RadioPanelWindow(QMainWindow):
|
||||
super().__init__()
|
||||
|
||||
self.engine = AudioEngine()
|
||||
self.session_logger = SessionLogger()
|
||||
self.engine.logger = self.session_logger
|
||||
|
||||
self.setWindowTitle(f"Getting To It v{__version__}")
|
||||
self.setMinimumSize(1400, 860)
|
||||
@@ -50,17 +53,19 @@ class RadioPanelWindow(QMainWindow):
|
||||
self.top_bar.ratio_changed.connect(self._apply_ratio)
|
||||
self.top_bar.save_session.connect(self._save_session)
|
||||
self.top_bar.load_session.connect(self._load_session)
|
||||
self.top_bar.recording_toggled.connect(self._on_recording_toggled)
|
||||
outer.addWidget(self.top_bar)
|
||||
|
||||
# ── Build widgets ─────────────────────────────────────────────────
|
||||
|
||||
self.deck1 = DeckWidget("deck1", "DECK_001", "#00b894", self.engine, mode='deck')
|
||||
self.deck2 = DeckWidget("deck2", "DECK_002", "#6c5ce7", self.engine, mode='deck')
|
||||
self.deck3 = DeckWidget("deck3", "TURN_001", "#fdcb6e", self.engine, mode='turn')
|
||||
self.deck4 = DeckWidget("deck4", "TURN_002", "#e17055", self.engine, mode='turn')
|
||||
|
||||
self.cart_bank = CartBankWidget(self.engine)
|
||||
self.cart_bank.setFixedHeight(150)
|
||||
self.cart_player = CartPlayerWidget(self.engine)
|
||||
self.cart_player.setFixedHeight(160)
|
||||
|
||||
self.mic_timer = MicTimerWidget(self.engine)
|
||||
self.lufs_section = LUFSExpandedSection(self.engine)
|
||||
|
||||
self.playlist_widget = PlaylistWidget(
|
||||
engine=self.engine,
|
||||
@@ -68,10 +73,11 @@ class RadioPanelWindow(QMainWindow):
|
||||
"deck1": self.deck1,
|
||||
"deck2": self.deck2,
|
||||
},
|
||||
cart_slots=self.cart_bank.slots
|
||||
cart_player=self.cart_player
|
||||
)
|
||||
|
||||
self.history_widget = HistoryWidget()
|
||||
self.history_widget = ShowHistoryWidget()
|
||||
self.history_widget.set_engine(self.engine)
|
||||
|
||||
self.mixer = MixerWidget(self.engine)
|
||||
|
||||
@@ -79,7 +85,7 @@ class RadioPanelWindow(QMainWindow):
|
||||
centre_col = QVBoxLayout()
|
||||
centre_col.setSpacing(6)
|
||||
|
||||
# Top: 4 decks in 2x2 grid + carts
|
||||
# Top: 2 decks + cart
|
||||
deck_area = QWidget()
|
||||
deck_area.setStyleSheet("background: transparent; border: none;")
|
||||
deck_layout = QVBoxLayout(deck_area)
|
||||
@@ -92,13 +98,15 @@ class RadioPanelWindow(QMainWindow):
|
||||
deck_row1.addWidget(self.deck2)
|
||||
deck_layout.addLayout(deck_row1)
|
||||
|
||||
deck_row2 = QHBoxLayout()
|
||||
deck_row2.setSpacing(4)
|
||||
deck_row2.addWidget(self.deck3)
|
||||
deck_row2.addWidget(self.deck4)
|
||||
deck_layout.addLayout(deck_row2)
|
||||
|
||||
deck_layout.addWidget(self.cart_bank)
|
||||
cart_row = QHBoxLayout()
|
||||
cart_row.setSpacing(4)
|
||||
cart_row.addWidget(self.cart_player)
|
||||
mic_lufs_row = QHBoxLayout()
|
||||
mic_lufs_row.setSpacing(4)
|
||||
mic_lufs_row.addWidget(self.mic_timer, stretch=1)
|
||||
mic_lufs_row.addWidget(self.lufs_section, stretch=1)
|
||||
cart_row.addLayout(mic_lufs_row)
|
||||
deck_layout.addLayout(cart_row)
|
||||
|
||||
# Mixer fills remaining space below decks
|
||||
centre_col.addWidget(deck_area)
|
||||
@@ -121,10 +129,9 @@ class RadioPanelWindow(QMainWindow):
|
||||
outer.addWidget(self.splitter)
|
||||
|
||||
# ── Wire signals ─────────────────────────────────────────────────
|
||||
self.deck1.track_started.connect(self.history_widget.add_track)
|
||||
self.deck2.track_started.connect(self.history_widget.add_track)
|
||||
self.deck3.track_started.connect(self.history_widget.add_track)
|
||||
self.deck4.track_started.connect(self.history_widget.add_track)
|
||||
self.deck1.track_started.connect(self.history_widget.add_song)
|
||||
self.deck2.track_started.connect(self.history_widget.add_song)
|
||||
self.cart_player.cart_triggered.connect(self.history_widget.add_cart)
|
||||
|
||||
# ── MIDI ──────────────────────────────────────────────────────────
|
||||
self._setup_midi()
|
||||
@@ -148,11 +155,11 @@ class RadioPanelWindow(QMainWindow):
|
||||
self._style_splitter(theme)
|
||||
self.deck1.apply_theme(theme)
|
||||
self.deck2.apply_theme(theme)
|
||||
self.deck3.apply_theme(theme)
|
||||
self.deck4.apply_theme(theme)
|
||||
self.cart_bank.apply_theme(theme)
|
||||
self.cart_player.apply_theme(theme)
|
||||
self.history_widget.apply_theme(theme)
|
||||
self.mixer.apply_theme(theme)
|
||||
self.mic_timer.apply_theme(theme)
|
||||
self.lufs_section.apply_theme(theme)
|
||||
|
||||
def _apply_ratio(self, w, h):
|
||||
self.resize(w, h)
|
||||
@@ -265,10 +272,6 @@ class RadioPanelWindow(QMainWindow):
|
||||
self.deck1.toggle_play()
|
||||
elif deck == 'deck2':
|
||||
self.deck2.toggle_play()
|
||||
elif deck == 'deck3':
|
||||
self.deck3.toggle_play()
|
||||
elif deck == 'deck4':
|
||||
self.deck4.toggle_play()
|
||||
|
||||
def _on_midi_cue(self, deck: str):
|
||||
if deck == 'deck1':
|
||||
@@ -283,7 +286,7 @@ class RadioPanelWindow(QMainWindow):
|
||||
self.deck2.scrub(delta)
|
||||
|
||||
def _on_midi_cart(self, slot: int):
|
||||
self.cart_bank.slots[slot].toggle()
|
||||
self.cart_player.toggle()
|
||||
|
||||
def _on_midi_mixer_volume(self, channel: int, value: float):
|
||||
self.engine.set_channel_volume(channel, value)
|
||||
@@ -320,6 +323,12 @@ class RadioPanelWindow(QMainWindow):
|
||||
self.engine.shutdown()
|
||||
event.accept()
|
||||
|
||||
def _on_recording_toggled(self, checked):
|
||||
if checked:
|
||||
self.engine.start_recording()
|
||||
else:
|
||||
self.engine.stop_recording()
|
||||
|
||||
|
||||
def main():
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
Reference in New Issue
Block a user