Skip to content

Commit 03362a2

Browse files
Merge remote-tracking branch 'upstream/main'
2 parents 8925259 + 4005300 commit 03362a2

File tree

11 files changed

+92
-123
lines changed

11 files changed

+92
-123
lines changed

main-ui/controller/key_watcher_controller_miyoo_mini.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ def read_event(self, fd):
103103

104104
def poll_keyboard(self):
105105
logger = PyUiLogger.get_logger()
106-
logger.debug("Starting keyboard polling on fd %d", self.fd)
107106

108107
while True:
109108
now = time.time()

main-ui/devices/device_common.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,11 @@ def monitor_wifi(self):
236236

237237
time.sleep(10)
238238

239-
@throttle.limit_refresh(10)
239+
@throttle.limit_refresh(15)
240240
def get_wifi_status(self):
241241
if(self.is_wifi_enabled()):
242+
if(self.get_ip_addr_text() in ["Off","Error","Connecting"]):
243+
return WifiStatus.OFF
242244
wifi_connection_quality_info = self.get_wifi_connection_quality_info()
243245
# Composite score out of 100 based on weighted contribution
244246
# Adjust weights as needed based on empirical testing

main-ui/devices/miyoo/mini/miyoo_mini_common.py

Lines changed: 72 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
1-
import ctypes
2-
import fcntl
1+
import time
2+
from asyncio import sleep
33
import json
4-
import math
54
from pathlib import Path
65
import subprocess
76
import threading
8-
import time
9-
from zoneinfo import reset_tzpath
7+
import os
8+
from utils.logger import PyUiLogger
109
from controller.controller_inputs import ControllerInput
1110
from controller.key_state import KeyState
1211
from controller.key_watcher import KeyWatcher
13-
import os
1412
from controller.key_watcher_controller_miyoo_mini import InputResult, KeyEvent, KeyWatcherControllerMiyooMini
1513
from devices.miyoo.mini.miyoo_mini_flip_shared_memory_writer import MiyooMiniFlipSharedMemoryWriter
1614
from devices.miyoo.mini.miyoo_mini_flip_specific_model_variables import MiyooMiniSpecificModelVariables
@@ -20,14 +18,12 @@
2018
from devices.miyoo_trim_common import MiyooTrimCommon
2119
from devices.utils.file_watcher import FileWatcher
2220
from devices.utils.process_runner import ProcessRunner
23-
from display.display import Display
2421
from menus.games.utils.rom_info import RomInfo
25-
from menus.settings.timezone_menu import TimezoneMenu
2622
from utils import throttle
2723
from utils.config_copier import ConfigCopier
2824
from utils.ffmpeg_image_utils import FfmpegImageUtils
29-
from utils.logger import PyUiLogger
3025
from utils.py_ui_config import PyUiConfig
26+
from utils.time_logger import log_timing
3127

3228
MAX_VOLUME = 20
3329
MIN_RAW_VALUE = -60
@@ -43,47 +39,21 @@ class MiyooMiniCommon(MiyooDevice):
4339

4440

4541
def __init__(self, device_name, main_ui_mode, miyoo_mini_specific_model_variables: MiyooMiniSpecificModelVariables):
42+
4643
self.device_name = device_name
4744
self.miyoo_mini_specific_model_variables = miyoo_mini_specific_model_variables
4845
self.controller_interface = self.build_controller_interface()
49-
self.unknown_axis_ranges = {} # axis -> (min, max)
50-
self.unknown_axis_stats = {} # axis -> (sum, count)
51-
self.sdl_axis_names = {
52-
0: "SDL_CONTROLLER_AXIS_LEFTX",
53-
1: "SDL_CONTROLLER_AXIS_LEFTY",
54-
2: "SDL_CONTROLLER_AXIS_RIGHTX",
55-
3: "SDL_CONTROLLER_AXIS_RIGHTY",
56-
4: "SDL_CONTROLLER_AXIS_TRIGGERLEFT",
57-
5: "SDL_CONTROLLER_AXIS_TRIGGERRIGHT"
58-
}
59-
6046

6147
ConfigCopier.ensure_config("/mnt/SDCARD/Saves/mini-flip-system.json", Path(__file__).resolve().parent / 'mini-flip-system.json')
6248
self.system_config = SystemConfig("/mnt/SDCARD/Saves/mini-flip-system.json")
49+
6350
if(main_ui_mode):
64-
os.environ["TZPATH"] = "/mnt/SDCARD/miyoo285/zoneinfo"
65-
reset_tzpath() # reload TZPATH
6651
self.miyoo_mini_flip_shared_memory_writer = MiyooMiniFlipSharedMemoryWriter()
6752
self.miyoo_games_file_parser = MiyooGamesFileParser()
68-
self._set_lumination_to_config()
69-
self._set_contrast_to_config()
70-
self._set_saturation_to_config()
71-
self._set_brightness_to_config()
72-
self.ensure_wpa_supplicant_conf()
73-
self.init_gpio()
7453
self.mainui_volume = None
7554
self.mainui_config_thread, self.mainui_config_thread_stop_event = FileWatcher().start_file_watcher(
7655
"/appconfigs/system.json", self.on_mainui_config_change, interval=0.2)
7756
threading.Thread(target=self.startup_init, daemon=True).start()
78-
79-
if(PyUiConfig.enable_button_watchers()):
80-
from controller.controller import Controller
81-
#/dev/miyooio if we want to get rid of miyoo_inputd
82-
# debug in terminal: hexdump /dev/miyooio
83-
self.volume_key_watcher = KeyWatcher("/dev/input/event0")
84-
Controller.add_button_watcher(self.volume_key_watcher.poll_keyboard)
85-
volume_key_polling_thread = threading.Thread(target=self.volume_key_watcher.poll_keyboard, daemon=True)
86-
volume_key_polling_thread.start()
8757

8858
super().__init__()
8959

@@ -100,19 +70,31 @@ def on_mainui_config_change(self):
10070
old_volume = self.mainui_volume
10171
self.mainui_volume = data.get("vol")
10272
if(old_volume != self.mainui_volume):
73+
from display.display import Display
10374
Display.volume_changed(self.mainui_volume * 5)
10475

10576
except Exception as e:
10677
PyUiLogger.get_logger().warning(f"Error reading {path}: {e}")
10778
return None
10879

10980
def startup_init(self, include_wifi=True):
110-
config_volume = self.system_config.get_volume()
111-
self._set_volume(config_volume)
11281
if(self.is_wifi_enabled()):
11382
self.start_wifi_services()
11483
self.on_mainui_config_change()
115-
self.apply_timezone(self.system_config.get_timezone())
84+
self._set_lumination_to_config()
85+
self._set_contrast_to_config()
86+
self._set_saturation_to_config()
87+
self._set_brightness_to_config()
88+
self.ensure_wpa_supplicant_conf()
89+
self.init_gpio()
90+
if(PyUiConfig.enable_button_watchers()):
91+
from controller.controller import Controller
92+
#/dev/miyooio if we want to get rid of miyoo_inputd
93+
# debug in terminal: hexdump /dev/miyooio
94+
self.volume_key_watcher = KeyWatcher("/dev/input/event0")
95+
Controller.add_button_watcher(self.volume_key_watcher.poll_keyboard)
96+
volume_key_polling_thread = threading.Thread(target=self.volume_key_watcher.poll_keyboard, daemon=True)
97+
volume_key_polling_thread.start()
11698

11799
def build_controller_interface(self):
118100
key_mappings = {}
@@ -346,63 +328,64 @@ def get_volume(self):
346328
return self.mainui_volume * 5
347329
except:
348330
return 0
349-
350-
def _set_volume_raw(self, value: int, add: int = 0) -> int:
351-
try:
352-
fd = os.open("/dev/mi_ao", os.O_RDWR)
353-
except OSError:
354-
return 0
355-
356-
# Prepare buffers
357-
buf2 = (ctypes.c_int * 2)(0, 0)
358-
buf1 = (ctypes.c_uint64 * 2)(ctypes.sizeof(buf2), ctypes.cast(buf2, ctypes.c_void_p).value)
359331

360-
# Get previous volume
361-
fcntl.ioctl(fd, MI_AO_GETVOLUME, buf1)
362-
prev_value = buf2[1]
332+
def volume_up(self):
333+
try:
334+
subprocess.run(
335+
["send_event", "/dev/input/event0", "115:1"],
336+
check=False
337+
)
338+
except Exception as e:
339+
PyUiLogger.get_logger().exception(f"Failed to set volume via input events: {e}")
363340

364-
if add:
365-
value = prev_value + add
341+
def volume_down(self):
342+
try:
343+
subprocess.run(
344+
["send_event", "/dev/input/event0", "114:1"],
345+
check=False
346+
)
347+
except Exception as e:
348+
PyUiLogger.get_logger().exception(f"Failed to set volume via input events: {e}")
349+
350+
def change_volume(self, amount):
351+
self.system_config.reload_config()
352+
volume = self.get_volume() + amount
353+
if(volume < 0):
354+
volume = 0
355+
elif(volume > 100):
356+
volume = 100
357+
if(amount > 0):
358+
self.volume_up()
366359
else:
367-
value += MIN_RAW_VALUE
368-
369-
# Clamp value
370-
value = max(MIN_RAW_VALUE, min(MAX_RAW_VALUE, value))
371-
372-
if value == prev_value:
373-
os.close(fd)
374-
return prev_value
375-
376-
buf2[1] = value
377-
fcntl.ioctl(fd, MI_AO_SETVOLUME, buf1)
378-
379-
# Handle mute
380-
if prev_value <= MIN_RAW_VALUE < value:
381-
buf2[1] = 0
382-
fcntl.ioctl(fd, MI_AO_SETMUTE, buf1)
383-
elif prev_value > MIN_RAW_VALUE >= value:
384-
buf2[1] = 1
385-
fcntl.ioctl(fd, MI_AO_SETMUTE, buf1)
386-
387-
os.close(fd)
388-
return value
389-
360+
self.volume_down()
361+
sleep(0.1)
362+
self.on_mainui_config_change()
390363

391364
def _set_volume(self, volume: int) -> int:
392-
#Breaks keymon somehow
393-
if(False):
394-
volume = max(0, min(MAX_VOLUME, volume))
365+
event_dev = "/dev/input/event0"
395366

396-
volume_raw = 0
397-
if volume != 0:
398-
volume_raw = round(48 * math.log10(1 + volume)) # volume curve
367+
try:
368+
# Send volume-down (114) 20 times
369+
for _ in range(20):
370+
subprocess.run(
371+
["send_event", event_dev, "114:1"],
372+
check=False
373+
)
374+
time.sleep(0.2)
375+
# Send volume-up (115) volume//5 times
376+
for _ in range(volume // 5):
377+
subprocess.run(
378+
["send_event", event_dev, "115:1"],
379+
check=False
380+
)
381+
382+
except Exception as e:
383+
PyUiLogger.get_logger().exception(f"Failed to set volume via input events: {e}")
399384

400-
self._set_volume_raw(volume_raw, 0)
401385
return volume
402386

403387
def fix_sleep_sound_bug(self):
404-
config_volume = self.system_config.get_volume()
405-
self._set_volume(config_volume)
388+
pass #uneeded
406389

407390

408391
def run_game(self, rom_info: RomInfo) -> subprocess.Popen:
@@ -468,14 +451,8 @@ def supports_timezone_setting(self):
468451
return True
469452

470453
def prompt_timezone_update(self):
471-
timezone_menu = TimezoneMenu()
472-
tz = timezone_menu.ask_user_for_timezone(timezone_menu.list_timezone_files('/mnt/SDCARD/miyoo285/zoneinfo/', verify_via_datetime=False))
473-
474-
if (tz is not None):
475-
self.system_config.set_timezone(tz)
476-
self.apply_timezone(tz)
477-
Display.display_message_multiline(["Timezone changed","Reloading UI..."],2000)
478-
self.exit_pyui()
454+
#No timezone update for miyoo mini
455+
pass
479456

480457
def apply_timezone(self, timezone):
481458
ProcessRunner.run(["rm", "-f", "/tmp/localtime"])

main-ui/devices/miyoo/mini/sprig_miyoo_mini_common.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ def __init__(self, device_name, main_ui_mode, miyoo_mini_specific_model_variable
2222

2323
def startup_init(self, include_wifi=True):
2424
super().startup_init()
25+
config_volume = self.system_config.get_volume()
26+
self._set_volume(config_volume)
2527
self._set_screen_values_to_config()
2628

2729
def on_sprig_config_change(self):

main-ui/display/display.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ class Display:
9191
_problematic_images = set() # Class-level set to track images that won't load properly
9292
_problematic_image_keywords = [
9393
"No such file or directory",
94-
"Text has zero width"
94+
"Text has zero width",
95+
"Texture dimensions are limited",
96+
"Corrupt PNG"
9597
]
9698

9799
@classmethod
@@ -232,18 +234,15 @@ def deinit_display(cls):
232234
cls._text_texture_cache.clear_cache()
233235
cls._image_texture_cache.clear_cache()
234236
sdl2.SDL_QuitSubSystem(sdl2.SDL_INIT_VIDEO)
235-
PyUiLogger.get_logger().debug("Display deinitialized")
236237

237238
@classmethod
238239
def clear_text_cache(cls):
239-
PyUiLogger.get_logger().debug("Clearing text cache")
240240
cls._text_texture_cache.clear_cache()
241241
cls.deinit_fonts()
242242
cls.init_fonts()
243243

244244
@classmethod
245245
def clear_image_cache(cls):
246-
PyUiLogger.get_logger().debug("Clearing image cache")
247246
cls._image_texture_cache.clear_cache()
248247

249248
@classmethod
@@ -259,7 +258,6 @@ def deinit_fonts(cls):
259258

260259
@classmethod
261260
def reinitialize(cls, bg=None):
262-
PyUiLogger.get_logger().info("reinitialize display")
263261
cls.deinit_display()
264262
cls._unload_bg_texture()
265263
cls._init_display()
@@ -274,7 +272,6 @@ def _unload_bg_texture(cls):
274272
if cls.background_texture:
275273
sdl2.SDL_DestroyTexture(cls.background_texture)
276274
cls.background_texture = None
277-
PyUiLogger.get_logger().debug("Destroying bg texture")
278275

279276
@classmethod
280277
def restore_bg(cls, bg=None):
@@ -635,8 +632,7 @@ def render_image(cls, image_path: str, x: int, y: int, render_mode=RenderMode.TO
635632
if(surface_width > Device.max_texture_width() or surface_height > Device.max_texture_height()):
636633
sdl2.SDL_FreeSurface(surface)
637634
PyUiLogger.get_logger().warning(
638-
f"Image is too large to render. Skipping {image_path}\n"
639-
f"Stack trace:\n{''.join(traceback.format_stack())}"
635+
f"Image is too large to render ({surface_width} x {surface_height} with max of {Device.max_texture_width()} x {Device.max_texture_height()}). Skipping {image_path}\n"
640636
)
641637
cls._problematic_images.add(image_path)
642638
return 0, 0

main-ui/games/utils/box_art_resizer.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ def clear_interim_folders(cls, img_path):
142142

143143
@classmethod
144144
def patch_boxart_list(cls, image_list):
145-
cls.scan_count = 0
145+
cls.scan_count = len(image_list)
146146
cls.patched_count = 0
147147
threading.Thread(target=cls.monitor_for_input, daemon=True).start()
148148

@@ -163,6 +163,7 @@ def patch_boxart_list(cls, image_list):
163163
@classmethod
164164
def process_rom_folders(cls):
165165
"""Search through ROM directories and scale images inside Imgs folders."""
166+
Display.display_message(f"Starting boxart patching", 500)
166167
rom_paths = ["/mnt/SDCARD/Roms/", "/media/sdcard1/Roms/"]
167168
target_medium_width, target_medium_height = Device.get_boxart_medium_resize_dimensions()
168169
target_small_width, target_small_height = Device.get_boxart_small_resize_dimensions()

main-ui/mainui.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,9 @@ def main():
198198
args = parse_arguments()
199199
PyUiLogger.init(args.logDir, "PyUI")
200200
PyUiLogger.get_logger().info(f"{args}")
201-
#PyUiLogger.get_logger().info(f"logDir: {args.logDir}")
202-
#PyUiLogger.get_logger().info(f"pyUiConfig: {args.pyUiConfig}")
203-
#PyUiLogger.get_logger().info(f"device: {args.device}")
204201

205202
#log_renderer_info()
206203

207-
PyUiLogger.get_logger().info(f"{args}")
208204
with log_timing("Entire Startup initialization", PyUiLogger.get_logger()):
209205

210206
with log_timing("Config initialization", PyUiLogger.get_logger()):
@@ -242,9 +238,9 @@ def main():
242238
check_for_msg_display_socket_based(args)
243239
check_for_option_list_file(args)
244240

245-
main_menu = MainMenu()
241+
main_menu = MainMenu()
246242

247-
start_background_threads()
243+
start_background_threads()
248244
keep_running = True
249245
PyUiLogger.get_logger().info("Entering main loop")
250246
while(keep_running):

main-ui/menus/settings/extra_settings_menu.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,6 @@ def build_options_list(self):
204204
menu_options = CfwSystemConfig.get_menu_options(category=category)
205205
contains_entry_for_device = False
206206
for name, option in menu_options.items():
207-
PyUiLogger.get_logger().info(f"{option}")
208207
devices = option.get('devices')
209208
supported_device = not devices or Device.get_device_name() in devices
210209
if(supported_device):

0 commit comments

Comments
 (0)