diff --git a/README.md b/README.md index ab2b4df..0db241a 100644 --- a/README.md +++ b/README.md @@ -1,54 +1,77 @@ -# Example +# OSTT -Example is a minimal reference plugin that demonstrates the common Noctalia -plugin entry types: a bar widget, a headless service, and a control-center -shortcut. +Voice-to-text for the Noctalia bar, powered by +[OSTT](https://github.com/kristoferlund/ostt). + +Click the microphone (or bind a hotkey) to start recording — the capsule turns +into a red record indicator with an elapsed timer while the microphone is +live. Click again to stop: OSTT transcribes the audio and, by default, +**pastes the transcript straight into the focused app** (`ostt --paste`). +No popup terminal is spawned; the recorder runs headlessly and the bar capsule +is the only UI. + +The indicator also lights up for recordings started outside Noctalia (e.g. an +`ostt launch` hotkey), since the plugin watches OSTT's own runtime state. ## Plugin | Field | Value | | --- | --- | -| ID | `noctalia/example` | -| Entries | Bar widgets: `hello`, `declarative`; service: `ticker`; shortcut: `toggle` | +| ID | `prdlk/ostt` | +| Entries | Bar widget: `recorder`; service: `monitor` | +| Requires | [`ostt`](https://ostt.ai/guide/installation), `script` (util-linux) | + +For paste output on Wayland you also need `wtype` or `ydotool` (`xdotool` on +X11) — see the [OSTT docs](https://ostt.ai). Pick a transcription model once +with `ostt model` / `ostt auth`. ## Usage -Add the `hello` widget from the Add-widget picker. The widget displays a -configurable label and glyph, counts clicks, reads `data.txt`, and watches the -shared `tick` state published by the `ticker` service. +Add the **OSTT** widget from the Add-widget picker. -Add the `declarative` widget to see the same service tick rendered as a -`ui.*` tree via `barWidget.render()` — a glyph, the live counter in a filled -rounded badge (impossible with the imperative API), and an inline `ui.button` -whose click is handled separately from the widget-level `onClick`. Simple -widgets can keep using `setText`/`setGlyph`; `render()` is the declarative -alternative for composite content. +| Interaction | Action | +| --- | --- | +| Left click | Start recording / stop & transcribe | +| Right click | Cancel the in-flight session (no transcription) | -Add the `toggle` shortcut from Settings -> Control Center shortcuts. It toggles -shared plugin state and shows how shortcut entries can render an active state. +Widget states: mic glyph (idle) → red filled mic + `m:ss` timer (recording) → +spinner (transcribing). ## Settings | Setting | Type | Default | Description | | --- | --- | --- | --- | -| `label` | `string` | `Hello` | Text shown in the bar widget. | -| `glyph` | `glyph` | `puzzle` | Glyph shown before the label. | -| `show_glyph` | `bool` | `true` | Controls whether the glyph is visible. | +| `output_mode` | `select` | `paste` | Where the transcript goes: paste into the focused app, or copy to the clipboard. | +| `model` | `string` | *(empty)* | Optional `provider/model` override (e.g. `deepgram/nova-3`, `whisper/turbo`). Empty uses the model selected with `ostt model`. | +| `process_action` | `string` | *(empty)* | Optional post-processing action id from `ostt.toml` (`ostt -p `). | +| `show_elapsed` | `bool` | `true` | Show the elapsed timer while recording. | +| `notify_on_done` | `bool` | `true` | Notify when the transcript has been delivered. | +| `extra_args` | `string` | *(empty)* | Advanced: appended verbatim to `ostt record` (e.g. `--param language=sv`). | -## IPC +## Hotkeys (IPC) -The `hello` widget exposes two IPC events: +The widget exposes IPC events for compositor keybinds: ```sh -noctalia msg plugin noctalia/example:hello focused set "Hi there" -noctalia msg plugin noctalia/example:hello focused fetch "https://example.com" +noctalia msg plugin prdlk/ostt:recorder focused toggle # start / stop & transcribe +noctalia msg plugin prdlk/ostt:recorder focused start +noctalia msg plugin prdlk/ostt:recorder focused stop +noctalia msg plugin prdlk/ostt:recorder focused cancel ``` -`set` updates the widget label at runtime. `fetch` performs an asynchronous HTTP -request and reports the response status in a notification. +Example (niri): -You can open the example panel with the following IPC call: +```kdl +Mod+Space { spawn "noctalia" "msg" "plugin" "prdlk/ostt:recorder" "focused" "toggle"; } +``` -```sh -noctalia msg panel-toggle noctalia/example:panel -``` \ No newline at end of file +## How it works + +- OSTT's recorder is a TUI, so the widget runs it inside a throwaway pty via + `script(1)` — headless, no window. +- Stopping uses OSTT's external-trigger contract: `SIGUSR1` finishes the + recording and runs transcription (the same mechanism `ostt launch` uses). +- The `monitor` service polls `$XDG_RUNTIME_DIR/ostt/recording.pid` + (liveness-checked) and publishes `idle / starting / recording / transcribing` + to the widget, plus an exit-code file written by the pty wrapper so failed + transcriptions surface as error notifications.