143 lines
6.3 KiB
Markdown
143 lines
6.3 KiB
Markdown
# Unified Binary + Startup Dialog Plan
|
|
|
|
## Summary
|
|
|
|
Merge the CLI and GUI into a single `voice_linux` binary that always opens the GTK3 window. On launch, a **startup dialog** appears letting the user choose CPU vs GPU and select which whisper model to use. All available ggml models are downloaded to `./models/` so the user can test them.
|
|
|
|
## Current State
|
|
|
|
| Item | Status |
|
|
|------|--------|
|
|
| Two binaries: `voice_linux` (CLI) and `voice_linux_gui` (GTK3) | Active |
|
|
| GPU passthrough + NVIDIA driver + CUDA toolkit | Working |
|
|
| whisper.cpp built with `GGML_CUDA=ON` | Working |
|
|
| `--gpu` / `--cpu` flags parsed in both binaries | Working |
|
|
| Model path hardcoded in `config.ini` as `model_path=` | Working |
|
|
| `transcribe_init()` called once at startup before GTK loop | Working |
|
|
|
|
## Architecture Changes
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
A[./voice_linux launched] --> B[Load config.ini]
|
|
B --> C[audio_init]
|
|
C --> D{Show Startup Dialog}
|
|
D --> |User picks CPU/GPU + model| E[transcribe_init with selections]
|
|
E --> F[typer_init]
|
|
F --> G[Main GTK window + event loop]
|
|
G --> H[On window close: cleanup]
|
|
```
|
|
|
|
Key change: **`transcribe_init()` is deferred** until after the startup dialog returns the user's selections. Audio init happens first so the mic meter can work, but model loading waits for the dialog.
|
|
|
|
## Whisper Models to Download
|
|
|
|
All English-optimized ggml models from the whisper.cpp HuggingFace repo. The GTX 1080 Ti has 11 GB VRAM, so all models up to `large-v3` fit comfortably.
|
|
|
|
| Model | File | Size | VRAM est. |
|
|
|-------|------|------|-----------|
|
|
| tiny.en | `ggml-tiny.en.bin` | ~75 MB | ~200 MB |
|
|
| base.en | `ggml-base.en.bin` | ~142 MB | ~350 MB |
|
|
| small.en | `ggml-small.en.bin` | ~466 MB | ~1 GB |
|
|
| medium.en | `ggml-medium.en.bin` | ~1.5 GB | ~3 GB |
|
|
| large-v3-turbo | `ggml-large-v3-turbo.bin` | ~1.6 GB | ~3.5 GB |
|
|
| large-v3 | `ggml-large-v3.bin` | ~3.1 GB | ~6 GB |
|
|
|
|
Base URL: `https://huggingface.co/ggerganov/whisper.cpp/resolve/main/`
|
|
|
|
## Detailed Steps
|
|
|
|
### Step 1: Download all whisper models
|
|
|
|
Create a `scripts/download_models.sh` that downloads each model to `./models/` if not already present. Also callable from `build.sh`.
|
|
|
|
### Step 2: Add startup dialog to gui_main.c
|
|
|
|
Insert a modal `GtkDialog` that runs **before** `transcribe_init()`:
|
|
|
|
- **GPU toggle**: `GtkComboBoxText` with entries `CPU` and `GPU`. Default to `GPU` if CUDA device is detected at runtime, otherwise `CPU`.
|
|
- **Model picker**: `GtkComboBoxText` populated by scanning `./models/ggml-*.bin` files. Display friendly names derived from filenames. Pre-select the model from `config.ini`.
|
|
- **OK button**: closes dialog, returns selections to `main()`.
|
|
|
|
The dialog is a transient child of a hidden parent window so it appears centered on screen.
|
|
|
|
GPU detection at dialog time: check if `nvidia-smi` exits 0, or check if the whisper.cpp CUDA backend reports a device. Simplest approach: try `access /dev/nvidia0` — if it exists, default to GPU.
|
|
|
|
### Step 3: Defer transcribe_init
|
|
|
|
Current flow in `gui_main.c` [`main()`](src/gui_main.c:588):
|
|
|
|
```
|
|
config_load -> use_gpu from argv -> audio_init -> transcribe_init -> typer_init -> gtk loop
|
|
```
|
|
|
|
New flow:
|
|
|
|
```
|
|
config_load -> audio_init -> show_startup_dialog -> transcribe_init(dialog selections) -> typer_init -> gtk loop
|
|
```
|
|
|
|
The startup dialog returns:
|
|
- `int use_gpu` — 0 or 1
|
|
- `char model_path[512]` — full path to selected model file
|
|
|
|
These override whatever was in config.ini / argv.
|
|
|
|
### Step 4: Remove CLI binary from default build
|
|
|
|
- Keep `src/main.c` in the repo for reference or future headless use, but do not build it by default.
|
|
- In [`build.sh`](build.sh): remove the separate CLI gcc invocation. The GUI gcc line outputs `./voice_linux` instead of `./voice_linux_gui`.
|
|
- In [`Makefile`](Makefile): change `TARGET` to build from `gui_main.c` sources. Remove `voice_linux_gui` target. Optionally add a `cli` target for headless builds.
|
|
- The `BUILD_GUI` env var is no longer needed; remove it.
|
|
|
|
### Step 5: Add use_gpu to config.ini and config.c
|
|
|
|
Add a `use_gpu=1` line to [`config.ini`](config.ini). Parse it in [`config_load_file()`](src/config.c:43). This becomes the default for the startup dialog, overridable by the dialog selection. The `--gpu` / `--cpu` CLI flags still work as overrides.
|
|
|
|
Add `int use_gpu;` to [`voice_config_t`](src/config.h:6).
|
|
|
|
### Step 6: Update README.md
|
|
|
|
Simplify run instructions to just `./voice_linux`. Remove `voice_linux_gui` references. Document the startup dialog behavior.
|
|
|
|
### Step 7: Build and test
|
|
|
|
```bash
|
|
bash ./build.sh
|
|
./voice_linux
|
|
```
|
|
|
|
Verify:
|
|
- Startup dialog appears with CPU/GPU toggle and model list
|
|
- Selecting GPU + medium.en loads correctly with CUDA backend
|
|
- Main window works as before after dialog closes
|
|
|
|
## Files Modified
|
|
|
|
| File | Change |
|
|
|------|--------|
|
|
| `src/gui_main.c` | Add startup dialog function; defer `transcribe_init`; update `main()` flow |
|
|
| `src/config.h` | Add `use_gpu` field to `voice_config_t` |
|
|
| `src/config.c` | Parse `use_gpu` from config file |
|
|
| `config.ini` | Add `use_gpu=1` |
|
|
| `build.sh` | Single binary output `./voice_linux`; remove `BUILD_GUI` toggle; remove CLI build |
|
|
| `Makefile` | Single target `./voice_linux` from gui sources |
|
|
| `README.md` | Update run instructions |
|
|
| `scripts/download_models.sh` | New script to download all models |
|
|
|
|
## Files NOT Modified
|
|
|
|
| File | Reason |
|
|
|------|--------|
|
|
| `src/main.c` | Kept for optional headless builds; not built by default |
|
|
| `src/transcribe.c` | API unchanged — `transcribe_init` / `transcribe_cleanup` already support the needed flow |
|
|
| `src/transcribe.h` | No changes needed |
|
|
| `src/audio.c` / `src/audio.h` | No changes needed |
|
|
| `src/hotkey.c` / `src/hotkey.h` | Only used by CLI; not linked into GUI binary |
|
|
|
|
## Risk Notes
|
|
|
|
- The startup dialog adds a brief pause before the main window. Model loading (especially large-v3 at 3 GB) takes several seconds — a progress indicator or status label in the main window info area will show loading state.
|
|
- If no models are found in `./models/`, the dialog should show an error message and offer to run the download script.
|
|
- The `transcribe_init` call blocks the GTK main thread during model load. For large models this could be 5-10 seconds. An improvement would be async loading with a progress bar, but for v1 a simple "Loading model..." label update before the blocking call is sufficient.
|