diff --git a/Fruit_Jam/Larsio_Paint_Music/code.py b/Fruit_Jam/Larsio_Paint_Music/code.py old mode 100755 new mode 100644 index 7f449e14d..1fea1ed76 --- a/Fruit_Jam/Larsio_Paint_Music/code.py +++ b/Fruit_Jam/Larsio_Paint_Music/code.py @@ -13,6 +13,9 @@ import time import gc +import sys +import atexit +import supervisor from sound_manager import SoundManager from note_manager import NoteManager from ui_manager import UIManager @@ -86,6 +89,23 @@ def run(self): gc.collect() print("Starting Music Staff Application...") + def atexit_callback(): + """ + re-attach USB devices to kernel if needed. + :return: + """ + print("inside atexit callback") + if app.ui_manager.input_handler.mouse is not None: + mouse = app.ui_manager.input_handler.mouse + mouse.release() + if mouse.was_attached: + # The keyboard buffer seems to have data left over from when it was detached + # This clears it before the next process starts + while supervisor.runtime.serial_bytes_available: + sys.stdin.read(1) + + atexit.register(atexit_callback) + try: app = MusicStaffApp(audio_output=AUDIO_OUTPUT) app.run() @@ -102,3 +122,5 @@ def run(self): app.run() except Exception as e2: # pylint: disable=broad-except print(f"Fatal error: {e2}") + + supervisor.reload() diff --git a/Fruit_Jam/Larsio_Paint_Music/input_handler.py b/Fruit_Jam/Larsio_Paint_Music/input_handler.py old mode 100755 new mode 100644 index 23e7d3151..f5badeccf --- a/Fruit_Jam/Larsio_Paint_Music/input_handler.py +++ b/Fruit_Jam/Larsio_Paint_Music/input_handler.py @@ -5,7 +5,7 @@ # input_handler.py: CircuitPython Music Staff Application component """ -from adafruit_usb_host_mouse import find_and_init_boot_mouse +from adafruit_usb_host_mouse import find_and_init_boot_mouse, find_and_init_report_mouse # pylint: disable=invalid-name,no-member,too-many-instance-attributes,too-many-arguments # pylint: disable=too-many-branches,too-many-statements,broad-except @@ -34,6 +34,9 @@ def __init__(self, screen_width, screen_height, staff_y_start, staff_height): def find_mouse(self): self.mouse = find_and_init_boot_mouse(cursor_image=None) + if self.mouse is None: + self.mouse = find_and_init_report_mouse(cursor_image=None) + if self.mouse is None: print("Failed to find a working mouse after multiple attempts") return False diff --git a/Fruit_Jam/Larsio_Paint_Music/ui_manager.py b/Fruit_Jam/Larsio_Paint_Music/ui_manager.py index 00c953945..e83ae2cb8 100755 --- a/Fruit_Jam/Larsio_Paint_Music/ui_manager.py +++ b/Fruit_Jam/Larsio_Paint_Music/ui_manager.py @@ -84,6 +84,7 @@ def __init__(self, sound_manager, note_manager): self.triangle_cursor = None self.tempo_minus_label = None self.tempo_plus_label = None + self.exit_button_label = None # Channel setting self.current_channel = 0 @@ -124,6 +125,9 @@ def setup_display(self): # Create tempo display self._create_tempo_display() + # Add Exit button + self._create_exit_button() + # Create highlight self.highlight_grid = self.staff_view.create_highlight() self.main_group.append(self.highlight_grid) @@ -206,6 +210,21 @@ def _create_note_name_label(self): self.note_name_label.anchored_position = (10, self.SCREEN_HEIGHT - 70) self.main_group.append(self.note_name_label) + def _create_exit_button(self): + """Create a lable to be used as an "Exit" button""" + gc.collect() + + self.exit_button_label = Label( + terminalio.FONT, + text="Exit", + color=0xFFFFFF, + background_color=0xFF0000, + scale=1 + ) + self.exit_button_label.anchor_point = (0.5, 0.5) + self.exit_button_label.anchored_position = (self.SCREEN_WIDTH - 135, 10) + self.main_group.append(self.exit_button_label) + def _create_tempo_display(self): """Create a label for the tempo display with + and - buttons""" gc.collect() # Force garbage collection before creating the label @@ -496,17 +515,26 @@ def handle_mouse_buttons(self): # Check for tempo button clicks minus_button_x, minus_button_y = self.tempo_minus_label.anchored_position plus_button_x, plus_button_y = self.tempo_plus_label.anchored_position + exit_button_x, exit_button_y = self.exit_button_label.anchored_position button_radius = 8 # Allow a bit of space around the button for easier clicking + # Radius 16**2 = 256, but squared to a y < 16 + if ( + ((mouse_x - exit_button_x)**2 + (mouse_y - exit_button_y)**2) < 256 and + mouse_y < 16): + + # Clicked Exit button + return False + if ((mouse_x - minus_button_x)**2 + (mouse_y - minus_button_y)**2) < button_radius**2: # Clicked minus button - decrease tempo self.adjust_tempo(-1) - return + return True if ((mouse_x - plus_button_x)**2 + (mouse_y - plus_button_y)**2) < button_radius**2: # Clicked plus button - increase tempo self.adjust_tempo(1) - return + return True # Check if a channel button was clicked channel_clicked = False @@ -565,6 +593,8 @@ def handle_mouse_buttons(self): ) self.note_name_label.text = message + return True + def _add_note_based_on_channel(self, x, y): """Add a note based on the current channel""" if self.current_channel == 0: @@ -641,4 +671,5 @@ def main_loop(self): self.handle_mouse_position() # Handle mouse button presses - self.handle_mouse_buttons() + if not self.handle_mouse_buttons(): + break