feat: Added automatic loading of Apps from the macropad_apps/python directory at load time.
Performance improvements to the lighting system. Renamed app_router to macropad_os.
This commit is contained in:
@@ -116,3 +116,4 @@ dmypy.json
|
|||||||
|
|
||||||
|
|
||||||
.idea*
|
.idea*
|
||||||
|
config.json
|
||||||
@@ -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 adafruit_macropad import MacroPad
|
||||||
|
|
||||||
from macropad_apps.python import NumpadApp
|
|
||||||
|
|
||||||
macropad = MacroPad()
|
macropad = MacroPad()
|
||||||
|
|
||||||
default_config = Config("default_config.json").load()
|
default_config = Config("default_config.json").load()
|
||||||
config = Config("config.json").load(default_config)
|
config = Config("config.json").load(default_config)
|
||||||
|
|
||||||
ar = AppRouter(macropad, config, [
|
PYTHON_APP_FOLDER = "./macropad_apps/python"
|
||||||
NumpadApp(macropad, config),
|
|
||||||
# Arrow Keys
|
|
||||||
# Script Runner
|
|
||||||
])
|
|
||||||
|
|
||||||
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))
|
# _thread.start_new_thread(sc.run, (sc))
|
||||||
|
|
||||||
ar.start()
|
ar.start()
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
from .numpad import NumpadApp
|
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
|
from time import monotonic_ns
|
||||||
|
|
||||||
import terminalio
|
import terminalio
|
||||||
from adafruit_display_text.bitmap_label import Label
|
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_displayio_layout.layouts.grid_layout import GridLayout
|
||||||
|
from adafruit_hid.keycode import Keycode
|
||||||
from rainbowio import colorwheel
|
from rainbowio import colorwheel
|
||||||
|
|
||||||
from macropad_os import App
|
from macropad_os import App
|
||||||
@@ -24,6 +26,8 @@ modified_labels = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
COLOR_UPDATE_RATE = 50000000 # .05 seconds
|
||||||
|
|
||||||
class NumpadApp(App):
|
class NumpadApp(App):
|
||||||
|
|
||||||
def __init__(self, macropad, config):
|
def __init__(self, macropad, config):
|
||||||
@@ -34,6 +38,7 @@ class NumpadApp(App):
|
|||||||
self.labels = []
|
self.labels = []
|
||||||
self.title = "Numpad"
|
self.title = "Numpad"
|
||||||
self.modifier_pressed = False
|
self.modifier_pressed = False
|
||||||
|
self.last_color_update = 0
|
||||||
|
|
||||||
def on_start(self):
|
def on_start(self):
|
||||||
print("on start from the app!")
|
print("on start from the app!")
|
||||||
@@ -65,6 +70,10 @@ class NumpadApp(App):
|
|||||||
def update_key_colors(self):
|
def update_key_colors(self):
|
||||||
self.wheel_offset += 1
|
self.wheel_offset += 1
|
||||||
colors = []
|
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):
|
for pixel in range(12):
|
||||||
if self.lit_keys[pixel]:
|
if self.lit_keys[pixel]:
|
||||||
(r, g, b) = rgb_from_int(colorwheel((pixel / 12 * 256) + self.wheel_offset))
|
(r, g, b) = rgb_from_int(colorwheel((pixel / 12 * 256) + self.wheel_offset))
|
||||||
@@ -74,12 +83,11 @@ class NumpadApp(App):
|
|||||||
self.set_colors(colors)
|
self.set_colors(colors)
|
||||||
|
|
||||||
def process_keys_pressed_callback(self, keyevent):
|
def process_keys_pressed_callback(self, keyevent):
|
||||||
print("PROCESS KEYS CALLBACK FROM DEBUG")
|
|
||||||
print(keyevent)
|
print(keyevent)
|
||||||
|
self.keyboard.send(Keycode.SHIFT,Keycode.SHIFT,Keycode.SHIFT, Keycode.A)
|
||||||
|
|
||||||
def process_keys_released_callback(self, keyevent):
|
def process_keys_released_callback(self, keyevent):
|
||||||
print("PROCESS KEYS RELEASED CALLBACK FROM DEBUG")
|
|
||||||
print(keyevent)
|
print(keyevent)
|
||||||
|
|
||||||
def process_enbcoder_changed(self, keyevent):
|
def process_enbcoder_changed(self, keyevent):
|
||||||
print("PROCESS Encoder Changed Callback FROM DEBUG")
|
|
||||||
print(keyevent)
|
print(keyevent)
|
||||||
@@ -2,4 +2,4 @@ from .serial_communications import SerialComms
|
|||||||
from .configuration import Config, ConfigItem
|
from .configuration import Config, ConfigItem
|
||||||
from .app_state import AppState, InvalidStateUpdateError
|
from .app_state import AppState, InvalidStateUpdateError
|
||||||
from .abstract_app import App
|
from .abstract_app import App
|
||||||
from .app_router import AppRouter
|
from .macropad_os import MacropadOS
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import time
|
from time import monotonic_ns
|
||||||
|
|
||||||
import displayio
|
import displayio
|
||||||
import terminalio
|
import terminalio
|
||||||
@@ -12,6 +12,9 @@ DISPLAY = displayio.Group()
|
|||||||
def convert_to_keynum(x, y):
|
def convert_to_keynum(x, y):
|
||||||
return 3 * 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):
|
class App(object):
|
||||||
|
|
||||||
@@ -42,10 +45,12 @@ class App(object):
|
|||||||
self._state = AppState.STOPPED
|
self._state = AppState.STOPPED
|
||||||
self._name = "app"
|
self._name = "app"
|
||||||
self._key_tones = {}
|
self._key_tones = {}
|
||||||
|
self._last_lighting_update = 0
|
||||||
|
|
||||||
self._current_brightness = config.brightness()
|
self._current_brightness = config.brightness()
|
||||||
|
|
||||||
self.macropad = macropad
|
self.macropad = macropad
|
||||||
|
self.keyboard = macropad.keyboard
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
@@ -86,7 +91,7 @@ class App(object):
|
|||||||
self._state = AppState.PAUSED
|
self._state = AppState.PAUSED
|
||||||
|
|
||||||
def _on_pause(self) -> None:
|
def _on_pause(self) -> None:
|
||||||
self.macropad.keyboard.release_all()
|
self.keyboard.release_all()
|
||||||
self.macropad.consumer_control.release()
|
self.macropad.consumer_control.release()
|
||||||
self.macropad.mouse.release_all()
|
self.macropad.mouse.release_all()
|
||||||
self.macropad.stop_tone()
|
self.macropad.stop_tone()
|
||||||
@@ -116,7 +121,6 @@ class App(object):
|
|||||||
if key_event.key_number < 12:
|
if key_event.key_number < 12:
|
||||||
if key_event.pressed:
|
if key_event.pressed:
|
||||||
self.macropad.stop_tone()
|
self.macropad.stop_tone()
|
||||||
print(self.config.get_items())
|
|
||||||
self._play_tone_for_key(key_event.key_number)
|
self._play_tone_for_key(key_event.key_number)
|
||||||
if self._key_pressed_callbacks:
|
if self._key_pressed_callbacks:
|
||||||
for callback in self._key_pressed_callbacks:
|
for callback in self._key_pressed_callbacks:
|
||||||
@@ -124,7 +128,7 @@ class App(object):
|
|||||||
else:
|
else:
|
||||||
self._stop_tone_for_key(key_event.key_number)
|
self._stop_tone_for_key(key_event.key_number)
|
||||||
if self._key_released_callbacks:
|
if self._key_released_callbacks:
|
||||||
for callback in self._key_pressed_callbacks:
|
for callback in self._key_released_callbacks:
|
||||||
callback(key_event.key_number)
|
callback(key_event.key_number)
|
||||||
|
|
||||||
def _play_tone_for_key(self, key_number):
|
def _play_tone_for_key(self, key_number):
|
||||||
@@ -169,13 +173,14 @@ class App(object):
|
|||||||
raise NotImplementedError("on_stop not implemented.")
|
raise NotImplementedError("on_stop not implemented.")
|
||||||
|
|
||||||
def _update_lighting(self) -> None:
|
def _update_lighting(self) -> None:
|
||||||
|
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()
|
new_brightness = self.config.brightness()
|
||||||
if self._current_brightness != new_brightness:
|
if self._current_brightness != new_brightness:
|
||||||
print("SETTING BRIGHTNESS!!!!")
|
# Setting the brightness here
|
||||||
print(self._key_lights)
|
|
||||||
self._key_lights = [tuple(rgb_val * new_brightness / self._current_brightness for rgb_val in color) for
|
self._key_lights = [tuple(rgb_val * new_brightness / self._current_brightness for rgb_val in color) for
|
||||||
color in self._key_lights]
|
color in self._key_lights]
|
||||||
print(self._key_lights)
|
|
||||||
self._current_brightness = self.config.brightness()
|
self._current_brightness = self.config.brightness()
|
||||||
for index, color in enumerate(self._key_lights):
|
for index, color in enumerate(self._key_lights):
|
||||||
self.macropad.pixels[index] = color
|
self.macropad.pixels[index] = color
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -4,14 +4,14 @@ from .app_state import AppState
|
|||||||
from macropad_os.system_apps import OptionsApp, DebugApp
|
from macropad_os.system_apps import OptionsApp, DebugApp
|
||||||
|
|
||||||
|
|
||||||
class AppRouter(object):
|
class MacropadOS(object):
|
||||||
def __init__(self, macropad, config, apps):
|
def __init__(self, macropad, config, apps):
|
||||||
print("app router")
|
print("app router")
|
||||||
self.macropad = macropad
|
self.macropad = macropad
|
||||||
self.app_index = 0
|
self.app_index = 0
|
||||||
self.apps = apps
|
self.apps = [a(macropad, config) for a in apps]
|
||||||
self.options = OptionsApp(macropad, config)
|
self.options = OptionsApp(macropad, config)
|
||||||
self.current_app = apps[self.app_index]
|
self.current_app = self.apps[self.app_index]
|
||||||
self.config = config
|
self.config = config
|
||||||
self.encoder_state = False
|
self.encoder_state = False
|
||||||
self.options_time = 500000000 # .5 seconds in nanoseconds
|
self.options_time = 500000000 # .5 seconds in nanoseconds
|
||||||
@@ -39,6 +39,7 @@ class AppRouter(object):
|
|||||||
self.current_app.resume()
|
self.current_app.resume()
|
||||||
|
|
||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
|
print(self.current_app)
|
||||||
self.current_app.start()
|
self.current_app.start()
|
||||||
self.current_app.resume()
|
self.current_app.resume()
|
||||||
|
|
||||||
Reference in New Issue
Block a user