Add MIDI device persistence functionality
- Add configuration file system to remember MIDI device selection - Load saved MIDI device preference on application startup - Automatically save MIDI device selection when changed - Handle device disconnection gracefully with fallback - Smart initialization with validation and error handling - Create config.json for storing device preferences - Improve user experience by eliminating need to re-select device
This commit is contained in:
43
src/main.py
43
src/main.py
@@ -2,6 +2,7 @@ import asyncio
|
|||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import ttk, messagebox # Import messagebox for confirmations
|
from tkinter import ttk, messagebox # Import messagebox for confirmations
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
from async_tkinter_loop import async_handler, async_mainloop
|
from async_tkinter_loop import async_handler, async_mainloop
|
||||||
from networking import WebSocketClient
|
from networking import WebSocketClient
|
||||||
import color_utils
|
import color_utils
|
||||||
@@ -10,6 +11,9 @@ import mido # Import mido for MIDI port detection
|
|||||||
import time
|
import time
|
||||||
from midi import MidiHandler # Import MidiHandler
|
from midi import MidiHandler # Import MidiHandler
|
||||||
|
|
||||||
|
# Configuration file path
|
||||||
|
CONFIG_FILE = "config.json"
|
||||||
|
|
||||||
# Dark theme colors (unchanged)
|
# Dark theme colors (unchanged)
|
||||||
bg_color = "#2e2e2e"
|
bg_color = "#2e2e2e"
|
||||||
fg_color = "white"
|
fg_color = "white"
|
||||||
@@ -36,11 +40,11 @@ class App:
|
|||||||
|
|
||||||
# --- MIDI Configuration ---
|
# --- MIDI Configuration ---
|
||||||
self.available_midi_ports = self.get_midi_ports()
|
self.available_midi_ports = self.get_midi_ports()
|
||||||
self.current_midi_port_index = 0 # Default to first port
|
self.current_midi_port_index = self.load_midi_device_preference() # Load saved preference
|
||||||
self.midi_handler: MidiHandler | None = None
|
self.midi_handler: MidiHandler | None = None
|
||||||
self.midi_task: asyncio.Task | None = None
|
self.midi_task: asyncio.Task | None = None
|
||||||
|
|
||||||
# Initialize MIDI handler with first available port (will be done after GUI is created)
|
# Initialize MIDI handler with saved port (will be done after GUI is created)
|
||||||
self.pending_midi_init = True if self.available_midi_ports else False
|
self.pending_midi_init = True if self.available_midi_ports else False
|
||||||
|
|
||||||
# Configure ttk style (unchanged)
|
# Configure ttk style (unchanged)
|
||||||
@@ -61,7 +65,12 @@ class App:
|
|||||||
# MIDI port dropdown
|
# MIDI port dropdown
|
||||||
self.midi_port_var = tk.StringVar()
|
self.midi_port_var = tk.StringVar()
|
||||||
if self.available_midi_ports:
|
if self.available_midi_ports:
|
||||||
self.midi_port_var.set(self.available_midi_ports[0])
|
# Set to saved preference if available, otherwise first port
|
||||||
|
if 0 <= self.current_midi_port_index < len(self.available_midi_ports):
|
||||||
|
self.midi_port_var.set(self.available_midi_ports[self.current_midi_port_index])
|
||||||
|
else:
|
||||||
|
self.midi_port_var.set(self.available_midi_ports[0])
|
||||||
|
self.current_midi_port_index = 0
|
||||||
|
|
||||||
midi_dropdown = ttk.Combobox(
|
midi_dropdown = ttk.Combobox(
|
||||||
midi_frame,
|
midi_frame,
|
||||||
@@ -230,6 +239,32 @@ class App:
|
|||||||
|
|
||||||
async_mainloop(self.root)
|
async_mainloop(self.root)
|
||||||
|
|
||||||
|
def load_midi_device_preference(self):
|
||||||
|
"""Load saved MIDI device preference from config file"""
|
||||||
|
try:
|
||||||
|
if os.path.exists(CONFIG_FILE):
|
||||||
|
with open(CONFIG_FILE, 'r') as f:
|
||||||
|
config = json.load(f)
|
||||||
|
saved_index = config.get('midi_device_index', 0)
|
||||||
|
print(f"Loaded MIDI device preference: index {saved_index}")
|
||||||
|
return saved_index
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error loading MIDI device preference: {e}")
|
||||||
|
return 0 # Default to first port
|
||||||
|
|
||||||
|
def save_midi_device_preference(self):
|
||||||
|
"""Save current MIDI device preference to config file"""
|
||||||
|
try:
|
||||||
|
config = {
|
||||||
|
'midi_device_index': self.current_midi_port_index,
|
||||||
|
'midi_device_name': self.available_midi_ports[self.current_midi_port_index] if self.available_midi_ports else None
|
||||||
|
}
|
||||||
|
with open(CONFIG_FILE, 'w') as f:
|
||||||
|
json.dump(config, f, indent=2)
|
||||||
|
print(f"Saved MIDI device preference: {config['midi_device_name']} (index {config['midi_device_index']})")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error saving MIDI device preference: {e}")
|
||||||
|
|
||||||
def get_midi_ports(self):
|
def get_midi_ports(self):
|
||||||
"""Get list of available MIDI input ports"""
|
"""Get list of available MIDI input ports"""
|
||||||
try:
|
try:
|
||||||
@@ -286,6 +321,7 @@ class App:
|
|||||||
# Current selection is no longer available, select first available
|
# Current selection is no longer available, select first available
|
||||||
self.midi_port_var.set(self.available_midi_ports[0])
|
self.midi_port_var.set(self.available_midi_ports[0])
|
||||||
self.current_midi_port_index = 0
|
self.current_midi_port_index = 0
|
||||||
|
self.save_midi_device_preference() # Save the new preference
|
||||||
self.restart_midi_handler()
|
self.restart_midi_handler()
|
||||||
elif not self.available_midi_ports:
|
elif not self.available_midi_ports:
|
||||||
# No ports available
|
# No ports available
|
||||||
@@ -305,6 +341,7 @@ class App:
|
|||||||
if selected_port in self.available_midi_ports:
|
if selected_port in self.available_midi_ports:
|
||||||
self.current_midi_port_index = self.available_midi_ports.index(selected_port)
|
self.current_midi_port_index = self.available_midi_ports.index(selected_port)
|
||||||
print(f"MIDI port changed to: {selected_port} (index: {self.current_midi_port_index})")
|
print(f"MIDI port changed to: {selected_port} (index: {self.current_midi_port_index})")
|
||||||
|
self.save_midi_device_preference() # Save the new preference
|
||||||
self.restart_midi_handler()
|
self.restart_midi_handler()
|
||||||
|
|
||||||
@async_handler
|
@async_handler
|
||||||
|
|||||||
Reference in New Issue
Block a user