Enable alpha blending on the controls texture so sprite icons float on any background without white cell artifacts. Regenerate skin template with transparent cells and magenta gutters. Change focus highlight from blue to red. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
60 lines
3.8 KiB
Markdown
60 lines
3.8 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project
|
|
|
|
SDLamp2 is a simple SDL2-based audio player written in C, designed for a child to use. It plays long m4a/mp3 files (fairy tale cassette rips) with a cassette-player-like UI: rewind, stop, play, fast-forward, next tape. Inspired by Winamp.
|
|
|
|
See `docs/sdlamp2-fsd.md` for the full functional specification and changelog.
|
|
See `docs/TOOLCHAIN.md` for the arm64 Docker build container.
|
|
See `docs/rg35xx-plus.md` for target device details, boot chain, and deployment.
|
|
|
|
## Build and Run
|
|
|
|
**Dependencies:** SDL2, SDL2_image, FFmpeg libraries (libavformat, libavcodec, libavutil, libswresample). Installed via system package manager (native) or via apt inside the arm64 Docker container.
|
|
|
|
```sh
|
|
make # native build — uses pkg-config
|
|
make clean # remove build artifacts
|
|
./build/sdlamp2 audio # run with the repo's audio directory
|
|
```
|
|
|
|
Building for the arm64 target device via the Docker container (from the `docker-arm64/` directory):
|
|
|
|
```sh
|
|
make build # one-shot: build sdlamp2 inside arm64 container
|
|
make shell # interactive shell inside the arm64 container
|
|
make clean # remove the Docker image
|
|
```
|
|
|
|
The controls spritesheet (`controls.png`) is embedded in the binary. If an external `controls.png` exists in the current working directory it takes precedence, allowing custom skins. Audio directory defaults to cwd if not specified.
|
|
|
|
No test suite, no linter.
|
|
|
|
## Architecture
|
|
|
|
Single-file C program: `src/sdlamp2.c` (~650 lines). One generated header: `src/controls_png.h` (embedded PNG byte array — regenerate with `python3 tools/embed_png.py assets/controls.png src/controls_png.h` if the spritesheet changes). Skin template: `python3 tools/gen_skin_template.py [output.png]` generates a labeled grid template for creating custom spritesheets (requires Pillow). Device-specific scripts live in `device/rg35xx/`.
|
|
|
|
Key sections in order:
|
|
- **Decoder struct** — holds all FFmpeg state (format/codec contexts, swr resampler, album art texture)
|
|
- **Position persistence** — `save_position()`/`load_position()` read/write a tab-separated `positions.txt` in the audio directory
|
|
- **File scanning** — `scan_audio_files()` finds supported files (.m4a, .mp3, .wav, .ogg) in a directory
|
|
- **Decoder lifecycle** — `decoder_open()` sets up FFmpeg + swr pipeline (planar float → interleaved stereo 48kHz), `decoder_pump()` feeds decoded audio into an SDL_AudioStream, `decoder_seek()` handles seeking
|
|
- **File switching** — `switch_file()` saves position, opens new file, restores saved position
|
|
- **Main loop** — event handling (mouse clicks on button rects), decoder pumping, SDL audio queue draining, EOF handling, rendering (album art, progress bar, control buttons from sprite sheet)
|
|
|
|
Audio pipeline: FFmpeg decoder → libswresample (format conversion) → SDL_AudioStream (FIFO) → SDL audio device queue (push model, no callback).
|
|
|
|
Uses SDL2 (not SDL3). Uses `#if LIBAVUTIL_VERSION_INT` preprocessor checks to support both old (channel_layout) and new (ch_layout) FFmpeg channel layout APIs.
|
|
|
|
## Conventions
|
|
|
|
- C formatted with Google style, `ColumnLimit: 100`
|
|
- Keep it simple — Casey Muratori's semantic compression; don't refactor too soon
|
|
- Minimize dependencies; discuss with owner before adding any
|
|
- Non-fatal errors go to stderr and continue; fatal errors (SDL init failures) abort via `panic_and_abort()`
|
|
- Update the changelog in `docs/sdlamp2-fsd.md` when making changes
|
|
- Never run privileged Docker containers or make system-wide changes without explicit approval; explain what's needed and let the owner do it manually
|
|
- Never install global Python packages; use a temporary venv in `/tmp` when Python dependencies are needed (e.g. `python3 -m venv /tmp/venv && source /tmp/venv/bin/activate && pip install ...`)
|