DMX caputre/playback software
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

# 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_())