From a0f95c7252b7e287abf361711743db873ffc767f Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Fri, 13 Feb 2026 14:38:17 +0100 Subject: [PATCH] Combine Play/Stop into toggle, add Previous Cassette button Merge the separate Stop and Play buttons into one slot that toggles between play/stop and shows the corresponding icon. Use the freed slot for a Previous Cassette button, mirroring Next Cassette. Layout: [Volume] [Prev] [Rewind] [Play/Stop] [FF] [Next] Co-Authored-By: Claude Opus 4.6 --- docs/sdlamp2-fsd.md | 6 ++++++ src/sdlamp2.c | 43 ++++++++++++++++++++++++------------------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/docs/sdlamp2-fsd.md b/docs/sdlamp2-fsd.md index 1c47657..096d0ec 100644 --- a/docs/sdlamp2-fsd.md +++ b/docs/sdlamp2-fsd.md @@ -43,6 +43,12 @@ This document specifies the functional requirements for an SDL2 based media play ## 6. Changelog +### 2026-02-13 — Combine Play/Stop, add Previous Cassette button + +- **Play/Stop combined**: The separate Stop and Play buttons are merged into a single toggle button that shows the play icon (▶) when paused and the stop icon (■) when playing. +- **Previous Cassette**: A new "Previous Cassette" button is added at the left of the transport controls, mirroring "Next Cassette". Wraps from the first tape to the last. +- **New layout**: `[Volume] [Prev] [Rewind] [Play/Stop] [FF] [Next]` — same 6 focusable elements, same positions. + ### 2026-02-13 — Start paused, fix next-tape autoplay, quiet joystick log - **Start paused**: The player no longer autoplays on startup; it opens the last file at the saved position but waits for the user to press Play. diff --git a/src/sdlamp2.c b/src/sdlamp2.c index 6838406..edb831c 100644 --- a/src/sdlamp2.c +++ b/src/sdlamp2.c @@ -57,15 +57,15 @@ static int current_file_index = 0; /* --- Focus / navigation --- */ #define FOCUS_VOLUME 0 -#define FOCUS_REWIND 1 -#define FOCUS_STOP 2 -#define FOCUS_PLAY 3 +#define FOCUS_PREV 1 +#define FOCUS_REWIND 2 +#define FOCUS_PLAYSTOP 3 #define FOCUS_FF 4 #define FOCUS_NEXT 5 #define FOCUS_COUNT 6 static float volume = 0.5f; -static int focus_index = FOCUS_PLAY; +static int focus_index = FOCUS_PLAYSTOP; static SDL_GameController* controller = NULL; static SDL_Joystick* joystick = NULL; static int debug_mode = 0; @@ -494,13 +494,22 @@ static void switch_file(int index) { static void activate_focused_button(void) { switch (focus_index) { + case FOCUS_PREV: + if (num_audio_files > 0) { + int prev = (current_file_index - 1 + num_audio_files) % num_audio_files; + switch_file(prev); + } + break; case FOCUS_REWIND: { double pos = get_current_seconds() - SEEK_SECONDS; decoder_seek(pos < 0.0 ? 0.0 : pos); break; } - case FOCUS_STOP: - if (!paused) { + case FOCUS_PLAYSTOP: + if (paused && num_audio_files > 0) { + paused = SDL_FALSE; + SDL_PauseAudioDevice(audio_device, 0); + } else if (!paused) { paused = SDL_TRUE; SDL_PauseAudioDevice(audio_device, 1); if (current_file[0]) { @@ -508,12 +517,6 @@ static void activate_focused_button(void) { } } break; - case FOCUS_PLAY: - if (paused && num_audio_files > 0) { - paused = SDL_FALSE; - SDL_PauseAudioDevice(audio_device, 0); - } - break; case FOCUS_FF: { double pos = get_current_seconds() + SEEK_SECONDS; double dur = get_duration_seconds(); @@ -553,21 +556,22 @@ int main(int argc, char** argv) { const SDL_Rect volume_bg = {25, 390, 30, 80}; /* Button positions (bottom of window, centered) */ - const SDL_Rect rewind_btn = {80, 390, 80, 80}; - const SDL_Rect stop_btn = {180, 390, 80, 80}; - const SDL_Rect play_btn = {280, 390, 80, 80}; + const SDL_Rect prev_btn = {80, 390, 80, 80}; + const SDL_Rect rewind_btn = {180, 390, 80, 80}; + const SDL_Rect playstop_btn = {280, 390, 80, 80}; const SDL_Rect ff_btn = {380, 390, 80, 80}; const SDL_Rect next_btn = {480, 390, 80, 80}; /* Array of focusable rects indexed by FOCUS_* constants */ - const SDL_Rect* focus_rects[FOCUS_COUNT] = {&volume_bg, &rewind_btn, &stop_btn, - &play_btn, &ff_btn, &next_btn}; + const SDL_Rect* focus_rects[FOCUS_COUNT] = {&volume_bg, &prev_btn, &rewind_btn, + &playstop_btn, &ff_btn, &next_btn}; /* Sprite sheet source rects */ const SDL_Rect rewind_sprite = {0, 0, 200, 200}; const SDL_Rect play_sprite = {220, 0, 200, 200}; const SDL_Rect ff_sprite = {440, 0, 200, 200}; const SDL_Rect stop_sprite = {0, 220, 200, 200}; + const SDL_Rect prev_sprite = {440, 220, 200, 200}; /* same circle as next */ const SDL_Rect next_sprite = {440, 220, 200, 200}; /* Progress bar area */ @@ -901,9 +905,10 @@ int main(int argc, char** argv) { } /* Buttons */ + SDL_RenderCopy(renderer, controls_texture, &prev_sprite, &prev_btn); SDL_RenderCopy(renderer, controls_texture, &rewind_sprite, &rewind_btn); - SDL_RenderCopy(renderer, controls_texture, &stop_sprite, &stop_btn); - SDL_RenderCopy(renderer, controls_texture, &play_sprite, &play_btn); + SDL_RenderCopy(renderer, controls_texture, paused ? &play_sprite : &stop_sprite, + &playstop_btn); SDL_RenderCopy(renderer, controls_texture, &ff_sprite, &ff_btn); SDL_RenderCopy(renderer, controls_texture, &next_sprite, &next_btn);