From 597b007333d8ec0d9cfd29e6941fcbe57379108a Mon Sep 17 00:00:00 2001 From: Sébastien Dailly Date: Mon, 22 May 2023 08:40:47 +0200 Subject: Initial commit --- src/code.py | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 src/code.py (limited to 'src/code.py') diff --git a/src/code.py b/src/code.py new file mode 100644 index 0000000..813574a --- /dev/null +++ b/src/code.py @@ -0,0 +1,158 @@ +# SPDX-FileCopyrightText: 2021 Phillip Burgess for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +""" +A macro/hotkey program for Adafruit MACROPAD. Macro setups are stored in the +/macros folder (configurable below), load up just the ones you're likely to +use. Plug into computer's USB port, use dial to select an application macro +set, press MACROPAD keys to send key sequences and other USB protocols. +""" + +# pylint: disable=import-error, unused-import, too-few-public-methods + +import os +import time +import displayio +import terminalio + +import usb_cdc +import json + +#from adafruit_display_shapes.rect import Rect +#from adafruit_display_text import label +from adafruit_macropad import MacroPad + +from supervisor import runtime + +from actions import Action +import skeleton +import menu + +# CONFIGURABLES ------------------------ + +MACRO_FOLDER = '/macros' + + +# INITIALIZATION ----------------------- + +# Do not reload the application when the files are changed +runtime.autoreload = False + +macropad = MacroPad() +macropad.display.auto_refresh = False +macropad.pixels.auto_write = False + +Action().set_macropad(macropad) + +# Load all the macro key setups from .py files in MACRO_FOLDER +apps = [] +files = os.listdir(MACRO_FOLDER) +files.sort() +for filename in files: + if filename.startswith('._'): + continue + if filename.endswith('.py'): + module_name = filename[:-3] + elif filename.endswith('.mpy'): + module_name = filename[:-4] + else: + continue + + try: + module = __import__(MACRO_FOLDER + '/' + module_name) + apps.append(module.configuration) + except (SyntaxError, ImportError, AttributeError, KeyError, NameError, + IndexError, TypeError) as err: + print("ERROR in", filename) + import traceback + traceback.print_exception(err, err, err.__traceback__) + +if not apps: + group[13].text = 'NO MACRO FILES FOUND' + macropad.display.refresh() + while True: + pass + +app_index = 0 + +def run_application(app): + # Read encoder position. If it's changed, declare it as a button. + position = app.macropad.encoder + if position > app.position: + app.position = position + key_number = 12 + pressed = True + elif position < app.position: + app.position = position + key_number = 13 + pressed = True + else: + event = app.macropad.keys.events.get() + if not event: + app.tick() + return # No key events + key_number = event.key_number + pressed = event.pressed + + return app.execute_action(key_number, pressed or False) + +def switch_layout(configuration): + global app + app = skeleton.Handler(macropad, configuration) + app.start() + + +def search_and_switch(layout): + found_application = False + for local_app in apps: + if local_app.title == layout and app is not local_app: + found_application = True + switch_layout(local_app) + break + +def send_layout(_any): + if usb_cdc.data.connected: + usb_cdc.data.write(bytes("%s\n" % app.name, "utf-8")) + +actions = { + "layout" : search_and_switch, + "get_layout" : send_layout, + } + +switch_layout(apps[app_index]) + +# MAIN LOOP ---------------------------- + +while True: + + # First read from the serial + # If we have an application name from the command line, switch to this app. + if usb_cdc.data.connected and usb_cdc.data.in_waiting != 0: + line = usb_cdc.data.read(usb_cdc.data.in_waiting).strip() + commands = json.loads(line) + for command in commands: + for key, value in command.items(): + actions[key](value) + continue + + # Handle encoder button. If state has changed, and if there's a + # corresponding macro, set up variables to act on this just like + # the keypad keys, as if it were a 13th key/macro. + app.macropad.encoder_switch_debounced.update() + encoder_switch = app.macropad.encoder_switch_debounced.pressed + # On the encoder button, switch to the next mode + if encoder_switch: + + config = menu.build_application(apps) + menu_app = skeleton.Handler(macropad, config) + menu_app.start() + while True: + configuration = run_application(menu_app) + if configuration is None: continue + switch_layout(configuration) + break + send_layout(None) + + run_application(app) + continue -- cgit v1.2.3