diff --git a/App/PyUI/main-ui/devices/miyoo/mini/miyoo_mini_common.py b/App/PyUI/main-ui/devices/miyoo/mini/miyoo_mini_common.py index 0b6bcc5b8..d8c88f593 100644 --- a/App/PyUI/main-ui/devices/miyoo/mini/miyoo_mini_common.py +++ b/App/PyUI/main-ui/devices/miyoo/mini/miyoo_mini_common.py @@ -488,4 +488,7 @@ def get_core_for_game(self, game_system_config, rom_file_path): core = game_system_config.get_effective_menu_selection("Emulator_MiyooMini", rom_file_path) if(core is None): core = game_system_config.get_effective_menu_selection("Emulator", rom_file_path) - return core \ No newline at end of file + return core + + def get_core_name_overrides(self, core_name): + return [core_name, core_name+"-32"] diff --git a/App/PyUI/main-ui/devices/trimui/trim_ui_brick.py b/App/PyUI/main-ui/devices/trimui/trim_ui_brick.py index e64e73715..ff6f056be 100644 --- a/App/PyUI/main-ui/devices/trimui/trim_ui_brick.py +++ b/App/PyUI/main-ui/devices/trimui/trim_ui_brick.py @@ -1,4 +1,6 @@ +import math from pathlib import Path +import subprocess import threading from audio.audio_player_delegate_sdl2 import AudioPlayerDelegateSdl2 from controller.controller_inputs import ControllerInput @@ -10,10 +12,14 @@ from devices.miyoo.system_config import SystemConfig from devices.miyoo_trim_common import MiyooTrimCommon from devices.trimui.trim_ui_device import TrimUIDevice +from devices.utils.file_watcher import FileWatcher +from devices.utils.process_runner import ProcessRunner +from display.display import Display from utils import throttle from utils.config_copier import ConfigCopier from utils.ffmpeg_image_utils import FfmpegImageUtils +from utils.logger import PyUiLogger from utils.py_ui_config import PyUiConfig class TrimUIBrick(TrimUIDevice): @@ -37,6 +43,8 @@ def __init__(self, device_name, main_ui_mode): self.ensure_wpa_supplicant_conf() threading.Thread(target=self.monitor_wifi, daemon=True).start() threading.Thread(target=self.startup_init, daemon=True).start() + self.config_watcher_thread, self.config_watcher_thread_stop_event = FileWatcher().start_file_watcher( + "/mnt/SDCARD/Saves/trim-ui-brick-system.json", self.on_system_config_changed, interval=0.2, repeat_trigger_for_mtime_granularity_issues=True) if(PyUiConfig.enable_button_watchers()): from controller.controller import Controller #/dev/miyooio if we want to get rid of miyoo_inputd @@ -48,6 +56,7 @@ def __init__(self, device_name, main_ui_mode): self.power_key_watcher = KeyWatcher("/dev/input/event1") power_key_polling_thread = threading.Thread(target=self.power_key_watcher.poll_keyboard, daemon=True) power_key_polling_thread.start() + # Done to try to account for external systems editting the config file super().__init__() @@ -60,7 +69,7 @@ def startup_init(self, include_wifi=True): self._set_hue_to_config() config_volume = self.system_config.get_volume() self._set_volume(config_volume) - + #Untested @throttle.limit_refresh(5) def is_hdmi_connected(self): @@ -157,3 +166,27 @@ def get_audio_system(self): def get_core_name_overrides(self, core_name): return [core_name, core_name+"-64"] + + def _set_volume(self, user_volume): + from display.display import Display + if(user_volume < 0): + user_volume = 0 + elif(user_volume > 100): + user_volume = 100 + volume = math.ceil(user_volume * 255//100) + + try: + + ProcessRunner.run( + ["amixer", "cset", f"numid=17", str(int(volume))], + check=True + ) + + except subprocess.CalledProcessError as e: + PyUiLogger.get_logger().error(f"Failed to set volume: {e}") + + self.system_config.reload_config() + self.system_config.set_volume(user_volume) + self.system_config.save_config() + Display.volume_changed(user_volume) + return user_volume \ No newline at end of file diff --git a/App/PyUI/main-ui/devices/trimui/trim_ui_device.py b/App/PyUI/main-ui/devices/trimui/trim_ui_device.py index 515e75ccc..3f2d37d92 100644 --- a/App/PyUI/main-ui/devices/trimui/trim_ui_device.py +++ b/App/PyUI/main-ui/devices/trimui/trim_ui_device.py @@ -12,6 +12,7 @@ from devices.miyoo_trim_common import MiyooTrimCommon from devices.utils.process_runner import ProcessRunner from devices.wifi.wifi_connection_quality_info import WiFiConnectionQualityInfo +from display.display import Display from games.utils.device_specific.miyoo_trim_game_system_utils import MiyooTrimGameSystemUtils from games.utils.game_entry import GameEntry from menus.games.utils.rom_info import RomInfo @@ -26,6 +27,13 @@ def __init__(self): self.game_utils = MiyooTrimGameSystemUtils() self.sdl2_controller_interface = Sdl2ControllerInterface() + def on_system_config_changed(self): + old_volume = self.system_config.get_volume() + self.system_config.reload_config() + new_volume = self.system_config.get_volume() + if(old_volume != new_volume): + Display.volume_changed(new_volume) + def get_controller_interface(self): return self.sdl2_controller_interface @@ -78,30 +86,6 @@ def _set_brightness_to_config(self): def _set_hue_to_config(self): with open("/sys/devices/virtual/disp/disp/attr/color_temperature", "w") as f: f.write(str((self.system_config.hue * 5) - 50)) - - def _set_volume(self, user_volume): - from display.display import Display - if(user_volume < 0): - user_volume = 0 - elif(user_volume > 100): - user_volume = 100 - volume = math.ceil(user_volume * 255//100) - - try: - - ProcessRunner.run( - ["amixer", "cset", f"numid=17", str(int(volume))], - check=True - ) - - except subprocess.CalledProcessError as e: - PyUiLogger.get_logger().error(f"Failed to set volume: {e}") - - self.system_config.reload_config() - self.system_config.set_volume(user_volume) - self.system_config.save_config() - Display.volume_changed(user_volume) - return user_volume def get_volume(self): return self.system_config.get_volume() diff --git a/App/PyUI/main-ui/devices/trimui/trim_ui_smart_pro.py b/App/PyUI/main-ui/devices/trimui/trim_ui_smart_pro.py index 6e0f7fb94..8539c148d 100644 --- a/App/PyUI/main-ui/devices/trimui/trim_ui_smart_pro.py +++ b/App/PyUI/main-ui/devices/trimui/trim_ui_smart_pro.py @@ -1,3 +1,5 @@ +import subprocess +import math from pathlib import Path import threading from audio.audio_player_delegate_sdl2 import AudioPlayerDelegateSdl2 @@ -10,10 +12,13 @@ from devices.miyoo.system_config import SystemConfig from devices.miyoo_trim_common import MiyooTrimCommon from devices.trimui.trim_ui_device import TrimUIDevice +from devices.utils.file_watcher import FileWatcher +from devices.utils.process_runner import ProcessRunner from utils import throttle from utils.config_copier import ConfigCopier from utils.ffmpeg_image_utils import FfmpegImageUtils +from utils.logger import PyUiLogger from utils.py_ui_config import PyUiConfig class TrimUISmartPro(TrimUIDevice): @@ -36,6 +41,8 @@ def __init__(self, device_name,main_ui_mode): self.ensure_wpa_supplicant_conf() threading.Thread(target=self.monitor_wifi, daemon=True).start() threading.Thread(target=self.startup_init, daemon=True).start() + self.config_watcher_thread, self.config_watcher_thread_stop_event = FileWatcher().start_file_watcher( + "/mnt/SDCARD/Saves/trim-ui-smart-pro-system.json", self.on_system_config_changed, interval=0.2, repeat_trigger_for_mtime_granularity_issues=True) if(PyUiConfig.enable_button_watchers()): from controller.controller import Controller #/dev/miyooio if we want to get rid of miyoo_inputd @@ -160,3 +167,28 @@ def get_audio_system(self): def get_core_name_overrides(self, core_name): return [core_name, core_name+"-64"] + + + def _set_volume(self, user_volume): + from display.display import Display + if(user_volume < 0): + user_volume = 0 + elif(user_volume > 100): + user_volume = 100 + volume = math.ceil(user_volume * 255//100) + + try: + + ProcessRunner.run( + ["amixer", "set", f"'Soft Volume Master'", str(int(volume))], + check=True + ) + + except subprocess.CalledProcessError as e: + PyUiLogger.get_logger().error(f"Failed to set volume: {e}") + + self.system_config.reload_config() + self.system_config.set_volume(user_volume) + self.system_config.save_config() + Display.volume_changed(user_volume) + return user_volume \ No newline at end of file diff --git a/App/PyUI/main-ui/devices/trimui/trim_ui_smart_pro_s.py b/App/PyUI/main-ui/devices/trimui/trim_ui_smart_pro_s.py index 0d285f3b4..dbc3fa328 100644 --- a/App/PyUI/main-ui/devices/trimui/trim_ui_smart_pro_s.py +++ b/App/PyUI/main-ui/devices/trimui/trim_ui_smart_pro_s.py @@ -198,3 +198,11 @@ def on_mainui_config_change(self): except Exception as e: PyUiLogger.get_logger().warning(f"Error reading {path}: {e}") return None + + def _set_lumination_to_config(self): + val = self.map_backlight_from_10_to_full_255(self.system_config.backlight) + try: + with open("/sys/class/backlight/backlight0/brightness", "w") as f: + f.write(str(val)) + except Exception as e: + PyUiLogger.get_logger().error(f"Error setting backlight: {e}") diff --git a/App/PyUI/main-ui/games/utils/device_specific/miyoo_trim_game_system_utils.py b/App/PyUI/main-ui/games/utils/device_specific/miyoo_trim_game_system_utils.py index 3807918e1..562260e21 100644 --- a/App/PyUI/main-ui/games/utils/device_specific/miyoo_trim_game_system_utils.py +++ b/App/PyUI/main-ui/games/utils/device_specific/miyoo_trim_game_system_utils.py @@ -29,7 +29,7 @@ class MiyooTrimGameSystemUtils(GameSystemUtils): "duckstation": ["DuckStation"], "easyrpg": ["EasyRPG Player"], "ecwolf": ["ECWolf"], - "fake08": ["FAKE-08"], + "fake08": ["FAKE-08","fake-08"], "fbalpha2012": ["FB Alpha 2012"], "fbneo": ["FinalBurn Neo"], "fceumm": ["FCEUmm"], diff --git a/spruce/scripts/buttons_watchdog.sh b/spruce/scripts/buttons_watchdog.sh index 20db6b812..e0e4cd034 100644 --- a/spruce/scripts/buttons_watchdog.sh +++ b/spruce/scripts/buttons_watchdog.sh @@ -123,9 +123,9 @@ save_volume_to_config_file() { # scan all button input EVENTS="$EVENT_PATH_KEYBOARD" -[ "$PLATFORM" = "Flip" ] && EVENTS="$EVENTS $EVENT_PATH_VOLUME" +[ -n "$EVENT_PATH_VOLUME" ] && [ -c "$EVENT_PATH_VOLUME" ] && EVENTS="$EVENTS $EVENT_PATH_VOLUME" getevent $EVENTS | while read line; do - + log_message "*** : $line" # first print event code to log file logger -p 15 -t "keymon[$$]" "$line" diff --git a/spruce/scripts/platform/SmartPro.cfg b/spruce/scripts/platform/SmartPro.cfg index 144e0d8ef..15f52ece8 100644 --- a/spruce/scripts/platform/SmartPro.cfg +++ b/spruce/scripts/platform/SmartPro.cfg @@ -59,6 +59,7 @@ export DEVICE_USES_64_BIT_RA="true" export EVENT_PATH_KEYBOARD="/dev/input/event3" export EVENT_PATH_JOYPAD="/dev/input/event4" +export EVENT_PATH_VOLUME="/dev/input/event0" export POWER_EVENT="/dev/input/event1" export B_POWER="1 116" diff --git a/spruce/scripts/platform/device.sh b/spruce/scripts/platform/device.sh index 99b135c0b..14288d640 100644 --- a/spruce/scripts/platform/device.sh +++ b/spruce/scripts/platform/device.sh @@ -142,14 +142,6 @@ enter_sleep() { log_message "Missing enter_sleep function" } -get_current_volume() { - log_message "Missing get_current_volume function" -} - -set_volume() { - log_message "Missing set_volume function" -} - reset_playback_pack() { log_message "Missing reset_playback_pack function" } @@ -254,10 +246,20 @@ volume_up() { log_message "Missing volume_up function" } +# System volume (why do we differentiate?) +get_current_volume() { + log_message "Missing get_current_volume function" +} + +# Config volume (We should normalize and not have 2 functions) get_volume_level() { log_message "Missing get_volume_level function" } +set_volume() { + log_message "Missing set_volume function" +} + brightness_down() { log_message "Missing brightness_down function" } diff --git a/spruce/scripts/platform/device_functions/Brick.sh b/spruce/scripts/platform/device_functions/Brick.sh index 1818060d1..c32d3e9f4 100644 --- a/spruce/scripts/platform/device_functions/Brick.sh +++ b/spruce/scripts/platform/device_functions/Brick.sh @@ -41,3 +41,9 @@ device_init() { run_trimui_osdd } + +set_volume() { + new_vol="${1:-0}" # default to mute if no value supplied + amixer cset 'numid=17' "$new_vol" +} + diff --git a/spruce/scripts/platform/device_functions/SmartPro.sh b/spruce/scripts/platform/device_functions/SmartPro.sh index 599e6fdde..d29445633 100644 --- a/spruce/scripts/platform/device_functions/SmartPro.sh +++ b/spruce/scripts/platform/device_functions/SmartPro.sh @@ -57,3 +57,9 @@ device_init() { run_trimui_osdd fi } + + +set_volume() { + new_vol="${1:-0}" # default to mute if no value supplied + amixer set 'Soft Volume Master' "$new_vol" +} \ No newline at end of file diff --git a/spruce/scripts/platform/device_functions/trimui_a133p.sh b/spruce/scripts/platform/device_functions/trimui_a133p.sh index c5f913d4c..baa2a1676 100644 --- a/spruce/scripts/platform/device_functions/trimui_a133p.sh +++ b/spruce/scripts/platform/device_functions/trimui_a133p.sh @@ -44,10 +44,37 @@ get_current_volume() { amixer get 'Soft Volume Master' | sed -n 's/.*Front Left: *\([0-9]*\).*/\1/p' | tr -d '[]%' } -set_volume() { - amixer set 'Soft Volume Master' "$new_vol" +set_volume_delta() { + delta="$1" + + current=$(get_volume_level) + [ -z "$current" ] && current=0 + + new=$((current + delta)) + + # Clamp 0–20 + [ "$new" -lt 0 ] && new=0 + [ "$new" -gt 20 ] && new=20 + + jq ".vol = $new" "$SYSTEM_JSON" > "${SYSTEM_JSON}.tmp" && mv "${SYSTEM_JSON}.tmp" "$SYSTEM_JSON" + + scaled=$(( new * 255 / 20 )) + set_volume "$scaled" +} + +volume_up() { + set_volume_delta 1 +} + +volume_down() { + set_volume_delta -1 } +get_volume_level() { + jq -r '.vol' "$SYSTEM_JSON" +} + + reset_playback_pack() { #TODO I think this is wrong log_message "*** audioFunctions.sh: reset playback path" -v @@ -117,6 +144,7 @@ post_pyui_exit(){ launch_startup_watchdogs(){ launch_common_startup_watchdogs + /mnt/SDCARD/spruce/scripts/buttons_watchdog.sh & }