launcher page keys, new projects in build, launcher config, launcher favorites, cleanup
This commit is contained in:
parent
160edc8d61
commit
7efd046d44
2 changed files with 95 additions and 67 deletions
5
build.py
5
build.py
|
|
@ -7,6 +7,9 @@ from pathlib import Path
|
||||||
import requests
|
import requests
|
||||||
from circup.commands import main as circup_cli
|
from circup.commands import main as circup_cli
|
||||||
|
|
||||||
|
# TODO: maybe change these to use the first URLs i.e. https://learn.adafruit.com/elements/3198279/download?type=zip
|
||||||
|
# instead of the redirect URLs that are direct to the CDN. That will make easier for users to add apps here.
|
||||||
|
# The code will need to follow the redirect and get the filename from the next URL.
|
||||||
LEARN_PROJECT_URLS = [
|
LEARN_PROJECT_URLS = [
|
||||||
"https://cdn-learn.adafruit.com/downloads/zip/3194974/Metro/Metro_RP2350_Snake.zip?timestamp={}",
|
"https://cdn-learn.adafruit.com/downloads/zip/3194974/Metro/Metro_RP2350_Snake.zip?timestamp={}",
|
||||||
"https://cdn-learn.adafruit.com/downloads/zip/3195762/Metro/Metro_RP2350_Memory/memory_game.zip?timestamp={}",
|
"https://cdn-learn.adafruit.com/downloads/zip/3195762/Metro/Metro_RP2350_Memory/memory_game.zip?timestamp={}",
|
||||||
|
|
@ -15,6 +18,8 @@ LEARN_PROJECT_URLS = [
|
||||||
"https://cdn-learn.adafruit.com/downloads/zip/3196927/Metro/Metro_RP2350_Match3/match3_game.zip?timestamp={}",
|
"https://cdn-learn.adafruit.com/downloads/zip/3196927/Metro/Metro_RP2350_Match3/match3_game.zip?timestamp={}",
|
||||||
"https://cdn-learn.adafruit.com/downloads/zip/3194422/Metro/Metro_RP2350_Breakout.zip?timestamp={}",
|
"https://cdn-learn.adafruit.com/downloads/zip/3194422/Metro/Metro_RP2350_Breakout.zip?timestamp={}",
|
||||||
"https://cdn-learn.adafruit.com/downloads/zip/3196755/Metro/Metro_RP2350_Chips_Challenge.zip?timestamp={}",
|
"https://cdn-learn.adafruit.com/downloads/zip/3196755/Metro/Metro_RP2350_Chips_Challenge.zip?timestamp={}",
|
||||||
|
"https://cdn-learn.adafruit.com/downloads/zip/3198116/Metro/Metro_RP2350_Minesweeper.zip?timestamp={}",
|
||||||
|
"https://cdn-learn.adafruit.com/downloads/zip/3198279/Fruit_Jam/Larsio_Paint_Music.zip?timestamp=1750522464"
|
||||||
]
|
]
|
||||||
|
|
||||||
def create_font_specific_zip(font_path: Path, src_dir: Path, learn_projects_dir: Path, output_dir: Path):
|
def create_font_specific_zip(font_path: Path, src_dir: Path, learn_projects_dir: Path, output_dir: Path):
|
||||||
|
|
|
||||||
157
src/code.py
157
src/code.py
|
|
@ -88,72 +88,52 @@ mouse_tg.x = display.width // (2 * scale)
|
||||||
mouse_tg.y = display.height // (2 * scale)
|
mouse_tg.y = display.height // (2 * scale)
|
||||||
# 046d:c52f
|
# 046d:c52f
|
||||||
|
|
||||||
|
launcher_config = {}
|
||||||
|
if pathlib.Path("launcher.conf.json").exists():
|
||||||
|
with open("launcher.conf.json", "r") as f:
|
||||||
|
launcher_config = json.load(f)
|
||||||
|
|
||||||
# mouse = usb.core.find(idVendor=0x046d, idProduct=0xc52f)
|
# mouse = usb.core.find(idVendor=0x046d, idProduct=0xc52f)
|
||||||
|
|
||||||
DIR_IN = 0x80
|
DIR_IN = 0x80
|
||||||
mouse_interface_index, mouse_endpoint_address = None, None
|
mouse_interface_index, mouse_endpoint_address = None, None
|
||||||
mouse = None
|
mouse = None
|
||||||
# scan for connected USB device and loop over any found
|
|
||||||
print("scanning usb")
|
|
||||||
for device in usb.core.find(find_all=True):
|
|
||||||
# print device info
|
|
||||||
print(f"{device.idVendor:04x}:{device.idProduct:04x}")
|
|
||||||
print(device.manufacturer, device.product)
|
|
||||||
print()
|
|
||||||
config_descriptor = adafruit_usb_host_descriptors.get_configuration_descriptor(
|
|
||||||
device, 0
|
|
||||||
)
|
|
||||||
print(config_descriptor)
|
|
||||||
#
|
|
||||||
# i = 0
|
|
||||||
# while i < len(config_descriptor):
|
|
||||||
# descriptor_len = config_descriptor[i]
|
|
||||||
# descriptor_type = config_descriptor[i + 1]
|
|
||||||
# if descriptor_type == adafruit_usb_host_descriptors.DESC_CONFIGURATION:
|
|
||||||
# config_value = config_descriptor[i + 5]
|
|
||||||
# print(f" value {config_value:d}")
|
|
||||||
# elif descriptor_type == adafruit_usb_host_descriptors.DESC_INTERFACE:
|
|
||||||
# interface_number = config_descriptor[i + 2]
|
|
||||||
# interface_class = config_descriptor[i + 5]
|
|
||||||
# interface_subclass = config_descriptor[i + 6]
|
|
||||||
# interface_protocol = config_descriptor[i + 7]
|
|
||||||
# print(f" interface[{interface_number:d}]")
|
|
||||||
# print(
|
|
||||||
# f" class {interface_class:02x} subclass {interface_subclass:02x}"
|
|
||||||
# )
|
|
||||||
# print(f"protocol: {interface_protocol}")
|
|
||||||
# elif descriptor_type == adafruit_usb_host_descriptors.DESC_ENDPOINT:
|
|
||||||
# endpoint_address = config_descriptor[i + 2]
|
|
||||||
# if endpoint_address & DIR_IN:
|
|
||||||
# print(f" IN {endpoint_address:02x}")
|
|
||||||
# else:
|
|
||||||
# print(f" OUT {endpoint_address:02x}")
|
|
||||||
# i += descriptor_len
|
|
||||||
# print()
|
|
||||||
#
|
|
||||||
# # assume the device is the mouse
|
|
||||||
# mouse = device
|
|
||||||
_possible_interface_index, _possible_endpoint_address = adafruit_usb_host_descriptors.find_boot_mouse_endpoint(device)
|
|
||||||
if _possible_interface_index is not None and _possible_endpoint_address is not None:
|
|
||||||
mouse = device
|
|
||||||
mouse_interface_index = _possible_interface_index
|
|
||||||
mouse_endpoint_address = _possible_endpoint_address
|
|
||||||
print(f"mouse interface: {mouse_interface_index} endpoint_address: {hex(mouse_endpoint_address)}")
|
|
||||||
|
|
||||||
mouse_was_attached = None
|
if "use_mouse" in launcher_config and launcher_config["use_mouse"]:
|
||||||
if mouse is not None:
|
|
||||||
# detach the kernel driver if needed
|
|
||||||
if mouse.is_kernel_driver_active(0):
|
|
||||||
mouse_was_attached = True
|
|
||||||
mouse.detach_kernel_driver(0)
|
|
||||||
else:
|
|
||||||
mouse_was_attached = False
|
|
||||||
|
|
||||||
# set configuration on the mouse so we can use it
|
# scan for connected USB device and loop over any found
|
||||||
mouse.set_configuration()
|
print("scanning usb")
|
||||||
|
for device in usb.core.find(find_all=True):
|
||||||
|
# print device info
|
||||||
|
print(f"{device.idVendor:04x}:{device.idProduct:04x}")
|
||||||
|
print(device.manufacturer, device.product)
|
||||||
|
print()
|
||||||
|
config_descriptor = adafruit_usb_host_descriptors.get_configuration_descriptor(
|
||||||
|
device, 0
|
||||||
|
)
|
||||||
|
print(config_descriptor)
|
||||||
|
|
||||||
|
_possible_interface_index, _possible_endpoint_address = adafruit_usb_host_descriptors.find_boot_mouse_endpoint(device)
|
||||||
|
if _possible_interface_index is not None and _possible_endpoint_address is not None:
|
||||||
|
mouse = device
|
||||||
|
mouse_interface_index = _possible_interface_index
|
||||||
|
mouse_endpoint_address = _possible_endpoint_address
|
||||||
|
print(f"mouse interface: {mouse_interface_index} endpoint_address: {hex(mouse_endpoint_address)}")
|
||||||
|
|
||||||
|
mouse_was_attached = None
|
||||||
|
if mouse is not None:
|
||||||
|
# detach the kernel driver if needed
|
||||||
|
if mouse.is_kernel_driver_active(0):
|
||||||
|
mouse_was_attached = True
|
||||||
|
mouse.detach_kernel_driver(0)
|
||||||
|
else:
|
||||||
|
mouse_was_attached = False
|
||||||
|
|
||||||
|
# set configuration on the mouse so we can use it
|
||||||
|
mouse.set_configuration()
|
||||||
|
|
||||||
|
mouse_buf = array.array("b", [0] * 8)
|
||||||
|
|
||||||
mouse_buf = array.array("b", [0] * 8)
|
|
||||||
WIDTH = 280
|
WIDTH = 280
|
||||||
HEIGHT = 182
|
HEIGHT = 182
|
||||||
|
|
||||||
|
|
@ -248,11 +228,23 @@ for path in app_path.iterdir():
|
||||||
apps.append({
|
apps.append({
|
||||||
"title": title,
|
"title": title,
|
||||||
"icon": str(icon_file.absolute()) if icon_file is not None else None,
|
"icon": str(icon_file.absolute()) if icon_file is not None else None,
|
||||||
"file": str(code_file.absolute())
|
"file": str(code_file.absolute()),
|
||||||
|
"dir": path
|
||||||
})
|
})
|
||||||
|
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
|
print("launcher config", launcher_config)
|
||||||
|
if "favorites" in launcher_config:
|
||||||
|
|
||||||
|
for favorite_app in reversed(launcher_config["favorites"]):
|
||||||
|
print("checking favorite", favorite_app)
|
||||||
|
for app in apps:
|
||||||
|
print(f"checking app: {app["dir"]}")
|
||||||
|
if app["dir"] == f"/apps/{favorite_app}":
|
||||||
|
apps.remove(app)
|
||||||
|
apps.insert(0, app)
|
||||||
|
|
||||||
|
|
||||||
def reuse_cell(grid_coords):
|
def reuse_cell(grid_coords):
|
||||||
try:
|
try:
|
||||||
|
|
@ -317,6 +309,9 @@ def _unhide_cell_group(cell_group):
|
||||||
|
|
||||||
|
|
||||||
def display_page(page_index):
|
def display_page(page_index):
|
||||||
|
max_pages = math.ceil(len(apps) / 6)
|
||||||
|
page_txt.text = f"{page_index + 1}/{max_pages}"
|
||||||
|
|
||||||
for grid_index in range(6):
|
for grid_index in range(6):
|
||||||
grid_pos = (grid_index % config["width"], grid_index // config["width"])
|
grid_pos = (grid_index % config["width"], grid_index // config["width"])
|
||||||
try:
|
try:
|
||||||
|
|
@ -342,6 +337,11 @@ def display_page(page_index):
|
||||||
print(f"{grid_index} | {grid_index % config["width"], grid_index // config["width"]}")
|
print(f"{grid_index} | {grid_index % config["width"], grid_index // config["width"]}")
|
||||||
|
|
||||||
|
|
||||||
|
page_txt = Label(terminalio.FONT, text="", scale=2)
|
||||||
|
page_txt.anchor_point = (1.0, 1.0)
|
||||||
|
page_txt.anchored_position = (display.width - 2, display.height - 2)
|
||||||
|
main_group.append(page_txt)
|
||||||
|
|
||||||
cur_page = 0
|
cur_page = 0
|
||||||
display_page(cur_page)
|
display_page(cur_page)
|
||||||
|
|
||||||
|
|
@ -370,7 +370,7 @@ if mouse:
|
||||||
scaled_group.append(mouse_tg)
|
scaled_group.append(mouse_tg)
|
||||||
|
|
||||||
|
|
||||||
help_txt = Label(terminalio.FONT, text="[Arrow]: Move\n[E]: Edit\n[Enter]: Run")
|
help_txt = Label(terminalio.FONT, text="[Arrow]: Move\n[E]: Edit\n[Enter]: Run\n[1-9]: Page")
|
||||||
# help_txt = TextBox(terminalio.FONT, width=88, height=30, align=TextBox.ALIGN_RIGHT, background_color=0x008800, text="[E]: Edit\n[Enter]: Run")
|
# help_txt = TextBox(terminalio.FONT, width=88, height=30, align=TextBox.ALIGN_RIGHT, background_color=0x008800, text="[E]: Edit\n[Enter]: Run")
|
||||||
help_txt.anchor_point = (0, 0)
|
help_txt.anchor_point = (0, 0)
|
||||||
|
|
||||||
|
|
@ -417,6 +417,18 @@ def change_selected(new_selected):
|
||||||
|
|
||||||
change_selected((0, 0))
|
change_selected((0, 0))
|
||||||
|
|
||||||
|
def page_right():
|
||||||
|
global cur_page
|
||||||
|
if cur_page < math.ceil(len(apps) / 6) - 1:
|
||||||
|
cur_page += 1
|
||||||
|
display_page(cur_page)
|
||||||
|
|
||||||
|
def page_left():
|
||||||
|
global cur_page
|
||||||
|
if cur_page > 0:
|
||||||
|
cur_page -= 1
|
||||||
|
display_page(cur_page)
|
||||||
|
|
||||||
|
|
||||||
def handle_key_press(key):
|
def handle_key_press(key):
|
||||||
global index, editor_index, cur_page
|
global index, editor_index, cur_page
|
||||||
|
|
@ -476,15 +488,9 @@ def handle_key_press(key):
|
||||||
index = None
|
index = None
|
||||||
print("go!")
|
print("go!")
|
||||||
elif selected is left_tg:
|
elif selected is left_tg:
|
||||||
if cur_page > 0:
|
page_left()
|
||||||
cur_page -= 1
|
|
||||||
display_page(cur_page)
|
|
||||||
|
|
||||||
elif selected is right_tg:
|
elif selected is right_tg:
|
||||||
if cur_page < math.ceil(len(apps) / 6) - 1:
|
page_right()
|
||||||
cur_page += 1
|
|
||||||
display_page(cur_page)
|
|
||||||
|
|
||||||
elif key == "e":
|
elif key == "e":
|
||||||
if isinstance(selected, tuple):
|
if isinstance(selected, tuple):
|
||||||
editor_index = (selected[1] * 3 + selected[0]) + (cur_page * 6)
|
editor_index = (selected[1] * 3 + selected[0]) + (cur_page * 6)
|
||||||
|
|
@ -492,6 +498,17 @@ def handle_key_press(key):
|
||||||
editor_index = None
|
editor_index = None
|
||||||
|
|
||||||
print("go!")
|
print("go!")
|
||||||
|
elif key in "123456789":
|
||||||
|
if key != "9":
|
||||||
|
requested_page = int(key)
|
||||||
|
max_page = math.ceil(len(apps) / 6)
|
||||||
|
if requested_page <= max_page:
|
||||||
|
cur_page = requested_page - 1
|
||||||
|
display_page(requested_page-1)
|
||||||
|
else: # key == 9
|
||||||
|
max_page = math.ceil(len(apps) / 6)
|
||||||
|
cur_page = max_page - 1
|
||||||
|
display_page(max_page - 1)
|
||||||
else:
|
else:
|
||||||
print(f"unhandled key: {repr(key)}")
|
print(f"unhandled key: {repr(key)}")
|
||||||
|
|
||||||
|
|
@ -534,6 +551,12 @@ while True:
|
||||||
if clicked_cell is not None:
|
if clicked_cell is not None:
|
||||||
index = clicked_cell[1] * config["width"] + clicked_cell[0]
|
index = clicked_cell[1] * config["width"] + clicked_cell[0]
|
||||||
|
|
||||||
|
if right_tg.contains((mouse_tg.x, mouse_tg.y, 0)):
|
||||||
|
page_right()
|
||||||
|
if left_tg.contains((mouse_tg.x, mouse_tg.y, 0)):
|
||||||
|
page_left()
|
||||||
|
|
||||||
|
|
||||||
if index is not None:
|
if index is not None:
|
||||||
print("index", index)
|
print("index", index)
|
||||||
print(f"selected: {apps[index]}")
|
print(f"selected: {apps[index]}")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue