You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
6.7 KiB
174 lines
6.7 KiB
"""
|
|
Simulator Display GUI
|
|
|
|
Simplified visual representation showing only channel volumes.
|
|
"""
|
|
|
|
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QGridLayout,
|
|
QLabel, QFrame, QPushButton, QSlider, QGroupBox)
|
|
from PyQt5.QtCore import Qt, QTimer, pyqtSlot
|
|
from PyQt5.QtGui import QPainter, QColor, QBrush, QPen, QFont
|
|
|
|
class SynthWidget(QFrame):
|
|
"""Individual synth display widget - simplified to show only volume"""
|
|
|
|
def __init__(self, channel: int):
|
|
super().__init__()
|
|
self.channel = channel
|
|
self.channel_volume_midi = 100 # 0-127 MIDI CC7 value
|
|
|
|
self.setFrameStyle(QFrame.Box)
|
|
self.setFixedSize(100, 80)
|
|
self.setStyleSheet("""
|
|
QFrame {
|
|
border: 2px solid #404040;
|
|
border-radius: 6px;
|
|
background-color: #2a2a2a;
|
|
}
|
|
""")
|
|
|
|
def set_channel_volume(self, volume_midi: int):
|
|
"""Set channel volume (0-127 MIDI CC7) - this is what controls brightness"""
|
|
self.channel_volume_midi = max(0, min(127, volume_midi))
|
|
self.update() # Trigger repaint
|
|
|
|
def paintEvent(self, event):
|
|
"""Custom paint for volume-based lighting"""
|
|
super().paintEvent(event)
|
|
|
|
painter = QPainter(self)
|
|
painter.setRenderHint(QPainter.Antialiasing)
|
|
|
|
# Calculate brightness based on MIDI volume (0-127)
|
|
brightness_intensity = int((self.channel_volume_midi / 127.0) * 235) # Max 235 to leave room for +20
|
|
|
|
# Create color based on channel (different hues)
|
|
hue = (self.channel - 1) * 360 / 16 # Distribute hues across spectrum
|
|
brightness_value = max(20, min(255, brightness_intensity + 20)) # Clamp to valid range
|
|
color = QColor.fromHsv(int(hue), 200, brightness_value)
|
|
|
|
# Draw volume-based lighting effect - only show if volume is above 0
|
|
if self.channel_volume_midi > 0:
|
|
# Draw volume glow
|
|
glow_rect = self.rect().adjusted(8, 8, -8, -8)
|
|
painter.setBrush(QBrush(color))
|
|
painter.setPen(QPen(color.lighter(120), 1))
|
|
painter.drawRoundedRect(glow_rect, 4, 4)
|
|
|
|
# Draw channel info
|
|
painter.setPen(QPen(QColor(255, 255, 255), 1))
|
|
painter.setFont(QFont("Arial", 11, QFont.Bold))
|
|
|
|
# Channel number
|
|
painter.drawText(10, 20, f"Ch {self.channel}")
|
|
|
|
# Volume level (MIDI CC7 value)
|
|
painter.setFont(QFont("Arial", 9))
|
|
painter.drawText(10, 65, f"Vol: {self.channel_volume_midi}")
|
|
|
|
|
|
class SimulatorDisplay(QWidget):
|
|
"""Simplified simulator display widget"""
|
|
|
|
def __init__(self, simulator, channel_manager):
|
|
super().__init__()
|
|
self.simulator = simulator
|
|
self.channel_manager = channel_manager
|
|
self.synth_widgets = {}
|
|
self.current_synth_count = 8
|
|
|
|
self.setup_ui()
|
|
self.connect_signals()
|
|
|
|
def setup_ui(self):
|
|
"""Set up the user interface"""
|
|
layout = QVBoxLayout(self)
|
|
|
|
# Title
|
|
title = QLabel("Synth Array - Channel Volume Display")
|
|
title.setStyleSheet("font-size: 14px; font-weight: bold; color: #ffffff; margin: 5px;")
|
|
title.setAlignment(Qt.AlignCenter)
|
|
layout.addWidget(title)
|
|
|
|
# Synth display grid
|
|
self.synth_grid_widget = QWidget()
|
|
self.synth_grid_layout = QGridLayout(self.synth_grid_widget)
|
|
self.synth_grid_layout.setSpacing(5)
|
|
layout.addWidget(self.synth_grid_widget)
|
|
|
|
# Initialize with default synth count
|
|
self.create_synth_widgets(self.current_synth_count)
|
|
|
|
def connect_signals(self):
|
|
"""Connect signals"""
|
|
# Channel manager signals
|
|
if hasattr(self.channel_manager, 'volume_changed'):
|
|
self.channel_manager.volume_changed.connect(self.on_channel_volume_changed)
|
|
|
|
def create_synth_widgets(self, count: int):
|
|
"""Create synth widgets for display"""
|
|
# Clear existing widgets
|
|
for widget in self.synth_widgets.values():
|
|
widget.deleteLater()
|
|
self.synth_widgets.clear()
|
|
|
|
# Clear layout
|
|
while self.synth_grid_layout.count():
|
|
child = self.synth_grid_layout.takeAt(0)
|
|
if child.widget():
|
|
child.widget().deleteLater()
|
|
|
|
# Create new widgets
|
|
cols = 4 # 4 synths per row
|
|
for i in range(count):
|
|
channel = i + 1
|
|
widget = SynthWidget(channel)
|
|
|
|
row = i // cols
|
|
col = i % cols
|
|
self.synth_grid_layout.addWidget(widget, row, col)
|
|
|
|
self.synth_widgets[channel] = widget
|
|
|
|
self.current_synth_count = count
|
|
|
|
@pyqtSlot(int)
|
|
def set_synth_count(self, count: int):
|
|
"""Set number of synths to display"""
|
|
if count != self.current_synth_count:
|
|
self.create_synth_widgets(count)
|
|
|
|
@pyqtSlot(int, float)
|
|
def on_channel_volume_changed(self, channel: int, volume: float):
|
|
"""Handle channel volume change"""
|
|
if channel in self.synth_widgets:
|
|
self.synth_widgets[channel].set_channel_volume(volume)
|
|
|
|
@pyqtSlot(int, int, int, float)
|
|
def on_note_played(self, channel: int, note: int, velocity: int, duration: float):
|
|
"""Handle note played - we don't need special handling for this in volume mode"""
|
|
# In the simplified version, we only care about volume, not individual notes
|
|
pass
|
|
|
|
@pyqtSlot(int, int)
|
|
def on_midi_volume_changed(self, channel: int, volume: int):
|
|
"""Handle MIDI volume change (CC7) - channel 1-16, volume 0-127"""
|
|
if channel in self.synth_widgets:
|
|
self.synth_widgets[channel].set_channel_volume(volume)
|
|
|
|
@pyqtSlot(int, float, float)
|
|
@pyqtSlot(dict)
|
|
def update_lighting(self, lighting_data: dict):
|
|
"""Update lighting based on channel volume from simulator engine"""
|
|
for channel, brightness in lighting_data.items():
|
|
if channel in self.synth_widgets:
|
|
# Convert brightness (0-1) to MIDI (0-127) for display consistency
|
|
midi_volume = int(brightness * 127)
|
|
self.synth_widgets[channel].set_channel_volume(midi_volume)
|
|
|
|
def update_channel_volumes_from_output_manager(self, output_manager):
|
|
"""Update all channel volumes from output manager"""
|
|
for channel in range(1, self.current_synth_count + 1):
|
|
volume = output_manager.get_channel_volume(channel) / 127.0 # Convert from MIDI to 0-1
|
|
if channel in self.synth_widgets:
|
|
self.synth_widgets[channel].set_channel_volume(volume)
|