midi: bind patterns to notes 36+; beat triggers selected pattern; include n index; CC map: 30=R 31=G 32=B 33=brightness 34=n1 35=n2 36=delay; send n1/n2 raw 0-127 gui: show n1 and n2 in status
124 lines
4.6 KiB
Python
124 lines
4.6 KiB
Python
import asyncio
|
|
import tkinter as tk
|
|
from tkinter import ttk, messagebox # Import messagebox for confirmations
|
|
import json
|
|
from async_tkinter_loop import async_handler, async_mainloop
|
|
from networking import WebSocketClient
|
|
import color_utils
|
|
|
|
import time
|
|
from midi import MidiHandler # Import MidiHandler
|
|
|
|
# Dark theme colors (unchanged)
|
|
bg_color = "#2e2e2e"
|
|
fg_color = "white"
|
|
trough_color_red = "#4a0000"
|
|
trough_color_green = "#004a00"
|
|
trough_color_blue = "#00004a"
|
|
trough_color_brightness = "#4a4a4a"
|
|
trough_color_delay = "#4a4a4a"
|
|
active_bg_color = "#4a4a4a"
|
|
highlight_pattern_color = "#6a5acd"
|
|
# New color for active color in palette
|
|
active_palette_color_border = "#FFD700" # Gold color
|
|
|
|
|
|
class App:
|
|
def __init__(self) -> None:
|
|
self.root = tk.Tk()
|
|
# self.root.attributes("-fullscreen", True)
|
|
self.root.configure(bg=bg_color)
|
|
|
|
# --- WebSocketClient ---
|
|
self.websocket_client = WebSocketClient("ws://192.168.4.1:80/ws")
|
|
self.root.after(100, async_handler(self.websocket_client.connect))
|
|
|
|
# --- MIDI Handler ---
|
|
MIDI_PORT_INDEX = 1 # Adjust as needed
|
|
WEBSOCKET_SERVER_URI = "ws://192.168.4.1:80/ws"
|
|
self.midi_handler = MidiHandler(MIDI_PORT_INDEX, WEBSOCKET_SERVER_URI)
|
|
self.midi_task: asyncio.Task | None = None
|
|
# Start MIDI in background
|
|
self.root.after(0, async_handler(self.start_midi))
|
|
|
|
# Configure ttk style (unchanged)
|
|
style = ttk.Style()
|
|
style.theme_use("alt")
|
|
style.configure(".", background=bg_color, foreground=fg_color, font=("Arial", 14))
|
|
style.configure("TNotebook", background=bg_color, borderwidth=0)
|
|
style.configure(
|
|
"TNotebook.Tab", background=bg_color, foreground=fg_color, font=("Arial", 30), padding=[10, 5]
|
|
)
|
|
|
|
# --- Status Frame ---
|
|
status_frame = ttk.Frame(self.root)
|
|
status_frame.pack(padx=16, pady=16, fill="x")
|
|
|
|
self.lbl_delay = ttk.Label(status_frame, text="Delay: -")
|
|
self.lbl_brightness = ttk.Label(status_frame, text="Brightness: -")
|
|
self.lbl_r = ttk.Label(status_frame, text="R: -")
|
|
self.lbl_g = ttk.Label(status_frame, text="G: -")
|
|
self.lbl_b = ttk.Label(status_frame, text="B: -")
|
|
self.lbl_pattern = ttk.Label(status_frame, text="Pattern: -")
|
|
self.lbl_n1 = ttk.Label(status_frame, text="n1: -")
|
|
self.lbl_n2 = ttk.Label(status_frame, text="n2: -")
|
|
self.lbl_bpm = ttk.Label(status_frame, text="BPM: -")
|
|
|
|
for w in (self.lbl_delay, self.lbl_brightness, self.lbl_r, self.lbl_g, self.lbl_b, self.lbl_pattern, self.lbl_n1, self.lbl_n2, self.lbl_bpm):
|
|
w.pack(anchor="w")
|
|
|
|
# schedule periodic UI updates
|
|
self.root.after(200, self.update_status_labels)
|
|
|
|
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
|
|
|
|
async_mainloop(self.root)
|
|
|
|
@async_handler
|
|
async def start_midi(self):
|
|
# Launch MidiHandler.run() as a background task
|
|
if self.midi_task is None or self.midi_task.done():
|
|
self.midi_task = asyncio.create_task(self.midi_handler.run())
|
|
|
|
def on_closing(self):
|
|
print("Closing application...")
|
|
if self.midi_task and not self.midi_task.done():
|
|
self.midi_task.cancel()
|
|
asyncio.create_task(self.websocket_client.close())
|
|
self.root.destroy()
|
|
|
|
# --- Asynchronous Update Functions ---
|
|
@async_handler
|
|
async def update_rgb(self, tab):
|
|
pass
|
|
|
|
def update_status_labels(self):
|
|
# Pull values from midi_handler
|
|
delay = self.midi_handler.delay
|
|
brightness = self.midi_handler.brightness
|
|
r = getattr(self.midi_handler, 'color_r', 0)
|
|
g = getattr(self.midi_handler, 'color_g', 0)
|
|
b = getattr(self.midi_handler, 'color_b', 0)
|
|
pattern = getattr(self.midi_handler, 'current_pattern', '') or '-'
|
|
n1 = getattr(self.midi_handler, 'n1', '-')
|
|
n2 = getattr(self.midi_handler, 'n2', '-')
|
|
bpm = getattr(self.midi_handler, 'current_bpm', None)
|
|
bpm_text = f"{bpm:.2f}" if isinstance(bpm, (float, int)) else "-"
|
|
|
|
self.lbl_delay.config(text=f"Delay: {delay}")
|
|
self.lbl_brightness.config(text=f"Brightness: {brightness}")
|
|
self.lbl_r.config(text=f"R: {r}")
|
|
self.lbl_g.config(text=f"G: {g}")
|
|
self.lbl_b.config(text=f"B: {b}")
|
|
self.lbl_pattern.config(text=f"Pattern: {pattern}")
|
|
self.lbl_n1.config(text=f"n1: {n1}")
|
|
self.lbl_n2.config(text=f"n2: {n2}")
|
|
self.lbl_bpm.config(text=f"BPM: {bpm_text}")
|
|
|
|
# reschedule
|
|
self.root.after(200, self.update_status_labels)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app = App()
|