v0.5 — cleanup orphan code, add MIDI master volume learn, fix turn-deck crashes
- Remove vestigial lufs_meter_widget.py and debug_audio.py - Delete unused WaveformWidget/WaveformMonitor classes, dead stubs, duplicate code - Fix turn-mode deck crashes (deck3/deck4 missing from engine.decks, uninitialized manual_elapsed/duration) - Replace raw print() with logging in main.py - Add master_volume MIDI learn signal + settings popup entry - Bump version to 0.5
This commit is contained in:
+116
-323
@@ -2,11 +2,10 @@
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
||||
QPushButton, QFrame, QSizePolicy
|
||||
QPushButton, QFrame, QSizePolicy, QInputDialog
|
||||
)
|
||||
from PySide6.QtCore import Qt, QTimer, Signal, QSize
|
||||
from PySide6.QtGui import QFont, QColor, QPainter, QPen, QPainterPath
|
||||
import numpy as np
|
||||
from PySide6.QtGui import QFont, QColor
|
||||
import os
|
||||
|
||||
from icons import (
|
||||
@@ -15,161 +14,6 @@ from icons import (
|
||||
)
|
||||
|
||||
|
||||
class WaveformWidget(QFrame):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setFixedHeight(60)
|
||||
self.setStyleSheet("""
|
||||
QFrame {
|
||||
background-color: #050505;
|
||||
border: 1px solid #1a1a1a;
|
||||
border-radius: 4px;
|
||||
}
|
||||
""")
|
||||
|
||||
self.waveform_data = None
|
||||
self.position_pct = 0.0
|
||||
self.warning_flash = False
|
||||
|
||||
def set_waveform(self, audio: np.ndarray):
|
||||
if audio is None or audio.shape[1] == 0:
|
||||
self.waveform_data = None
|
||||
self.update()
|
||||
return
|
||||
|
||||
mono = np.mean(audio, axis=0)
|
||||
width = max(500, self.width())
|
||||
samples_per_pixel = max(1, len(mono) // width)
|
||||
num_pixels = len(mono) // samples_per_pixel
|
||||
|
||||
self.waveform_data = np.array([
|
||||
np.sqrt(np.mean(mono[i*samples_per_pixel:(i+1)*samples_per_pixel]**2))
|
||||
for i in range(num_pixels)
|
||||
], dtype=np.float32)
|
||||
|
||||
self.update()
|
||||
|
||||
def set_position(self, position_pct: float, warning: bool = False):
|
||||
self.position_pct = max(0.0, min(1.0, position_pct))
|
||||
self.warning_flash = warning
|
||||
self.update()
|
||||
|
||||
def paintEvent(self, event):
|
||||
super().paintEvent(event)
|
||||
|
||||
if self.waveform_data is None or len(self.waveform_data) == 0:
|
||||
return
|
||||
|
||||
painter = QPainter(self)
|
||||
painter.setRenderHint(QPainter.Antialiasing)
|
||||
|
||||
rect = self.rect().adjusted(2, 2, -2, -2)
|
||||
width = rect.width()
|
||||
height = rect.height()
|
||||
|
||||
max_val = np.max(self.waveform_data) if np.max(self.waveform_data) > 0 else 1.0
|
||||
scaled = (self.waveform_data / max_val) * (height * 0.8)
|
||||
x_scale = width / len(self.waveform_data)
|
||||
|
||||
for i, rms in enumerate(self.waveform_data):
|
||||
x = rect.x() + int(i * x_scale)
|
||||
bar_h = int(scaled[i])
|
||||
y_top = rect.y() + (height - bar_h) // 2
|
||||
|
||||
pct = i / len(self.waveform_data)
|
||||
if pct < self.position_pct:
|
||||
color = QColor("#004400")
|
||||
elif pct > 0.85:
|
||||
color = QColor("#ff0000") if self.warning_flash else QColor("#aa0000")
|
||||
elif pct > 0.70:
|
||||
color = QColor("#ffaa00")
|
||||
else:
|
||||
color = QColor("#00ff41")
|
||||
|
||||
pen = QPen(color, 1)
|
||||
painter.setPen(pen)
|
||||
painter.drawLine(x, y_top, x, y_top + bar_h)
|
||||
|
||||
playhead_x = rect.x() + int(self.position_pct * width)
|
||||
pen = QPen(QColor("#ffffff"), 2)
|
||||
painter.setPen(pen)
|
||||
painter.drawLine(playhead_x, rect.y(), playhead_x, rect.y() + height)
|
||||
|
||||
|
||||
class WaveformMonitor(QFrame):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setStyleSheet("""
|
||||
QFrame {
|
||||
background-color: #050a05;
|
||||
border: 1px solid #1a2a1a;
|
||||
border-radius: 4px;
|
||||
}
|
||||
""")
|
||||
|
||||
def paintEvent(self, event):
|
||||
painter = QPainter(self)
|
||||
painter.setRenderHint(QPainter.Antialiasing)
|
||||
rect = self.rect().adjusted(3, 3, -3, -3)
|
||||
if rect.width() < 2 or rect.height() < 2:
|
||||
painter.end()
|
||||
return
|
||||
|
||||
painter.fillRect(rect, QColor("#050a05"))
|
||||
|
||||
pen = QPen(QColor("#1a2a1a"), 1)
|
||||
painter.setPen(pen)
|
||||
painter.drawRect(rect)
|
||||
|
||||
engine = getattr(self, '_engine', None)
|
||||
monitor_key = getattr(self, '_monitor_key', None)
|
||||
if engine is None or monitor_key is None:
|
||||
painter.end()
|
||||
return
|
||||
|
||||
monitor = engine.ext_monitors.get(monitor_key)
|
||||
if monitor is None or not monitor.monitoring:
|
||||
pen = QPen(QColor("#0a1a0a"), 1)
|
||||
painter.setPen(pen)
|
||||
mid_y = rect.center().y()
|
||||
painter.drawLine(rect.left(), mid_y, rect.right(), mid_y)
|
||||
painter.end()
|
||||
return
|
||||
|
||||
buf = monitor.buffer
|
||||
w = rect.width()
|
||||
h = rect.height()
|
||||
mid_y = rect.y() + h // 2
|
||||
|
||||
path = QPainterPath()
|
||||
path.moveTo(rect.right(), mid_y)
|
||||
for i in range(len(buf)):
|
||||
x = rect.right() - int((i / len(buf)) * w)
|
||||
val = buf[(monitor.write_pos - i) % len(buf)]
|
||||
y = mid_y - int(val * (h * 0.45))
|
||||
if i == 0:
|
||||
path.lineTo(x, y)
|
||||
else:
|
||||
path.lineTo(x, y)
|
||||
path.lineTo(rect.right(), mid_y)
|
||||
path.closeSubpath()
|
||||
|
||||
painter.setPen(QPen(QColor("#00ff41"), 1))
|
||||
painter.setBrush(QColor(0, 255, 65, 30))
|
||||
painter.drawPath(path)
|
||||
|
||||
pen = QPen(QColor("#00ff41"), 1)
|
||||
painter.setPen(pen)
|
||||
for i in range(len(buf)):
|
||||
x = rect.right() - int((i / len(buf)) * w)
|
||||
val = buf[(monitor.write_pos - i) % len(buf)]
|
||||
y = mid_y - int(val * (h * 0.45))
|
||||
if val > 0.01:
|
||||
painter.drawLine(x, y, x, mid_y)
|
||||
|
||||
painter.end()
|
||||
|
||||
|
||||
class LCDDisplay(QFrame):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
@@ -186,11 +30,17 @@ class LCDDisplay(QFrame):
|
||||
layout.setContentsMargins(10, 8, 10, 8)
|
||||
layout.setSpacing(4)
|
||||
|
||||
self.track_label = QLabel("NO TRACK LOADED")
|
||||
self.track_label.setFont(QFont("Courier New", 13, QFont.Bold))
|
||||
self.track_label.setStyleSheet("color: #00ff41; background: transparent;")
|
||||
self.track_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
|
||||
self.track_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||
self.track_btn = QPushButton("NO TRACK LOADED")
|
||||
self.track_btn.setFont(QFont("Courier New", 13, QFont.Bold))
|
||||
self.track_btn.setStyleSheet("""
|
||||
QPushButton {
|
||||
color: #00ff41; background: transparent; border: none;
|
||||
text-align: left; padding: 0px;
|
||||
}
|
||||
QPushButton:hover { color: #ffffff; }
|
||||
""")
|
||||
self.track_btn.setCursor(Qt.PointingHandCursor)
|
||||
self.track_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||
|
||||
time_row = QHBoxLayout()
|
||||
time_row.setSpacing(4)
|
||||
@@ -224,14 +74,17 @@ class LCDDisplay(QFrame):
|
||||
status_row.addStretch()
|
||||
status_row.addWidget(self.queue_label)
|
||||
|
||||
layout.addWidget(self.track_label)
|
||||
layout.addWidget(self.track_btn)
|
||||
layout.addLayout(time_row)
|
||||
layout.addLayout(status_row)
|
||||
|
||||
def update_track(self, name: str):
|
||||
if len(name) > 40:
|
||||
name = name[:37] + "..."
|
||||
self.track_label.setText(name)
|
||||
self.track_btn.setText(name)
|
||||
|
||||
def track_name(self) -> str:
|
||||
return self.track_btn.text()
|
||||
|
||||
def update_time(self, elapsed: str, remaining: str):
|
||||
self.elapsed_label.setText(elapsed)
|
||||
@@ -287,7 +140,7 @@ class DeckWidget(QWidget):
|
||||
track_started = Signal(str)
|
||||
|
||||
def __init__(self, deck_key: str, label: str, accent_color: str,
|
||||
engine, parent=None):
|
||||
engine, parent=None, mode='deck'):
|
||||
super().__init__(parent)
|
||||
self.deck_key = deck_key
|
||||
self.engine = engine
|
||||
@@ -295,9 +148,9 @@ class DeckWidget(QWidget):
|
||||
self.current_theme = None
|
||||
self.flash_state = False
|
||||
self._playing_icon = False
|
||||
self.mode = mode
|
||||
|
||||
deck_num = label.split()[-1]
|
||||
self.deck_label = f"DECK_{int(deck_num):03d}"
|
||||
self.deck_label = label
|
||||
|
||||
self._build_ui()
|
||||
self._connect_signals()
|
||||
@@ -339,9 +192,6 @@ class DeckWidget(QWidget):
|
||||
self.lcd = LCDDisplay()
|
||||
root.addWidget(self.lcd)
|
||||
|
||||
self.waveform = WaveformWidget()
|
||||
root.addWidget(self.waveform)
|
||||
|
||||
transport = QHBoxLayout()
|
||||
transport.setSpacing(6)
|
||||
|
||||
@@ -362,6 +212,12 @@ class DeckWidget(QWidget):
|
||||
|
||||
root.addLayout(transport)
|
||||
|
||||
if self.mode == 'turn':
|
||||
self.btn_to_start.setVisible(False)
|
||||
self.btn_back_15.setVisible(False)
|
||||
self.btn_fwd_15.setVisible(False)
|
||||
self.btn_to_end.setVisible(False)
|
||||
|
||||
def apply_theme(self, theme: dict):
|
||||
self.current_theme = theme
|
||||
border_color = theme['border']
|
||||
@@ -381,13 +237,6 @@ class DeckWidget(QWidget):
|
||||
border-radius: 4px;
|
||||
}}
|
||||
""")
|
||||
self.waveform.setStyleSheet(f"""
|
||||
QFrame {{
|
||||
background-color: {theme['bg']};
|
||||
border: 1px solid {border_color};
|
||||
border-radius: 3px;
|
||||
}}
|
||||
""")
|
||||
|
||||
def _toggle_flash(self):
|
||||
self.flash_state = not self.flash_state
|
||||
@@ -395,21 +244,39 @@ class DeckWidget(QWidget):
|
||||
def _connect_signals(self):
|
||||
self.btn_play.clicked.connect(self._toggle_play)
|
||||
self.btn_stop.clicked.connect(self._stop_eject)
|
||||
self.btn_to_start.clicked.connect(self._go_to_start)
|
||||
self.btn_to_end.clicked.connect(self._go_to_end)
|
||||
self.btn_back_15.clicked.connect(lambda: self._scrub(-15))
|
||||
self.btn_fwd_15.clicked.connect(lambda: self._scrub(15))
|
||||
self.lcd.track_btn.clicked.connect(self._edit_track_name)
|
||||
if self.mode != 'turn':
|
||||
self.btn_to_start.clicked.connect(self._go_to_start)
|
||||
self.btn_to_end.clicked.connect(self._go_to_end)
|
||||
self.btn_back_15.clicked.connect(lambda: self._scrub(-15))
|
||||
self.btn_fwd_15.clicked.connect(lambda: self._scrub(15))
|
||||
|
||||
def _edit_track_name(self):
|
||||
current = self.lcd.track_btn.text()
|
||||
if current == "NO TRACK LOADED":
|
||||
current = ""
|
||||
name, ok = QInputDialog.getText(self, "Track Name", "Track name:", text=current)
|
||||
if ok:
|
||||
if not name.strip():
|
||||
name = "NO TRACK LOADED"
|
||||
self.lcd.update_track(name.strip())
|
||||
if self.mode == 'turn':
|
||||
deck = self.engine.decks[self.deck_key]
|
||||
if self.mode == 'turn' and name.strip() != "NO TRACK LOADED":
|
||||
dur, ok2 = QInputDialog.getText(self, "Duration", "Duration (MM:SS):", text="00:00")
|
||||
if ok2 and ':' in dur:
|
||||
parts = dur.split(':')
|
||||
try:
|
||||
total_sec = int(parts[0]) * 60 + int(parts[1])
|
||||
deck = self.engine.decks[self.deck_key]
|
||||
deck.manual_duration = float(total_sec)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def set_track_name(self, name: str):
|
||||
self.lcd.update_track(name)
|
||||
self.lcd.update_status("LOADED")
|
||||
self.lcd.update_time("00:00", "-00:00")
|
||||
QTimer.singleShot(200, self._update_waveform)
|
||||
|
||||
def _update_waveform(self):
|
||||
deck = self.engine.decks[self.deck_key]
|
||||
if deck.track:
|
||||
self.waveform.set_waveform(deck.track.audio)
|
||||
|
||||
def set_queue_name(self, name: str):
|
||||
self.lcd.update_queue(name)
|
||||
@@ -418,6 +285,8 @@ class DeckWidget(QWidget):
|
||||
self._toggle_play()
|
||||
|
||||
def cue(self):
|
||||
if self.mode == 'turn':
|
||||
return
|
||||
deck = self.engine.decks[self.deck_key]
|
||||
if deck.track is None:
|
||||
return
|
||||
@@ -442,10 +311,13 @@ class DeckWidget(QWidget):
|
||||
|
||||
def _toggle_play(self):
|
||||
deck = self.engine.decks[self.deck_key]
|
||||
if deck.track is None:
|
||||
if deck.track is None and self.mode != 'turn':
|
||||
return
|
||||
if deck.playing:
|
||||
deck.pause()
|
||||
if self.mode == 'turn':
|
||||
deck.playing = False
|
||||
else:
|
||||
deck.pause()
|
||||
self.btn_play.setIcon(icon_play("#00ff41"))
|
||||
self._playing_icon = False
|
||||
self.btn_play.setStyleSheet("""
|
||||
@@ -456,10 +328,13 @@ class DeckWidget(QWidget):
|
||||
}
|
||||
QPushButton:hover { background-color: #2a7b4a; }
|
||||
""")
|
||||
self.lcd.update_status("PAUSED")
|
||||
self.lcd.update_status("PAUSED" if self.mode != 'turn' else "STOPPED")
|
||||
self.lcd.set_playing(False)
|
||||
else:
|
||||
deck.play()
|
||||
if self.mode == 'turn':
|
||||
deck.playing = True
|
||||
else:
|
||||
deck.play()
|
||||
self.btn_play.setIcon(icon_pause("#ffffff"))
|
||||
self._playing_icon = True
|
||||
self.btn_play.setStyleSheet("""
|
||||
@@ -472,12 +347,21 @@ class DeckWidget(QWidget):
|
||||
""")
|
||||
self.lcd.update_status("PLAYING")
|
||||
self.lcd.set_playing(True)
|
||||
if deck.track:
|
||||
if self.mode == 'turn':
|
||||
deck.manual_elapsed = 0.0
|
||||
name = self.lcd.track_btn.text()
|
||||
if name and name != "NO TRACK LOADED":
|
||||
self.track_started.emit(f"[TURN] {name}")
|
||||
elif deck.track:
|
||||
self.track_started.emit(deck.track.filepath)
|
||||
|
||||
def _stop_eject(self):
|
||||
deck = self.engine.decks[self.deck_key]
|
||||
deck.stop()
|
||||
if self.mode == 'turn':
|
||||
deck.playing = False
|
||||
deck.manual_elapsed = 0.0
|
||||
else:
|
||||
deck.stop()
|
||||
self.btn_play.setIcon(icon_play("#00ff41"))
|
||||
self._playing_icon = False
|
||||
self.btn_play.setStyleSheet("""
|
||||
@@ -492,7 +376,6 @@ class DeckWidget(QWidget):
|
||||
self.lcd.update_time("00:00", "-00:00")
|
||||
self.lcd.update_status("STOPPED")
|
||||
self.lcd.set_playing(False)
|
||||
self.waveform.set_waveform(None)
|
||||
|
||||
def _go_to_start(self):
|
||||
self.engine.decks[self.deck_key].go_to_start()
|
||||
@@ -506,17 +389,42 @@ class DeckWidget(QWidget):
|
||||
def _refresh_display(self):
|
||||
deck = self.engine.decks[self.deck_key]
|
||||
|
||||
if not deck.playing and deck.track is not None:
|
||||
if deck.position >= deck.track.num_samples - 1:
|
||||
if deck.queued:
|
||||
deck.load(deck.queued)
|
||||
self.lcd.update_track(os.path.splitext(os.path.basename(deck.queued.filepath))[0])
|
||||
QTimer.singleShot(200, self._update_waveform)
|
||||
if self.mode == 'turn':
|
||||
if deck.playing:
|
||||
deck.manual_elapsed += 0.1
|
||||
if deck.manual_duration > 0 and deck.manual_elapsed >= deck.manual_duration:
|
||||
deck.playing = False
|
||||
self.btn_play.setIcon(icon_play("#00ff41"))
|
||||
self._playing_icon = False
|
||||
self.lcd.update_status("STOPPED")
|
||||
self.lcd.set_playing(False)
|
||||
|
||||
elapsed_s = int(deck.manual_elapsed)
|
||||
elapsed = f"{elapsed_s // 60:02d}:{elapsed_s % 60:02d}"
|
||||
if deck.manual_duration > 0:
|
||||
remaining = max(0, deck.manual_duration - deck.manual_elapsed)
|
||||
remaining_s = int(remaining)
|
||||
remaining_str = f"-{remaining_s // 60:02d}:{remaining_s % 60:02d}"
|
||||
else:
|
||||
remaining_str = "-00:00"
|
||||
self.lcd.update_time(elapsed, remaining_str)
|
||||
return
|
||||
|
||||
track = deck.track
|
||||
playing = deck.playing
|
||||
position = deck.position
|
||||
queued = deck.queued
|
||||
|
||||
if not playing and track is not None:
|
||||
if position >= track.num_samples - 1:
|
||||
if queued:
|
||||
deck.load(queued)
|
||||
self.lcd.update_track(os.path.splitext(os.path.basename(queued.filepath))[0])
|
||||
deck.queued = None
|
||||
self.lcd.update_queue("")
|
||||
self.lcd.update_status("LOADED")
|
||||
|
||||
if not deck.playing and self._playing_icon:
|
||||
if not playing and self._playing_icon:
|
||||
self.btn_play.setIcon(icon_play("#00ff41"))
|
||||
self._playing_icon = False
|
||||
self.btn_play.setStyleSheet("""
|
||||
@@ -530,13 +438,13 @@ class DeckWidget(QWidget):
|
||||
self.lcd.update_status("STOPPED")
|
||||
self.lcd.set_playing(False)
|
||||
|
||||
if deck.track:
|
||||
if track:
|
||||
self.lcd.update_time(deck.get_elapsed(), deck.get_remaining())
|
||||
position_pct = deck.position / deck.track.num_samples
|
||||
remaining_sec = deck.track.duration - (deck.position / deck.track.sr)
|
||||
position_pct = position / track.num_samples
|
||||
remaining_sec = track.duration - (position / track.sr)
|
||||
in_warning = (remaining_sec < 20) or (position_pct > 0.85)
|
||||
|
||||
if deck.playing and in_warning:
|
||||
if playing and in_warning:
|
||||
flash_color = '#ff4444' if self.flash_state else self.accent_color
|
||||
self.header.setStyleSheet(f"""
|
||||
color: {flash_color};
|
||||
@@ -554,120 +462,5 @@ class DeckWidget(QWidget):
|
||||
""")
|
||||
self.lcd.flash_warning(False)
|
||||
|
||||
self.waveform.set_position(position_pct, in_warning and self.flash_state)
|
||||
|
||||
if deck.queued:
|
||||
self.lcd.update_queue(os.path.basename(deck.queued.filepath))
|
||||
|
||||
|
||||
class ExternalDeckWidget(QWidget):
|
||||
def __init__(self, deck_key: str, label: str, accent_color: str,
|
||||
engine, parent=None):
|
||||
super().__init__(parent)
|
||||
self.deck_key = deck_key
|
||||
self.engine = engine
|
||||
self.accent_color = accent_color
|
||||
self._monitoring = False
|
||||
|
||||
deck_num = label.split()[-1]
|
||||
self.deck_label = f"EXT_{int(deck_num):03d}"
|
||||
|
||||
self._build_ui()
|
||||
|
||||
def _build_ui(self):
|
||||
self.setStyleSheet(f"""
|
||||
QWidget {{
|
||||
background-color: #1c1c1c;
|
||||
border: 2px solid {self.accent_color};
|
||||
border-radius: 6px;
|
||||
}}
|
||||
""")
|
||||
|
||||
root = QVBoxLayout(self)
|
||||
root.setContentsMargins(10, 10, 10, 10)
|
||||
root.setSpacing(8)
|
||||
|
||||
self.header = QLabel(self.deck_label)
|
||||
self.header.setFont(QFont("Courier New", 24, QFont.Bold))
|
||||
self.header.setStyleSheet(f"""
|
||||
color: {self.accent_color};
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 4px;
|
||||
""")
|
||||
self.header.setAlignment(Qt.AlignCenter)
|
||||
root.addWidget(self.header)
|
||||
|
||||
self.waveform = WaveformMonitor()
|
||||
self.waveform._engine = self.engine
|
||||
self.waveform._monitor_key = self.deck_key
|
||||
self.waveform.setMinimumHeight(100)
|
||||
root.addWidget(self.waveform, stretch=1)
|
||||
|
||||
transport = QHBoxLayout()
|
||||
transport.setSpacing(6)
|
||||
|
||||
self.btn_play = make_icon_button(icon_play(), "#1a6b3a", "#00ff41", 68, 48)
|
||||
transport.addStretch()
|
||||
transport.addWidget(self.btn_play)
|
||||
transport.addStretch()
|
||||
|
||||
root.addLayout(transport)
|
||||
|
||||
self._connect_signals()
|
||||
|
||||
def _connect_signals(self):
|
||||
self.btn_play.clicked.connect(self._toggle_monitor)
|
||||
|
||||
def toggle_play(self):
|
||||
self._toggle_monitor()
|
||||
|
||||
def _toggle_monitor(self):
|
||||
monitor = self.engine.ext_monitors[self.deck_key]
|
||||
self._monitoring = not self._monitoring
|
||||
monitor.monitoring = self._monitoring
|
||||
|
||||
if self._monitoring:
|
||||
self.btn_play.setIcon(icon_pause("#ffffff"))
|
||||
self.btn_play.setStyleSheet("""
|
||||
QPushButton {
|
||||
background-color: #00aa33;
|
||||
border: 1px solid #00ff41;
|
||||
border-radius: 4px;
|
||||
}
|
||||
QPushButton:hover { background-color: #00cc44; }
|
||||
""")
|
||||
self.header.setStyleSheet(f"""
|
||||
color: #00ff41;
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 4px;
|
||||
""")
|
||||
else:
|
||||
self.btn_play.setIcon(icon_play("#00ff41"))
|
||||
self.btn_play.setStyleSheet("""
|
||||
QPushButton {
|
||||
background-color: #1a6b3a;
|
||||
border: 1px solid #555;
|
||||
border-radius: 4px;
|
||||
}
|
||||
QPushButton:hover { background-color: #2a7b4a; }
|
||||
""")
|
||||
self.header.setStyleSheet(f"""
|
||||
color: {self.accent_color};
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 4px;
|
||||
""")
|
||||
self.waveform.update()
|
||||
|
||||
def apply_theme(self, theme: dict):
|
||||
border_color = theme['border']
|
||||
bg_color = theme['bg2']
|
||||
self.setStyleSheet(f"""
|
||||
QWidget {{
|
||||
background-color: {bg_color};
|
||||
border: 2px solid {border_color};
|
||||
border-radius: 6px;
|
||||
}}
|
||||
""")
|
||||
if queued:
|
||||
self.lcd.update_queue(os.path.basename(queued.filepath))
|
||||
|
||||
Reference in New Issue
Block a user