diff --git a/ROADMAP.md b/ROADMAP.md index a181d8c..c4a4046 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,12 +1,13 @@ # Roadmap -Three applications live here: a sound module, Ostinato the sequencer, and -Vamp, which plays Ostinato's songs on a board. The first is a sound module: a box that plays whatever a DAW, -sequencer or keyboard sends it over MIDI, the way a hardware tone module does. -It grows one part at a time, on the desktop interpreters first. +What's planned for the apps and libraries here. An app or library with a +longer list keeps its own roadmap beside its code, linked below. ## Sound module +The sound module (`lib/soundmodule`) plays whatever a DAW, sequencer or +keyboard sends it over MIDI, the way a hardware tone module does. + - Patch and macro names that DAWs can read, from the catalog files audioinstruments publishes with each release. - A SysEx request that returns the module's instruments, patches, effects and @@ -14,13 +15,12 @@ It grows one part at a time, on the desktop interpreters first. - On an ESP32-P4 as a USB MIDI device, with 24 voices at 48 kHz stereo. - Over BLE MIDI. - Reverb and chorus as true sends per channel, once the sampler can mix its - voices into a send bus. Today CC91 and CC93 set one master level, the mean - of the channels in use. + voices into a send bus. Today CC91 and CC93 set one master level. ## Vamp -- A MIDI keyboard such as the DMK-25 on the board's USB host port, playing - and recording into the selected track. +- Recording from a MIDI keyboard such as the DMK-25 on the board's USB host + port into the selected track. It already plays from one. - Undo in the window that knows about edits made on other panels. - The timed voice pool that schedules notes ahead of the audio moving into audioinstruments, once a second player needs it. @@ -29,6 +29,11 @@ It grows one part at a time, on the desktop interpreters first. - A published copy of the app on the web, so it installs without running a local server. +- The rest is in [Ostinato's roadmap](apps/ostinato/ROADMAP.md). + +## Synth Station + +- [Synth Station's roadmap](apps/synthstation/ROADMAP.md). ## Stompbox @@ -42,7 +47,8 @@ It grows one part at a time, on the desktop interpreters first. ## Libraries -- sayso's own list is in [lib/sayso/ROADMAP.md](lib/sayso/ROADMAP.md). - Ship songmodel's front panel page to boards. The wheel carries `page.html`, but a `mip` install or a frozen build has only the Python, so today Vamp copies the page across itself. +- [appkit](lib/appkit/ROADMAP.md), [controlkit](lib/controlkit/ROADMAP.md) + and [sayso](lib/sayso/ROADMAP.md) keep their own roadmaps. diff --git a/lib/appkit/ROADMAP.md b/lib/appkit/ROADMAP.md index 04f2da3..1a3589e 100644 --- a/lib/appkit/ROADMAP.md +++ b/lib/appkit/ROADMAP.md @@ -1,9 +1,6 @@ # Roadmap -- **Publishing.** appkit in the mip index with the other packages here, and - later a pip package. -- **A model for a front panel.** An app can expose a model (describe, apply, - telemetry, command) and the launcher exposes one too (the app list, which - app is up, switch), so hmilink can serve them to a phone, a browser or a - second screen. Apps without a model pay nothing. Model-first becomes the - recommended way to write an app in these docs, not a requirement. +- **A pip package.** appkit is already in the mip index. +- **A model for a front panel.** An app and the launcher expose a model + (describe, apply, telemetry, command), so hmilink can serve them to a phone, + a browser or a second screen. Apps without a model pay nothing. diff --git a/lib/sayso/README.md b/lib/sayso/README.md index b136b4d..1911c90 100644 --- a/lib/sayso/README.md +++ b/lib/sayso/README.md @@ -362,5 +362,5 @@ Some playback controls require Spotify Premium and an active device. for the current user and `playlist.items` for playlist entries. See [`PORTABILITY.md`](PORTABILITY.md) for details. -See [`ROADMAP.md`](ROADMAP.md) for implemented areas, next steps, and open design questions. +See [`ROADMAP.md`](ROADMAP.md) for what's planned. See `PORTABILITY.md` for CPython, MicroPython, and CircuitPython boundary notes. diff --git a/lib/sayso/ROADMAP.md b/lib/sayso/ROADMAP.md index 8b8d8b2..2353047 100644 --- a/lib/sayso/ROADMAP.md +++ b/lib/sayso/ROADMAP.md @@ -1,65 +1,17 @@ -# sayso Roadmap - -This project currently has a lightweight Spotify Web API object layer, auth helpers, -transport helpers, read methods, selected write methods, examples, and live tests. - -## Implemented - -- Spec-driven Spotify object classes from `SPOTIFY_OBJECT_SPECS` -- Nested object wrapping for object, object list, typed object, and page fields -- Lazy hydration from simplified objects to full objects (`_get` / `_peek`) -- `Page.__getitem__`, `CursorPaging`, and page-backed `object_by_key` properties -- `Artist.albums` and `Playlist.items` wired to client page methods -- Discovery scripts (`sayso_*_discovery.py`) for object-graph walkthroughs -- Offline object-layer unit tests in [`tests/sayso/test_objects.py`](../../tests/sayso/test_objects.py) -- February 2026 Dev Mode API notes in [`PORTABILITY.md`](PORTABILITY.md) -- `SpotifyObject.__str__()` pretty-prints raw object data for `print()` -- Client Credentials auth -- Authorization Code auth helpers consolidated in `sayso.auth` -- PKCE verifier/challenge helpers -- `TokenCache` for access/refresh token persistence -- `sayso.local.json` config file for app credentials -- `examples/write_examples.json` for optional write-example settings -- `SpotifyClient()` config-file bootstrap from `sayso.local.json` -- Automatic browser OAuth on first `SpotifyClient()` call when needed -- OAuth error translation into `SpotifyAuthError` -- CPython interactive OAuth flow in `sayso.auth` -- Manual callback URL parsing and lower-level OAuth examples -- Automatic HTTP backend selection (`requests` or CircuitPython `adafruit_requests`) -- JSON and raw-body write transports; non-JSON 2xx responses treated as success -- Read methods for major Spotify object families, paging, search, playback, library, and user endpoints -- Write methods for saved-library items, follows, playlists, and playback controls -- `SnapshotResult` for playlist mutation responses -- Draft schema-to-object-spec generator script -- Endpoint coverage report that parses `lib/sayso/client.py` and compares it to OpenAPI (`--map` prints path-to-method names) -- First-class client methods for all OpenAPI paths currently reported by Spotify's schema -- Example scripts for client credentials, OAuth, user-library usage, playback controls, and guarded write calls -- Live integration tests against the Spotify Web API (playlists, saved paging, artist albums, recently played) -- 401 retry after token refresh in `SpotifyClient` request helpers -- Offline client retry tests in [`tests/sayso/test_client.py`](../../tests/sayso/test_client.py) -- Lazy `Playlist.items` via `LazyPageRef` (metadata without fetch; load on access) -- `HydrationError` for contextual object-layer fetch failures -- MicroPython on Linux validated with discovery scripts and the Spotify app -- MicroPython on an ESP32-P4 board validated with the Spotify app -- The Spotify LVGL MicroPython app, now in the [apps repo](https://github.com/PyDevices/apps/tree/main/apps/spotify) -- The Spotify app follows a local earful speaker through its state events (`Device.events()`): while the board is Spotify's active device the screen shows each pause, skip and seek as earful reports it, and the Web API is only asked when playback moves elsewhere -- `transport.get_bytes()` for binary downloads (for example cover art) -- Socket-based OAuth callback fallback for MicroPython -- Offline transport tests in [`tests/sayso/test_transport.py`](../../tests/sayso/test_transport.py) - -## Good Next Steps - -- Validate CircuitPython on embedded hardware; record the result in `PORTABILITY.md`. -- Keep the schema generator aligned with hand-curated object_by_key overrides and February 2026 endpoint removals. -- Optionally deprecate removed Dev Mode client methods (`user()`, legacy `playlist_tracks()`) in docstrings and endpoint coverage output. - -## Resolved Decisions - -- **Global client** — keep `set_client()` / `SpotifyClient(auto_set=True)`; objects do not carry a per-instance client. -- **Token storage** — keep `TokenCache` and default `tokens.json` paths as they are. -- **Examples** — keep `examples/` as source-only in the repo for now (no packaging or docs migration yet). - -## Open Design Questions - -- Are there additional non-playlist mutation response shapes worth modeling? -- Should write methods validate Spotify limits such as max IDs per request, or leave that to API errors? +# sayso roadmap + +What's working today is in the [README](README.md) and +[PORTABILITY.md](PORTABILITY.md). + +- **CircuitPython on a board.** sayso runs on a CircuitPython board as it + does on MicroPython, with the result recorded in `PORTABILITY.md`. +- **Removed endpoints marked.** Client methods Spotify no longer serves to + Dev Mode apps, such as `user()` and the old `playlist_tracks()`, say so in + their docstrings and in the endpoint coverage report. +- **Generated specs that match the hand-curated ones.** The schema generator + keeps the `object_by_key` overrides and Spotify's endpoint removals. +- **More mutation results.** Write methods return a result object, as + playlist changes return `SnapshotResult`, wherever Spotify's response is + worth having. +- **Spotify's limits checked before a request,** such as the most IDs one + request takes, so a write fails with a clear error instead of the API's.