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.
209 lines
7.5 KiB
209 lines
7.5 KiB
# main.py
|
|
|
|
import sys
|
|
import json
|
|
import os
|
|
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QWidget, QVBoxLayout, QLabel, QSpinBox, QLineEdit, QGridLayout
|
|
from PyQt5.QtCore import Qt
|
|
from PyQt5.QtGui import QImage, QPixmap, qRgb
|
|
from dmx import DMXRecorder, DMXPlayer
|
|
|
|
class MainWindow(QMainWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.settings = self.load_settings()
|
|
self.initUI()
|
|
self.isRecording = False
|
|
self.isPlaying = False
|
|
self.recorder = None
|
|
self.player = None
|
|
|
|
def initUI(self):
|
|
self.setWindowTitle("DMX Recorder and Player")
|
|
self.resize(300, 500)
|
|
|
|
# Use dark theme
|
|
self.setStyleSheet('''
|
|
QWidget {
|
|
background-color: #222222;
|
|
color: #FFFFFF;
|
|
}
|
|
QSlider::groove:horizontal {
|
|
border: 1px solid #444444;
|
|
height: 8px;
|
|
background: #555555;
|
|
}
|
|
QSlider::handle:horizontal {
|
|
background: #888888;
|
|
border: 1px solid #444444;
|
|
width: 18px;
|
|
margin: -8px 0;
|
|
}
|
|
QLineEdit {
|
|
background-color: #333333;
|
|
border: 1px solid #555555;
|
|
color: #FFFFFF;
|
|
padding: 4px;
|
|
}
|
|
QPushButton {
|
|
background-color: #444444;
|
|
border: 1px solid #666666;
|
|
padding: 6px;
|
|
}
|
|
QPushButton:hover {
|
|
background-color: #555555;
|
|
}
|
|
QLabel {
|
|
color: #FFFFFF;
|
|
}
|
|
''')
|
|
|
|
self.central_widget = QWidget()
|
|
self.setCentralWidget(self.central_widget)
|
|
|
|
self.layout = QVBoxLayout()
|
|
self.central_widget.setLayout(self.layout)
|
|
|
|
self.record_button = QPushButton("Record")
|
|
self.record_button.clicked.connect(self.toggle_recording)
|
|
|
|
self.play_button = QPushButton("Play")
|
|
self.play_button.clicked.connect(self.toggle_playback)
|
|
|
|
# Input fields for settings
|
|
self.universes_label = QLabel("Universes to Playback:")
|
|
self.universes_spinbox = QSpinBox()
|
|
self.universes_spinbox.setMinimum(1)
|
|
self.universes_spinbox.setMaximum(4) # Maximum universes recorded
|
|
self.universes_spinbox.setValue(self.settings.get('universes', 4))
|
|
|
|
# Port number
|
|
self.port_label = QLabel("Port Number:")
|
|
self.port_input = QLineEdit(str(self.settings.get('port', 6454)))
|
|
|
|
# Transmit Address (Playback)
|
|
self.transmit_label = QLabel("Transmit Address:")
|
|
self.transmit_input = QLineEdit(self.settings.get('transmit_address', '255.255.255.255'))
|
|
|
|
# Listen Address (Recording)
|
|
self.listen_label = QLabel("Listen Address:")
|
|
self.listen_input = QLineEdit(self.settings.get('listen_address', '0.0.0.0'))
|
|
|
|
self.video_label = QLabel()
|
|
self.video_label.setAlignment(Qt.AlignCenter)
|
|
self.layout.addWidget(self.video_label)
|
|
|
|
# Add settings input fields to the layout
|
|
settings_layout = QGridLayout()
|
|
settings_layout.addWidget(self.universes_label, 0, 0)
|
|
settings_layout.addWidget(self.universes_spinbox, 0, 1)
|
|
settings_layout.addWidget(self.port_label, 1, 0)
|
|
settings_layout.addWidget(self.port_input, 1, 1)
|
|
settings_layout.addWidget(self.transmit_label, 2, 0)
|
|
settings_layout.addWidget(self.transmit_input, 2, 1)
|
|
settings_layout.addWidget(self.listen_label, 3, 0)
|
|
settings_layout.addWidget(self.listen_input, 3, 1)
|
|
self.layout.addLayout(settings_layout)
|
|
|
|
self.layout.addWidget(self.record_button)
|
|
self.layout.addWidget(self.play_button)
|
|
|
|
def toggle_recording(self):
|
|
if not self.isRecording:
|
|
if self.isPlaying:
|
|
# Can't record while playing
|
|
return
|
|
# Get settings
|
|
port = int(self.port_input.text())
|
|
listen_address = self.listen_input.text()
|
|
# Start recording
|
|
self.recorder = DMXRecorder(listen_address=listen_address, port=port)
|
|
self.recorder.frame_ready.connect(self.update_frame)
|
|
self.recorder.start_recording()
|
|
self.record_button.setText("Stop")
|
|
self.isRecording = True
|
|
else:
|
|
# Stop recording
|
|
if self.recorder:
|
|
self.recorder.frame_ready.disconnect(self.update_frame)
|
|
self.recorder.stop_recording()
|
|
self.recorder = None
|
|
self.record_button.setText("Record")
|
|
self.isRecording = False
|
|
|
|
def toggle_playback(self):
|
|
if not self.isPlaying:
|
|
if self.isRecording:
|
|
# Can't play while recording
|
|
return
|
|
# Get settings
|
|
num_universes_to_playback = self.universes_spinbox.value()
|
|
port = int(self.port_input.text())
|
|
transmit_address = self.transmit_input.text()
|
|
# Start playback
|
|
self.player = DMXPlayer(num_universes=num_universes_to_playback, transmit_address=transmit_address, port=port)
|
|
self.player.frame_ready.connect(self.update_frame)
|
|
self.player.playback_finished.connect(self.on_playback_finished)
|
|
self.player.start_playback()
|
|
self.play_button.setText("Stop")
|
|
self.isPlaying = True
|
|
else:
|
|
# Stop playback
|
|
if self.player:
|
|
self.player.stop_playback()
|
|
self.player = None
|
|
self.play_button.setText("Play")
|
|
self.isPlaying = False
|
|
|
|
def on_playback_finished(self):
|
|
if self.isPlaying:
|
|
self.play_button.setText("Play")
|
|
self.isPlaying = False
|
|
if self.player:
|
|
self.player.frame_ready.disconnect(self.update_frame)
|
|
self.player = None
|
|
|
|
def update_frame(self, frame_array):
|
|
# Convert the numpy array to QImage and display
|
|
height, width = frame_array.shape
|
|
# Convert the numpy array to QImage
|
|
q_img = QImage(frame_array.data, width, height, width, QImage.Format_Indexed8)
|
|
# Create a grayscale color table
|
|
color_table = [qRgb(i, i, i) for i in range(256)]
|
|
q_img.setColorTable(color_table)
|
|
|
|
# Scale image to fit the label
|
|
pixmap = QPixmap.fromImage(q_img).scaled(self.video_label.width(), self.video_label.height(), Qt.KeepAspectRatio)
|
|
# Set the pixmap to the label
|
|
self.video_label.setPixmap(pixmap)
|
|
|
|
def closeEvent(self, event):
|
|
# Save settings to JSON file
|
|
self.save_settings()
|
|
super().closeEvent(event)
|
|
|
|
def load_settings(self):
|
|
# Load settings from settings.json if it exists
|
|
settings_file = 'settings.json'
|
|
if os.path.exists(settings_file):
|
|
with open(settings_file, 'r') as f:
|
|
return json.load(f)
|
|
else:
|
|
# Return default settings
|
|
return {}
|
|
|
|
def save_settings(self):
|
|
settings = {
|
|
'universes': self.universes_spinbox.value(),
|
|
'port': int(self.port_input.text()),
|
|
'transmit_address': self.transmit_input.text(),
|
|
'listen_address': self.listen_input.text(),
|
|
}
|
|
with open('settings.json', 'w') as f:
|
|
json.dump(settings, f)
|
|
|
|
if __name__ == '__main__':
|
|
app = QApplication(sys.argv)
|
|
window = MainWindow()
|
|
window.show()
|
|
sys.exit(app.exec_())
|