107 lines
3.9 KiB
Python
107 lines
3.9 KiB
Python
"""
|
|
Configuration module for MIDI-to-Hue application.
|
|
Handles loading, creating and validating configuration.
|
|
"""
|
|
import os
|
|
import json
|
|
from typing import Dict, Any, Optional
|
|
|
|
# Default config file path
|
|
DEFAULT_CONFIG_FILE = 'midi_hue_config.json'
|
|
|
|
# Default MIDI-to-Hue mapping if no config file exists
|
|
DEFAULT_CONFIG = {
|
|
"midi_device": 1, # Index of MIDI device to use (from available inputs list)
|
|
"update_interval_ms": 50, # Throttling interval in milliseconds
|
|
"bridge_ip": "192.168.178.35", # Default Bridge IP
|
|
"mappings": [
|
|
{
|
|
"midi_channel": 5,
|
|
"midi_control": 1,
|
|
"light_name": "Zimmer Decke",
|
|
"parameter": "bri",
|
|
"value_transform": "value * 2" # MIDI range 0-127 to Hue brightness 0-254
|
|
},
|
|
{
|
|
"midi_channel": 6,
|
|
"midi_control": 1,
|
|
"light_name": "Fernseher links",
|
|
"parameter": "bri",
|
|
"value_transform": "value * 2" # MIDI range 0-127 to Hue brightness 0-254
|
|
},
|
|
]
|
|
}
|
|
|
|
class ConfigManager:
|
|
"""Manages configuration loading, validation and access."""
|
|
|
|
def __init__(self, config_file: str = DEFAULT_CONFIG_FILE):
|
|
"""Initialize the config manager with a specific config file."""
|
|
self.config_file = config_file
|
|
self.config = self._load_or_create_config()
|
|
|
|
def _load_or_create_config(self) -> Dict[str, Any]:
|
|
"""Load config from file or create with defaults if it doesn't exist."""
|
|
try:
|
|
if os.path.exists(self.config_file):
|
|
with open(self.config_file, 'r') as f:
|
|
config = json.load(f)
|
|
print(f"Loaded configuration from {self.config_file}")
|
|
return config
|
|
except Exception as e:
|
|
print(f"Error loading config file: {e}")
|
|
|
|
# If we get here, either the file doesn't exist or there was an error
|
|
# Create the default config file
|
|
with open(self.config_file, 'w') as f:
|
|
json.dump(DEFAULT_CONFIG, f, indent=4)
|
|
print(f"Created default configuration file at {self.config_file}")
|
|
|
|
return DEFAULT_CONFIG
|
|
|
|
def get(self, key: str, default: Any = None) -> Any:
|
|
"""Get a configuration value by key with a default fallback."""
|
|
return self.config.get(key, default)
|
|
|
|
def get_mappings(self) -> list:
|
|
"""Get all mappings from the configuration."""
|
|
return self.config.get("mappings", [])
|
|
|
|
def get_bridge_ip(self) -> str:
|
|
"""Get the Bridge IP address."""
|
|
return self.config.get("bridge_ip", "192.168.178.35")
|
|
|
|
def get_update_interval_sec(self) -> float:
|
|
"""Get the update interval in seconds."""
|
|
update_interval_ms = self.config.get("update_interval_ms", 50)
|
|
return update_interval_ms / 1000 # Convert to seconds
|
|
|
|
def get_midi_device_index(self) -> int:
|
|
"""Get the MIDI device index."""
|
|
return self.config.get("midi_device", 1)
|
|
|
|
def get_stt_config(self) -> Dict[str, Any]:
|
|
"""Get the speech-to-text configuration."""
|
|
default_stt_config = {
|
|
"enabled": False,
|
|
"audio_device_index": 1,
|
|
"language": "de",
|
|
"api_key": "",
|
|
"api_endpoint": "https://api.openai.com/v1/audio/transcriptions",
|
|
"midi_trigger": {
|
|
"channel": 1,
|
|
"note": 1,
|
|
"type": "note_on"
|
|
}
|
|
}
|
|
return self.config.get("speech_to_text", default_stt_config)
|
|
|
|
def is_stt_enabled(self) -> bool:
|
|
"""Check if speech-to-text is enabled in the configuration."""
|
|
stt_config = self.get_stt_config()
|
|
return stt_config.get("enabled", False)
|
|
|
|
def get_stt_midi_trigger(self) -> Dict[str, Any]:
|
|
"""Get MIDI trigger configuration for speech-to-text."""
|
|
stt_config = self.get_stt_config()
|
|
return stt_config.get("midi_trigger", {})
|