Files
looper/evaluation.md

7.4 KiB
Raw Blame History

Client Code Evaluation

Summary Table

Category Rating Remarks
Mocked / Left Undone ⚠️ Incomplete Most features are stubs. Only four FIFO commands are sent: record <col>, scene_next, stop, and ? toggles help. Visual mode, yank/paste, fuzzy search, zoom, MIDI grid, rack view, transport controls, and all other keybindings are placeholders. The TUI does not display engine state all cells show a static number with a single color.
Potential Segfaults Low Risk No unsafe pointer dereferences. All array indices are bounded by modulo. send_command opens with O_NONBLOCK and returns -1 on failure callers (except test_client.c) ignore it, but no crash occurs. yank_buffer.clip_indices is never allocated; free(NULL) is safe. No null pointer accesses in ncurses calls.
Memory Safety Good Only stackallocated data. The sole dynamic allocation (yank_buffer.clip_indices) is never allocated, so the free in tui_cleanup is harmless. No leaks, no useafterfree.
Thread Safety / Race None The entire TUI runs on the main thread. No concurrency, no shared state. send_command is called synchronously. No race conditions.
Performance Acceptable Main loop blocks on getch(). Each command opens, writes, and closes a FIFO system call overhead, but acceptable at human interaction rate (~dozen commands/s). No CPUintensive work. draw_grid redraws the entire screen; with 8×8 grid it is negligible.
Architectural Soundness Reasonable Clean separation: TUI communicates only via FIFO, no engine linkage. send_command is testable (unit test passes). The architecture supports future extension (add new keybindings → call send_command). However, the current implementation sends commands without any feedback or validation; the user receives no visual confirmation that the engine acted.

Detailed Remarks

1. Mocked / Left Undone

  • Clip state display: All cells use COLOR_EMPTY (white) regardless of actual engine state. state_to_color() returns a fixed value.
  • Visual mode: Declared (MODE_VISUAL, MODE_MOVE) but never triggered. marks array is initialized but never written or read.
  • Yank buffer: yank_buffer.clip_indices is never allocated; yank_buffer.count is always 0. Paste (p) not implemented.
  • Fuzzy search: FuzzySearch struct exists with all fields, but never used. No file listing or Carla integration.
  • Rack view: Not implemented; key \t is not handled.
  • Many engine commands missing: bind, unbind, add_channel, remove_channel, add_midi, scene_prev, toggle_play, record_stop, MIDI note events, etc., are not mapped.
  • Transport controls: No play/pause toggle engine has no corresponding FIFO command yet.
  • Help text: Only a single line; many described keys are not actually handled.
  • Mouse: Not handled.
  • Colors: Only COLOR_EMPTY and COLOR_SELECTED are used dynamically; colours for looping, recording, stopped states are initialized but never applied.

The code is a minimal stub exactly as defined in PLAN.md. This is acceptable for the first phase, but the client is far from usable as a real looper UI.

2. Potential Segfaults

  • send_command returns -1 on failure; callers in the main loop (cases t, s, d) ignore the return value. No crash.
  • draw_cell uses fixed coordinates; no offscreen access. Grid is 8×8, coordinates are bounded by modulo.
  • send_command accesses getenv("LOOPER_CMD_FIFO") returns NULL if unset; code then uses hardcoded /tmp/looper_cmd. Safe.
  • Open with O_NONBLOCK avoids blocking hang.
  • write() return value is checked for short writes only when appending newline.
  • No pointer arithmetic or unsafe casts.

3. Memory Safety

  • The only dynamic allocation is yank_buffer.clip_indices it is never assigned a value, remains NULL. tui_cleanup calls free(NULL) welldefined.
  • All other data is static or stackallocated.
  • No realloc or custom allocators.
  • No memory leaks.

4. Thread Safety / Race Conditions

  • Singlethreaded. No threads are spawned.
  • send_command is synchronous and blocking; no concurrent access to the file.
  • No atomics, locks, or shared mutable state.

5. Performance

  • Main loop blocks on getch() CPU idle.
  • Each FIFO command incurs one open(), write(), close() system call. With a real FIFO, open() with O_NONBLOCK returns immediately or fails. This is acceptable at UI speeds.
  • draw_grid does a clear() and refreshes the entire screen; for 64 cells it is fast enough (submillisecond).
  • No audio processing or heavy computation.

6. Architectural Soundness

  • Separation: The client has zero dependency on engine source code; it communicates only via FIFO.
  • Testability: send_command is exposed and can be tested independently (existing unit test works).
  • Extensibility: Adding a new command is trivial add a case and call send_command with a formatted string. The plan already defines the mapping.
  • Weakness: No feedback path from the engine; the user has no visual confirmation that their action took effect. A future readback FIFO or shared memory would be required for a production UI.
  • Placeholder code: Many structures and functions (FuzzySearch, marks, visual mode) are dead code they increase compilation time but do not affect runtime. They can be removed when the corresponding features are implemented properly.

Overall Verdict

The client code is minimal, safe, and architecturally sound for its intended firstphase purpose.

  • It compiles without errors and passes its unit test.
  • No segfaults, memory leaks, or race conditions exist.
  • Performance is acceptable for interactive use.
  • The architecture cleanly separates UI from engine and supports incremental feature addition.

Missing features are deliberate stubs as per PLAN.md. The client is a functional skeleton that can be extended once the engine exposes more FIFO commands and a feedback channel.