import subprocess import time import threading import os import runtime.whisplay_client class WhisplayInterface: LONG_PRESS_THRESHOLD = 0.5 DOUBLE_PRESS_THRESHOLD = 0.3 def __init__(self): self.board = None self._lock = threading.Lock() self._is_pressing = False self._is_double_pressing = False self._is_long_pressing = False self._long_press_timer_thread = None self._button_press_start = None self._button_press_end = None self._on_press_callback = None self._on_release_callback = None self._on_long_press_callback = None self._on_long_release_callback = None self._on_double_press_callback = None self._on_double_release_callback = None self.set_wm8960_volume_stable(speaker=200, mic=80) def create_board(self): self.board = runtime.whisplay_client.create_whisplay_hardware( app_id=os.getenv("WHISPLAY_APP_ID", "whisplay-lxst-client"), display_name="LXST Client", icon="L", exit_gesture="quad_press", use_daemon_default_log=False, ) self.board.on_button_press(self._on_button_press) self.board.on_button_release(self._on_button_release) # -- Internal press/release (called from GPIO thread) -- def on_press(self, callback): self._on_press_callback = callback def on_release(self, callback): self._on_release_callback = callback def on_long_press(self, callback): self._on_long_press_callback = callback def on_long_release(self, callback): self._on_long_release_callback = callback def on_double_press(self, callback): self._on_double_press_callback = callback def on_double_release(self, callback): self._on_double_release_callback = callback def _on_button_press(self): with self._lock: self._is_pressing = True self._button_press_start = time.time() if self._button_press_end is not None: time_since_last_press = self._button_press_start- self._button_press_end if time_since_last_press <= self.DOUBLE_PRESS_THRESHOLD: self._is_double_pressing = True if self._on_double_press_callback: self._on_double_press_callback() if not self._is_double_pressing: if self._on_press_callback: self._on_press_callback() self._long_press_timer_thread = threading.Timer(self.LONG_PRESS_THRESHOLD, self._long_press_timer) self._long_press_timer_thread.start() def _on_button_release(self): with self._lock: self._long_press_timer_thread.cancel() self._is_pressing = False self._button_press_end = time.time() if self._is_double_pressing: if self._on_double_release_callback: self._on_double_release_callback() self._is_double_pressing = False elif self._is_long_pressing: if self._on_long_release_callback: self._on_long_release_callback() self._is_long_pressing = False else: if self._on_release_callback: self._on_release_callback() def _long_press_timer(self): with self._lock: if self._is_pressing: self._is_long_pressing = True if self._on_long_press_callback: self._on_long_press_callback() def set_wm8960_volume_stable(self, speaker: int = 0, mic: int = 0): CARD_NAME = 'wm8960soundcard' DEVICE_ARG = f'hw:{CARD_NAME}' try: subprocess.run(['amixer', '-D', DEVICE_ARG, 'sset', 'Speaker', str(speaker)], check=False, capture_output=True) subprocess.run(['amixer', '-D', DEVICE_ARG, 'sset', 'Capture', str(mic)], check=False, capture_output=True) except Exception as e: print(f"ERROR: Failed to set volume: {e}")