reformatting the default_app structure and worked on options menu.
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
from .abstract_app import App
|
||||
from .app_state import AppState, InvalidStateUpdateError
|
||||
from .app_router import AppRouter
|
||||
from macropad_os.default_apps.debug_app import DebugApp
|
||||
@@ -0,0 +1,82 @@
|
||||
import displayio
|
||||
|
||||
from .app_state import AppState, InvalidStateUpdateError
|
||||
|
||||
|
||||
|
||||
DISPLAY = displayio.Group()
|
||||
|
||||
class App(object):
|
||||
|
||||
def __init__(self, macropad, config):
|
||||
print("app created")
|
||||
self.macropad = macropad
|
||||
self.config = config
|
||||
self.name = "app"
|
||||
self.state = AppState.STOPPED
|
||||
self.display_group = DISPLAY
|
||||
|
||||
def start(self):
|
||||
print("Start from base class ")
|
||||
if self.state is not AppState.STOPPED:
|
||||
raise InvalidStateUpdateError(f"Start called but the current app state is {self.state}")
|
||||
self.state = AppState.STARTING
|
||||
self._on_start()
|
||||
self.on_start()
|
||||
self.state = AppState.PAUSED
|
||||
|
||||
def _on_start(self):
|
||||
pass
|
||||
|
||||
def on_start(self):
|
||||
raise NotImplementedError("on_start not implemented")
|
||||
|
||||
def resume(self):
|
||||
if self.state is not AppState.PAUSED:
|
||||
raise InvalidStateUpdateError(f"Resume called but the current app state is {self.state}")
|
||||
self.state = AppState.RESUMING
|
||||
self._on_resume()
|
||||
self.on_resume()
|
||||
self.state = AppState.RUNNING
|
||||
|
||||
def _on_resume(self):
|
||||
pass
|
||||
|
||||
def on_resume(self):
|
||||
raise NotImplementedError("on_resume not implemented")
|
||||
|
||||
def pause(self):
|
||||
if self.state is not AppState.RUNNING:
|
||||
raise InvalidStateUpdateError(f"Pause called but the current app state is {self.state}")
|
||||
self.state = AppState.PAUSING
|
||||
self._on_pause()
|
||||
self.on_pause()
|
||||
self.state = AppState.PAUSED
|
||||
|
||||
def _on_pause(self):
|
||||
self.macropad.keyboard.release_all()
|
||||
self.macropad.consumer_control.release()
|
||||
self.macropad.mouse.release_all()
|
||||
self.macropad.stop_tone()
|
||||
self.macropad.pixels.show()
|
||||
# self.macropad.display.refresh()
|
||||
|
||||
def on_pause(self):
|
||||
raise NotImplementedError("on_pause not implemented")
|
||||
|
||||
def loop(self):
|
||||
raise NotImplementedError("Not implemented")
|
||||
|
||||
def stop(self):
|
||||
if self.state is not AppState.PAUSED:
|
||||
raise InvalidStateUpdateError(f"Stop called but the current app state is {self.state}")
|
||||
self.state = AppState.STOPPING
|
||||
self._on_stop()
|
||||
self.on_stop()
|
||||
self.state = AppState.STOPPED
|
||||
|
||||
def _on_stop(self):
|
||||
pass
|
||||
|
||||
def on_stop(self):
|
||||
raise NotImplementedError("on_stop not implemented.")
|
||||
@@ -0,0 +1,67 @@
|
||||
import time
|
||||
|
||||
from .app_state import AppState
|
||||
from app.options.options_app import OptionsApp
|
||||
|
||||
|
||||
class AppRouter(object):
|
||||
def __init__(self, macropad, config, apps):
|
||||
print("app router")
|
||||
self.macropad = macropad
|
||||
self.app_index = 0
|
||||
self.apps = apps
|
||||
self.options = OptionsApp(macropad, config)
|
||||
self.current_app = apps[self.app_index]
|
||||
self.config = config
|
||||
self.encoder_state = False
|
||||
self.options_time = 500000000 # .5 seconds in nanoseconds
|
||||
self.click_time = 0
|
||||
|
||||
def swap_to_app(self, app):
|
||||
"""
|
||||
TODO: Calculate the size of the stack and the max size of hte stack and then fully close apps if need be.
|
||||
:param app:
|
||||
:return:
|
||||
"""
|
||||
print("Pausing current app")
|
||||
self.current_app.pause()
|
||||
print("Selecting new app")
|
||||
self.current_app = app
|
||||
if self.current_app.state is AppState.STOPPED:
|
||||
print("Starting new app")
|
||||
self.current_app.start()
|
||||
if self.current_app.state is AppState.PAUSED:
|
||||
print("Starting new app")
|
||||
self.current_app.resume()
|
||||
print(time.monotonic_ns())
|
||||
|
||||
def start(self):
|
||||
self.current_app.start()
|
||||
self.current_app.resume()
|
||||
|
||||
while True:
|
||||
# detect if the current app is what should be running
|
||||
# stop current app and start new one if not
|
||||
self.current_app.loop()
|
||||
# any other finite state machine logic that comes up
|
||||
if self.macropad.encoder_switch_debounced.pressed and not self.encoder_state:
|
||||
self.macropad.play_tone(1000, .1)
|
||||
self.encoder_state = True
|
||||
self.click_time = time.monotonic_ns()
|
||||
|
||||
elif self.macropad.encoder_switch_debounced.released and self.encoder_state:
|
||||
self.encoder_state = False
|
||||
if self.current_app is self.options:
|
||||
print("Moving from options to the last opened app.")
|
||||
else:
|
||||
self.app_index += 1
|
||||
print("Moving to the next app on the list. ")
|
||||
self.swap_to_app(self.apps[self.app_index % len(self.apps)])
|
||||
print("released encoder")
|
||||
if self.encoder_state and self.click_time:
|
||||
self.release_time = time.monotonic_ns()
|
||||
if (time.monotonic_ns() - self.click_time) > self.options_time:
|
||||
self.macropad.play_tone(1000, .1)
|
||||
self.swap_to_app(self.options)
|
||||
self.encoder_state = False
|
||||
self.macropad.encoder_switch_debounced.update()
|
||||
@@ -0,0 +1,12 @@
|
||||
class InvalidStateUpdateError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class AppState(object):
|
||||
STARTING = "starting"
|
||||
RESUMING = "resuming"
|
||||
RUNNING = "running"
|
||||
PAUSING = "pausing"
|
||||
PAUSED = "paused"
|
||||
STOPPING = "stopping"
|
||||
STOPPED = "stopped"
|
||||
@@ -0,0 +1 @@
|
||||
from light_patterns import *
|
||||
@@ -0,0 +1,20 @@
|
||||
arrows_with_enter = [
|
||||
(0, 0, 0), (0, 0, 0), (0, 0, 0),
|
||||
(0, 0, 0), (0, 0, 100), (0, 0, 0),
|
||||
(0, 0, 100), (100, 0, 0), (0, 0, 100),
|
||||
(0, 0, 0), (0, 0, 100), (0, 0, 0)
|
||||
]
|
||||
|
||||
up_down_enter = [
|
||||
(0, 0, 0), (0, 0, 0), (0, 0, 0),
|
||||
(0, 0, 0), (0, 0, 100), (0, 0, 0),
|
||||
(0, 0, 0), (100, 0, 0), (0, 0, 0),
|
||||
(0, 0, 0), (0, 0, 100), (0, 0, 0)
|
||||
]
|
||||
|
||||
arrows_yes_no = [
|
||||
(0, 0, 0), (0, 0, 0), (0, 0, 0),
|
||||
(0, 0, 0), (0, 0, 100), (0, 0, 0),
|
||||
(0, 0, 0), (100, 0, 0), (0, 0, 0),
|
||||
(0, 100, 0), (0, 0, 100), (100, 0, 0)
|
||||
]
|
||||
@@ -0,0 +1,91 @@
|
||||
import terminalio
|
||||
from adafruit_display_text import bitmap_label as label
|
||||
from adafruit_displayio_layout.layouts.grid_layout import GridLayout
|
||||
from rainbowio import colorwheel
|
||||
|
||||
from macropad_os.abstract_app import App
|
||||
|
||||
|
||||
def rgb_from_int(rgb):
|
||||
blue = rgb & 255
|
||||
green = (rgb >> 8) & 255
|
||||
red = (rgb >> 16) & 255
|
||||
return red, green, blue
|
||||
|
||||
|
||||
class DebugApp(App):
|
||||
|
||||
def __init__(self, macropad, config, name):
|
||||
super().__init__(macropad, config)
|
||||
self.name = name
|
||||
self.tones = [196, 220, 246, 262, 294, 330, 349, 392, 440, 494, 523, 587]
|
||||
self.wheel_offset = 0
|
||||
self.send_keyboard_inputs = 0
|
||||
self.lit_keys = [False] * 12
|
||||
self.labels = []
|
||||
self.layout = GridLayout(x=0, y=9, width=128, height=54, grid_size=(4, 4), cell_padding=1)
|
||||
self.title = label.Label(
|
||||
y=4,
|
||||
font=terminalio.FONT,
|
||||
color=0x0,
|
||||
text=f" {self.name} MENU ",
|
||||
background_color=0xFFFFFF,
|
||||
)
|
||||
|
||||
def on_start(self):
|
||||
print("on start from the app!")
|
||||
self.lit_keys = [False] * 12
|
||||
self.macropad.display.show(self.display_group)
|
||||
for _ in range(12):
|
||||
self.labels.append(label.Label(terminalio.FONT, text=""))
|
||||
|
||||
for index in range(12):
|
||||
x = index % 3
|
||||
y = index // 3
|
||||
self.layout.add_content(self.labels[index], grid_position=(x, y), cell_size=(1, 1))
|
||||
|
||||
|
||||
def on_resume(self):
|
||||
print("resume from the debug app!")
|
||||
|
||||
print(id(self.display_group))
|
||||
print(self.display_group)
|
||||
self.display_group.append(self.title)
|
||||
self.display_group.append(self.layout)
|
||||
self.macropad.display.show(self.display_group)
|
||||
|
||||
def on_pause(self):
|
||||
print("Pausing")
|
||||
self.display_group.remove(self.title)
|
||||
self.display_group.remove(self.layout)
|
||||
|
||||
|
||||
def on_stop(self):
|
||||
print("Stopping")
|
||||
|
||||
def loop(self):
|
||||
self.process_key_presses()
|
||||
self.light_keys()
|
||||
self.light_keys()
|
||||
|
||||
def process_key_presses(self):
|
||||
key_event = self.macropad.keys.events.get()
|
||||
if key_event:
|
||||
if key_event.pressed:
|
||||
self.labels[key_event.key_number].text = "KEY{}".format(key_event.key_number)
|
||||
print(self.macropad.keys)
|
||||
self.lit_keys[key_event.key_number] = not self.lit_keys[key_event.key_number]
|
||||
self.macropad.stop_tone()
|
||||
self.macropad.start_tone(self.tones[key_event.key_number])
|
||||
else:
|
||||
self.labels[key_event.key_number].text = ""
|
||||
self.macropad.stop_tone()
|
||||
|
||||
def light_keys(self):
|
||||
self.wheel_offset += 1
|
||||
for pixel in range(12):
|
||||
if self.lit_keys[pixel]:
|
||||
(r, g, b) = rgb_from_int(colorwheel((pixel / 12 * 256) + self.wheel_offset))
|
||||
self.macropad.pixels[pixel] = (r * .1, g * .1, b * .1)
|
||||
else:
|
||||
self.macropad.pixels[pixel] = 0
|
||||
@@ -0,0 +1,67 @@
|
||||
import terminalio
|
||||
from adafruit_display_text import label
|
||||
from adafruit_displayio_layout.layouts.grid_layout import GridLayout
|
||||
|
||||
from common.light_patterns import arrows_yes_no
|
||||
from ..abstract_app import App
|
||||
|
||||
|
||||
class OptionsApp(App):
|
||||
|
||||
def __init__(self, macropad, config):
|
||||
super().__init__(macropad, config)
|
||||
self.send_keyboard_inputs = 0
|
||||
self.labels = []
|
||||
self.layout = GridLayout(x=0, y=9, width=128, height=54, grid_size=(4, 4), cell_padding=1)
|
||||
self.key_colors = arrows_yes_no
|
||||
self.title = label.Label(
|
||||
y=4,
|
||||
font=terminalio.FONT,
|
||||
color=0x0,
|
||||
text=f" OPTIONS MENU ",
|
||||
background_color=0xFFFFFF,
|
||||
)
|
||||
|
||||
def on_start(self):
|
||||
print("on start from the app!")
|
||||
self.lit_keys = [False] * 4
|
||||
for _ in range(4):
|
||||
self.labels.append(label.Label(terminalio.FONT, text=""))
|
||||
|
||||
for index in range(4):
|
||||
x = 0
|
||||
y = index
|
||||
self.layout.add_content(self.labels[index], grid_position=(x, y), cell_size=(3, 1))
|
||||
|
||||
def on_resume(self):
|
||||
print("resume from the options app!")
|
||||
self.display_group.append(self.title)
|
||||
self.display_group.append(self.layout)
|
||||
self.macropad.display.show(self.display_group)
|
||||
|
||||
def on_pause(self):
|
||||
print("Pausing")
|
||||
self.display_group.remove(self.title)
|
||||
self.display_group.remove(self.layout)
|
||||
|
||||
def on_stop(self):
|
||||
print("Stopping")
|
||||
|
||||
def loop(self):
|
||||
self.process_key_presses()
|
||||
self.light_keys()
|
||||
|
||||
def process_key_presses(self):
|
||||
key_event = self.macropad.keys.events.get()
|
||||
if key_event:
|
||||
if key_event.key_number < 12:
|
||||
if key_event.pressed:
|
||||
self.macropad.stop_tone()
|
||||
self.macropad.start_tone(200)
|
||||
else:
|
||||
self.macropad.stop_tone()
|
||||
|
||||
def light_keys(self):
|
||||
for pixel in range(12):
|
||||
print(pixel)
|
||||
self.macropad.pixels[pixel] = self.key_colors[pixel]
|
||||
Reference in New Issue
Block a user