diff --git a/home/stormux/.local/.functions/download.sh b/home/stormux/.local/.functions/download.sh index e9409cc..161c2c0 100755 --- a/home/stormux/.local/.functions/download.sh +++ b/home/stormux/.local/.functions/download.sh @@ -106,7 +106,7 @@ beep_download_progress() { command -v play > /dev/null 2>&1 || return 0 frequency="$((220 + (percent * 7)))" - play -q -n synth 0.06 sine "${frequency}" vol 0.12 > /dev/null 2>&1 || true + play -q -n synth 0.06 sine "${frequency}" vol 0.25 > /dev/null 2>&1 || true } monitor_download_progress() { diff --git a/home/stormux/.local/bin/game_launcher.py b/home/stormux/.local/bin/game_launcher.py index 7d15e30..4ef7e26 100755 --- a/home/stormux/.local/bin/game_launcher.py +++ b/home/stormux/.local/bin/game_launcher.py @@ -164,6 +164,7 @@ class VoicedMenu: # Load downloadable games registry self.downloadable_games = self.load_downloadable_games() self.savedMenuState = None + self.activeGameEntry = None def load_downloadable_games(self): """Load downloadable games registry from JSON file""" @@ -725,6 +726,7 @@ class VoicedMenu: self.currentItemIndices = self.savedMenuState["currentItemIndices"] self.menuSections = self.savedMenuState["menuSections"] self.savedMenuState = None + self.activeGameEntry = None self.draw_menu() self.announce_current_section() time.sleep(0.5) @@ -744,8 +746,40 @@ class VoicedMenu: def show_game_actions(self, gameEntry): """Show available actions for a game.""" + self.activeGameEntry = gameEntry self.show_action_menu(gameEntry.name, build_game_actions(gameEntry)) + def refresh_game_entry(self, gameEntry): + """Return a fresh game entry with current launcher state.""" + launchRoot = gameEntry.launchScript.parent if gameEntry.launchScript else Path.home() / ".local" / ".launch" + if gameEntry.installScript.parent.parent.name == ".install": + launchRoot = gameEntry.installScript.parent.parent.parent / ".launch" + + launchScript = find_launch_script(launchRoot, gameEntry.section, gameEntry.name) + return GameEntry(gameEntry.section, gameEntry.name, gameEntry.installScript, launchScript) + + def refresh_game_action_menu(self): + """Refresh the current game action submenu after install state changes.""" + if self.activeGameEntry is None: + return + + self.activeGameEntry = self.refresh_game_entry(self.activeGameEntry) + sectionName = self.activeGameEntry.name + self.sectionNames = [sectionName] + self.currentSection = 0 + self.currentItemIndices = {sectionName: 0} + self.menuSections = {sectionName: build_game_actions(self.activeGameEntry) + [("Back", self.restore_saved_menu)]} + self.draw_menu() + self.announce_current_item() + + def handle_escape(self): + """Handle Escape based on whether a temporary submenu is active.""" + if self.savedMenuState is None: + return False + + self.restore_saved_menu() + return True + def speak(self, text, interrupt=True): """Speak the given text with option to interrupt existing speech""" if self.speechClient is None: @@ -936,7 +970,10 @@ class VoicedMenu: # Update service menu items and redraw self.update_service_menu_items() - self.draw_menu() + if self.activeGameEntry is not None: + self.refresh_game_action_menu() + else: + self.draw_menu() # Let the user know the menu is activated self.speak("Game menu activated") @@ -1169,7 +1206,9 @@ class VoicedMenu: elif key == ord('b') or key == ord('B'): # Battery status self.report_battery_status() - elif key == 27: # Esc key - restart the application + elif key == 27: # Esc key - go back from submenus, otherwise restart the application + if self.handle_escape(): + continue try: # Announce restart first while speech still works self.speak("Restarting menu")