Initial commit - Radio Panel v0.1
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
# 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 fingerprint_widget import FingerprintWidget
|
||||
from midi_engine import MidiEngine
|
||||
from top_bar_widget import TopBarWidget, THEMES
|
||||
from history_widget import HistoryWidget
|
||||
|
||||
# ─────────────────────────────────────────
|
||||
# AcoustID API Key
|
||||
# ─────────────────────────────────────────
|
||||
ACOUSTID_API_KEY = "Y0RZoLiEmr"
|
||||
|
||||
|
||||
class RadioPanelWindow(QMainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.engine = AudioEngine()
|
||||
|
||||
self.setWindowTitle("Radio Panel")
|
||||
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.fingerprint_panel = FingerprintWidget(
|
||||
engine=self.engine,
|
||||
api_key=ACOUSTID_API_KEY
|
||||
)
|
||||
self.fingerprint_panel.setFixedHeight(240)
|
||||
|
||||
# ── Centre column ─────────────────────────────────────────────────
|
||||
centre_col = QVBoxLayout()
|
||||
centre_col.setSpacing(8)
|
||||
|
||||
deck_row = QHBoxLayout()
|
||||
deck_row.setSpacing(8)
|
||||
deck_row.addWidget(self.deck1)
|
||||
deck_row.addWidget(self.deck2)
|
||||
centre_col.addLayout(deck_row)
|
||||
|
||||
centre_col.addWidget(self.cart_bank)
|
||||
centre_col.addWidget(self.fingerprint_panel)
|
||||
centre_col.addStretch()
|
||||
|
||||
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)
|
||||
|
||||
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.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_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("GTI")
|
||||
|
||||
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()
|
||||
Reference in New Issue
Block a user