Files
gti_radiostudio/main.py
T

239 lines
7.9 KiB
Python
Raw Normal View History

2026-04-29 16:21:44 +10:00
# main.py
import sys
from PySide6.QtWidgets import (
QApplication, QMainWindow, QWidget,
QVBoxLayout, QHBoxLayout, QSplitter
)
from PySide6.QtCore import Qt
from PySide6.QtGui import QFont, QColor, QPalette
from audio_engine import AudioEngine
from deck_widget import DeckWidget
from cart_widget import CartBankWidget
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
2026-04-29 16:21:44 +10:00
class RadioPanelWindow(QMainWindow):
def __init__(self):
super().__init__()
self.engine = AudioEngine()
self.setWindowTitle("Getting To It")
2026-04-29 16:21:44 +10:00
self.setMinimumSize(1280, 720)
self.resize(1920, 1080)
self._apply_global_style(THEMES[0])
central = QWidget()
self.setCentralWidget(central)
outer = QVBoxLayout(central)
outer.setContentsMargins(8, 8, 8, 8)
outer.setSpacing(8)
# Top bar
self.top_bar = TopBarWidget()
self.top_bar.theme_changed.connect(self._on_theme_changed)
outer.addWidget(self.top_bar)
# ── Build widgets ─────────────────────────────────────────────────
self.deck1 = DeckWidget(
deck_key="deck1",
label="DECK 1",
accent_color="#00897b",
engine=self.engine
)
self.deck2 = DeckWidget(
deck_key="deck2",
label="DECK 2",
accent_color="#f9ca24",
engine=self.engine
)
self.cart_bank = CartBankWidget(self.engine)
self.cart_bank.setFixedHeight(280)
self.playlist_widget = PlaylistWidget(
engine=self.engine,
deck_widgets={
"deck1": self.deck1,
"deck2": self.deck2,
},
cart_slots=self.cart_bank.slots
)
self.history_widget = HistoryWidget()
self.mixer = MixerWidget(self.engine)
2026-04-29 16:21:44 +10:00
# ── Centre column (decks + carts + mixer) ─────────────────────────
centre_col = QVBoxLayout()
2026-04-29 16:21:44 +10:00
centre_col.setSpacing(8)
# Top: decks row + carts
deck_area = QWidget()
deck_area.setStyleSheet("background: transparent; border: none;")
deck_layout = QVBoxLayout(deck_area)
deck_layout.setContentsMargins(0, 0, 0, 0)
deck_layout.setSpacing(8)
2026-04-30 00:30:23 +10:00
2026-04-29 16:21:44 +10:00
deck_row = QHBoxLayout()
deck_row.setSpacing(8)
deck_row.addWidget(self.deck1)
deck_row.addWidget(self.deck2)
deck_layout.addLayout(deck_row)
deck_layout.addWidget(self.cart_bank)
deck_layout.addStretch()
2026-04-30 00:30:23 +10:00
# Bottom: mixer
centre_col.addWidget(deck_area, stretch=1)
centre_col.addWidget(self.mixer)
2026-04-29 16:21:44 +10:00
centre_widget = QWidget()
centre_widget.setStyleSheet("background: transparent; border: none;")
centre_widget.setLayout(centre_col)
# ── Splitter ──────────────────────────────────────────────────────
self.splitter = QSplitter(Qt.Horizontal)
self.splitter.setHandleWidth(6)
self._style_splitter(THEMES[0])
self.splitter.addWidget(self.playlist_widget)
self.splitter.addWidget(centre_widget)
self.splitter.addWidget(self.history_widget)
self.splitter.setSizes([400, 1120, 400])
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)
# ── MIDI ──────────────────────────────────────────────────────────
self._setup_midi()
def _style_splitter(self, theme: dict):
self.splitter.setStyleSheet(f"""
QSplitter::handle {{
background-color: #333333;
border-radius: 3px;
}}
QSplitter::handle:hover {{
background-color: {theme['accent']};
}}
QSplitter::handle:pressed {{
background-color: {theme['accent_dim']};
}}
""")
def _on_theme_changed(self, theme: dict):
self._apply_global_style(theme)
self._style_splitter(theme)
2026-04-30 00:30:23 +10:00
self.deck1.apply_theme(theme)
self.deck2.apply_theme(theme)
self.cart_bank.apply_theme(theme)
self.history_widget.apply_theme(theme)
self.mixer.apply_theme(theme)
2026-04-29 16:21:44 +10:00
def _apply_global_style(self, theme: dict):
self.setStyleSheet(f"""
QMainWindow {{
background-color: {theme['bg']};
}}
QWidget {{
background-color: {theme['bg']};
color: {theme['text']};
font-family: Arial;
}}
QToolTip {{
background-color: {theme['bg2']};
color: {theme['text']};
border: 1px solid #444;
padding: 4px;
}}
""")
def _setup_midi(self):
self.midi = MidiEngine()
self.midi.deck_play_pause.connect(self._on_midi_play_pause)
self.midi.deck_cue.connect(self._on_midi_cue)
self.midi.deck_jog.connect(self._on_midi_jog)
self.midi.cart_trigger.connect(self._on_midi_cart)
self.midi.mixer_volume.connect(self._on_midi_mixer_volume)
self.midi.mixer_mute.connect(self._on_midi_mixer_mute)
2026-04-29 16:21:44 +10:00
self.midi.controller_connected.connect(self._on_midi_status)
self.midi.start()
def _on_midi_play_pause(self, deck: str):
if deck == 'deck1':
self.deck1.toggle_play()
elif deck == 'deck2':
self.deck2.toggle_play()
def _on_midi_cue(self, deck: str):
if deck == 'deck1':
self.deck1.cue()
elif deck == 'deck2':
self.deck2.cue()
def _on_midi_jog(self, deck: str, delta: float):
if deck == 'deck1':
self.deck1.scrub(delta)
elif deck == 'deck2':
self.deck2.scrub(delta)
def _on_midi_cart(self, slot: int):
self.cart_bank.slots[slot].toggle()
def _on_midi_mixer_volume(self, channel: int, value: float):
self.engine.set_channel_volume(channel, value)
def _on_midi_mixer_mute(self, channel: int, muted: bool):
self.engine.set_channel_mute(channel, muted)
2026-04-29 16:21:44 +10:00
def _on_midi_status(self, connected: bool, name: str):
if connected:
print(f"[MIDI] Connected: {name}")
else:
print(f"[MIDI] Not connected: {name}")
def closeEvent(self, event):
self.midi.stop()
self.engine.shutdown()
event.accept()
def main():
app = QApplication(sys.argv)
app.setApplicationName("Radio Panel")
app.setOrganizationName("Getting To It")
2026-04-29 16:21:44 +10:00
palette = QPalette()
palette.setColor(QPalette.Window, QColor("#0d0d0d"))
palette.setColor(QPalette.WindowText, QColor("#cccccc"))
palette.setColor(QPalette.Base, QColor("#111111"))
palette.setColor(QPalette.AlternateBase, QColor("#1a1a1a"))
palette.setColor(QPalette.Text, QColor("#cccccc"))
palette.setColor(QPalette.Button, QColor("#2a2a2a"))
palette.setColor(QPalette.ButtonText, QColor("#cccccc"))
palette.setColor(QPalette.Highlight, QColor("#1a3a5a"))
palette.setColor(QPalette.HighlightedText, QColor("#ffffff"))
app.setPalette(palette)
window = RadioPanelWindow()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()