diff --git a/.gitignore b/.gitignore index 95da7b5..ebe7643 100644 --- a/.gitignore +++ b/.gitignore @@ -116,3 +116,4 @@ dmypy.json .idea* +config.json \ No newline at end of file diff --git a/code.py b/code.py index b26eb85..8663e88 100644 --- a/code.py +++ b/code.py @@ -1,22 +1,40 @@ -from macropad_os import AppRouter, SerialComms, Config +import os + +from macropad_os import MacropadOS, SerialComms, Config, App from adafruit_macropad import MacroPad -from macropad_apps.python import NumpadApp - macropad = MacroPad() default_config = Config("default_config.json").load() config = Config("config.json").load(default_config) -ar = AppRouter(macropad, config, [ - NumpadApp(macropad, config), -# Arrow Keys -# Script Runner -]) +PYTHON_APP_FOLDER = "./macropad_apps/python" -sc = SerialComms(config) +apps = [] +files = os.listdir(PYTHON_APP_FOLDER) +files.sort() + +app_classes = [] +for filename in files: + if filename.endswith('.py') and not filename.startswith('._'): + try: + print(filename) + module = __import__(PYTHON_APP_FOLDER + '/' + filename[:-3]) + classes = [getattr(module, a) for a in dir(module) + if isinstance(getattr(module, a), type)] + for cls in classes: + if issubclass(cls, App) and cls.__name__ != "App": + app_classes.append(cls) + print(app_classes) + except (SyntaxError, ImportError, AttributeError, KeyError, NameError, IndexError, TypeError) as err: + print("ERROR in", filename) + import traceback + + traceback.print_exception(err, err, err.__traceback__) + +ar = MacropadOS(macropad, config, apps=app_classes) +# sc = SerialComms(config) # _thread.start_new_thread(sc.run, (sc)) - ar.start() diff --git a/macropad_apps/python/__init__.py b/macropad_apps/python/__init__.py deleted file mode 100644 index e37fb02..0000000 --- a/macropad_apps/python/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .numpad import NumpadApp \ No newline at end of file diff --git a/macropad_apps/python/numpad.py b/macropad_apps/python/numpad.py index f321e6e..bbe54de 100644 --- a/macropad_apps/python/numpad.py +++ b/macropad_apps/python/numpad.py @@ -1,8 +1,10 @@ +from time import monotonic_ns + import terminalio from adafruit_display_text.bitmap_label import Label -from adafruit_display_text.scrolling_label import ScrollingLabel from adafruit_displayio_layout.layouts.grid_layout import GridLayout +from adafruit_hid.keycode import Keycode from rainbowio import colorwheel from macropad_os import App @@ -24,6 +26,8 @@ modified_labels = [ ] +COLOR_UPDATE_RATE = 50000000 # .05 seconds + class NumpadApp(App): def __init__(self, macropad, config): @@ -34,6 +38,7 @@ class NumpadApp(App): self.labels = [] self.title = "Numpad" self.modifier_pressed = False + self.last_color_update = 0 def on_start(self): print("on start from the app!") @@ -65,6 +70,10 @@ class NumpadApp(App): def update_key_colors(self): self.wheel_offset += 1 colors = [] + + last_update_ago = monotonic_ns() - self.last_color_update + if last_update_ago > COLOR_UPDATE_RATE: + self.last_color_update = monotonic_ns() for pixel in range(12): if self.lit_keys[pixel]: (r, g, b) = rgb_from_int(colorwheel((pixel / 12 * 256) + self.wheel_offset)) @@ -74,12 +83,11 @@ class NumpadApp(App): self.set_colors(colors) def process_keys_pressed_callback(self, keyevent): - print("PROCESS KEYS CALLBACK FROM DEBUG") print(keyevent) + self.keyboard.send(Keycode.SHIFT,Keycode.SHIFT,Keycode.SHIFT, Keycode.A) def process_keys_released_callback(self, keyevent): - print("PROCESS KEYS RELEASED CALLBACK FROM DEBUG") print(keyevent) + def process_enbcoder_changed(self, keyevent): - print("PROCESS Encoder Changed Callback FROM DEBUG") - print(keyevent) + print(keyevent) \ No newline at end of file diff --git a/macropad_os/__init__.py b/macropad_os/__init__.py index 2afbcca..32095b6 100644 --- a/macropad_os/__init__.py +++ b/macropad_os/__init__.py @@ -2,4 +2,4 @@ from .serial_communications import SerialComms from .configuration import Config, ConfigItem from .app_state import AppState, InvalidStateUpdateError from .abstract_app import App -from .app_router import AppRouter \ No newline at end of file +from .macropad_os import MacropadOS \ No newline at end of file diff --git a/macropad_os/abstract_app.py b/macropad_os/abstract_app.py index 0b2a279..f2935e8 100644 --- a/macropad_os/abstract_app.py +++ b/macropad_os/abstract_app.py @@ -1,4 +1,4 @@ -import time +from time import monotonic_ns import displayio import terminalio @@ -12,6 +12,9 @@ DISPLAY = displayio.Group() def convert_to_keynum(x, y): return 3 * x + y +#TODO: Limit sounds to a similar rate as well for better performance + +MAX_LIGHTING_UPDATE_RATE = 50000000 # .05 seconds class App(object): @@ -42,10 +45,12 @@ class App(object): self._state = AppState.STOPPED self._name = "app" self._key_tones = {} + self._last_lighting_update = 0 self._current_brightness = config.brightness() self.macropad = macropad + self.keyboard = macropad.keyboard self.config = config def start(self) -> None: @@ -86,7 +91,7 @@ class App(object): self._state = AppState.PAUSED def _on_pause(self) -> None: - self.macropad.keyboard.release_all() + self.keyboard.release_all() self.macropad.consumer_control.release() self.macropad.mouse.release_all() self.macropad.stop_tone() @@ -116,7 +121,6 @@ class App(object): if key_event.key_number < 12: if key_event.pressed: self.macropad.stop_tone() - print(self.config.get_items()) self._play_tone_for_key(key_event.key_number) if self._key_pressed_callbacks: for callback in self._key_pressed_callbacks: @@ -124,7 +128,7 @@ class App(object): else: self._stop_tone_for_key(key_event.key_number) if self._key_released_callbacks: - for callback in self._key_pressed_callbacks: + for callback in self._key_released_callbacks: callback(key_event.key_number) def _play_tone_for_key(self, key_number): @@ -169,16 +173,17 @@ class App(object): raise NotImplementedError("on_stop not implemented.") def _update_lighting(self) -> None: - new_brightness = self.config.brightness() - if self._current_brightness != new_brightness: - print("SETTING BRIGHTNESS!!!!") - print(self._key_lights) - self._key_lights = [tuple(rgb_val * new_brightness / self._current_brightness for rgb_val in color) for - color in self._key_lights] - print(self._key_lights) - self._current_brightness = self.config.brightness() - for index, color in enumerate(self._key_lights): - self.macropad.pixels[index] = color + last_update_ago = monotonic_ns() - self._last_lighting_update + if last_update_ago > MAX_LIGHTING_UPDATE_RATE: + self._last_lighting_update = monotonic_ns() + new_brightness = self.config.brightness() + if self._current_brightness != new_brightness: + # Setting the brightness here + self._key_lights = [tuple(rgb_val * new_brightness / self._current_brightness for rgb_val in color) for + color in self._key_lights] + self._current_brightness = self.config.brightness() + for index, color in enumerate(self._key_lights): + self.macropad.pixels[index] = color def add_displays_to_group(self) -> None: self._display_group.append(self._title_label) diff --git a/macropad_os/app_utils/key.py b/macropad_os/app_utils/key.py new file mode 100644 index 0000000..163f4a6 --- /dev/null +++ b/macropad_os/app_utils/key.py @@ -0,0 +1,6 @@ +from adafruit_hid.keycode import Keycode + +class Key(object): + def __init__(self, name, keycode:Keycodes): + self.name = name + self.code = keycode \ No newline at end of file diff --git a/macropad_os/app_router.py b/macropad_os/macropad_os.py similarity index 94% rename from macropad_os/app_router.py rename to macropad_os/macropad_os.py index 84cb052..41c5aac 100644 --- a/macropad_os/app_router.py +++ b/macropad_os/macropad_os.py @@ -4,14 +4,14 @@ from .app_state import AppState from macropad_os.system_apps import OptionsApp, DebugApp -class AppRouter(object): +class MacropadOS(object): def __init__(self, macropad, config, apps): print("app router") self.macropad = macropad self.app_index = 0 - self.apps = apps + self.apps = [a(macropad, config) for a in apps] self.options = OptionsApp(macropad, config) - self.current_app = apps[self.app_index] + self.current_app = self.apps[self.app_index] self.config = config self.encoder_state = False self.options_time = 500000000 # .5 seconds in nanoseconds @@ -39,6 +39,7 @@ class AppRouter(object): self.current_app.resume() def start(self) -> None: + print(self.current_app) self.current_app.start() self.current_app.resume()