| Age | Commit message (Collapse) | Author |
|
The checkbox used data-value (binds the element's 'value' string attribute)
instead of data-checked (binds the 'checked' bool state) -- per RmlUi docs,
checkboxes must use data-checked with a bool. So it neither reflected nor
toggled study_mode, and with no explicit styling it rendered invisibly.
Fix: wrap the input in a <form> (canonical RmlUi form-control flow), switch
data-value -> data-checked, and give #cb-study an explicit visible style
(border + background, green fill when :checked). Verified the document loads
with no RmlUi parse errors.
Note: RmlUi's border shorthand is 'width color' (no 'solid' keyword).
|
|
Root cause: the Input/Update/ApplySeek/Study systems iterated
'with: [playback_state]' AND wrote playback_state back via ecs_set. In
this flecs build, an ecs_set on the component a system is currently
iterating is deferred and then DISCARDED -- so current_time never
committed and the elapsed_str binding always read 0.0 (audio played fine
because play/resume are imperative, but the clock and seek/keyboard
state never persisted).
Fix: each of those systems now iterates 'with: [audio_file]' -- a
component the player always has but these systems do NOT mutate -- so
their ecs_set on playback_state/study_state is immediate and persists.
Verified: current_time now persists across world.progress (0.5, 1.0,
1.499, ...), the elapsed_str getter is re-evaluated every frame, and the
app runs clean (no crash, audio loads + streams + shuts down cleanly).
Note: LoadSystem still iterates audio_file and mutates it (af[:duration]),
so the total-time display stays 0:00 for now -- left for a follow-up to
avoid iterating a tag, which crashed the flecs binding.
|
|
Same with: [] (zero-term) trap as the drag-and-drop fix, but it silently
killed four runtime systems -- so audio loaded but never played and the
clock stayed at 0:00:
- Update (ON_UPDATE): never called Rl.update_music_stream, so miniaudio
never pumped its buffers -> no sound, get_music_time_played stayed 0.
- Input (PRE_UPDATE): keyboard controls (space, seek keys, M) dead.
- ApplySeek(PRE_UPDATE): seeking dead.
- Study (ON_UPDATE): study-mode auto-pause FSM dead.
A zero-term system never iterates its block in this flecs build. Gave each
a real term (with: [playback_state]) so they match the player entity and
run every frame. The play/smart-play buttons already called audio.resume
via RmlUi -- they just had no stream pumping behind them.
Verified end-to-end (synthetic Xdnd drop + ARGV load): file loads ->
plays -> current_time advances 0..duration -> end-of-track auto-pause.
|
|
Root cause: the file-drop check was a flecs system registered with
with: [] (zero terms). In this flecs build a zero-term system never
iterates its block, so Rl.file_dropped? was never polled and dropped
files were silently ignored -- the SDL backend was receiving the Xdnd
events fine all along.
Moved the IsFileDropped()/LoadDroppedFiles() check into the main loop
(before world.progress, so the LoadSystem picks up the file the same
frame), matching the original C study-player. Verified end-to-end with a
synthetic Xdnd drop: file detected -> loaded as a music stream.
|
|
With no script arg, main.c defaults to game/main.rb — the raylib-jamstack
HUD demo — which has no file-drop handler. Pass the study-player script
explicitly so the CheckFileDrop system (drag-and-drop) is actually loaded.
|
|
The GLFW Wayland drag-and-drop crash fix (previous commit) did NOT resolve
drag-and-drop on the real target (labwc), so abandon the GLFW path entirely
instead of patching it further.
Why SDL: raylib ships a first-class SDL backend (PLATFORM_DESKTOP_SDL) that
implements file drop via SDL_DROPFILE. GLFW 3.4 (vendored in raylib 6.0) has
broken Wayland drag-and-drop (wl_data_offer NULL source_actions/action
listeners -> libwayland wl_abort on drag, glfw/glfw#2835) AND its X11 backend
segfaults on WSLg (Mesa GLX). SDL's window/EGL/drag-drop is mature on BOTH
real Wayland (labwc) and WSLg, so one backend covers both targets with no
vendor patches and no X11/Wayland special-casing.
Changes (desktop only; web build stays Emscripten+GLFW, untouched):
- build.zig: build raylib PLATFORM=PLATFORM_DESKTOP_SDL (SDL_INCLUDE_PATH/
LIBRARY_PATH = system SDL2); link SDL2 instead of wayland-*/xkbcommon/EGL.
- Revert the GLFW patch (patches/glfw-wayland-dnd-crash.patch removed; the
build.zig patch-application step removed).
- Docs: environment.md / study-player.md / BUILDING.md / SCREENSHOT.md updated
to reflect the SDL backend + the SDL2 system dependency.
The RmlUi binding is backend-agnostic (rlgl render + raylib IsKeyDown input,
zero glfw* calls), so the swap is transparent to it.
Prerequisite on the cyberdeck: install SDL2 dev (sudo pacman -S sdl2 or
sdl2-compat) before building.
Verified on the laptop (WSLg): build green; binary runs under SDL
(Platform backend: DESKTOP (SDL)), window opens, no GLX segfault, RmlUi fonts
load, mp3 loads from argv (132300 frames), no crash. Interactive drag-drop
itself still needs user testing on the cyberdeck (SDL_DROPFILE path).
|
|
Cross-ref from study-player.md drag-drop section to environment.md so the
next agent touching drag-drop finds the real root cause (GLFW/Wayland, not
the Ruby CheckFileDrop code).
|
|
listener)
The rewrite builds raylib Wayland-only (X11/GLX segfaults on WSLg), but
raylib 6.0 vendors GLFW 3.4 (release) which crashes the moment a file is
dragged over the window on Wayland (glfw/glfw#2835, #2562):
struct wl_data_offer_listener dataOfferListener = { dataOfferHandleOffer };
// source_actions (opcode 1) + action (opcode 2) handlers are NULL
wl_data_offer is v3; modern compositors (labwc/GNOME/KDE) emit
source_actions/action during a drag -> libwayland-client wl_abort()s on
the NULL listener -> app dies on drag-enter, before any drop registers.
This is why drag-and-drop is 'unreliable' in the rewrite but reliable in
the original 'dev' app, which uses the X11/Xdnd backend (-D_GLFW_X11) — a
separate code path with none of these bugs.
Fix: backport the upstream GLFW-master fix as a committed patch applied
idempotently in build.zig before (marker = dataOfferHandleAction;
forces a lib rebuild when newly applied). Adds no-op source_actions/action
handlers so the events are safely consumed (GLFW only needs the
mime-types to accept a drop), plus guards two NULL derefs in the same
data-device path (dataDeviceHandleEnter / dataDeviceHandleDrop).
This keeps the Wayland-only build (no WSLg GLX regression) and fixes the
crash on both WSLg and a real Wayland desktop (cyberdeck/labwc). Drop the
patch once raylib vendors a GLFW release containing the upstream fix.
Verified: build green; desktop binary launches, loads an mp3 from argv
(132300 frames), enters the loop with no segfault. Interactive drag-drop
itself still needs user testing (it's a user action; the WSLg
non-interactive shell stalls the Wayland window before render).
|
|
Aligns apply_font_scale to the body element's id across study_player.rb /
layout.rb / main.rml (was probing element('body')||element('__body__')).
Verified: build green, run clean, player view renders correctly.
(these edits were left uncommitted by the Phase 6 agent's timed-out turn;
orchestrator verified + committed.)
|
|
Phase 6's settings panel toggles on F2, but Rl::resolve_key's SYMBOL_KEYS map
only had letters/digits/a few named keys — :f2 raised ArgumentError and crashed
the loop at frame 1. Added f1..f12 (raylib keycodes 290-301) to the map.
The KEY_F* constants aren't all exposed to mruby, so the int values are used.
(orchestrator fix — unblocked the final end-to-end verification.)
|
|
- Config: INI-style study-player.cfg (forward-compatible with the original C
config.c format). Persists window size, study_mode_default, volume,
last_audio_path, font_scale.
- Layout: UILayout keys mapped to RmlUi element properties (RCSS-tunable).
Adapted the C drag-to-reposition editor to RmlUi-appropriate settings (P4:
RmlUi uses declarative RCSS, so pixel-drag doesn't map cleanly; persist what's
meaningful). load on startup, save on change.
- study_player.rb wiring + main.rml/rcss settings panel.
(orchestrator-committed: agent completed + built green, but its turn timed out
before committing — it was running gen_ai_reference.rb at the timeout.)
|
|
|
|
|
|
- mrbgems/study_audio: native C scanner (scan_silence) avoids Ruby array overflow
for large audio files; returns normalized silence region pairs directly
- Core.detect_silence: pure Ruby algorithm (threshold 0.015, min 0.75s)
for testing with synthetic data; pad_silence_regions (0.25s padding)
- Core portion navigation: find_silence_at, current_speaking_portion,
total_speaking_portions, portion_seek_target (2 frames into padding zone),
in_padding_zone?, speaking_portion_start
- Input: V/B keys for prev/next portion navigation
- Draw: section counter (N/total) displayed below play state
- build_config.rb: added study_audio gem to both desktop and web builds
- Runtime: silence_regions, raw_silence_regions, analysis_done fields
- Load system: triggers C scan_silence after audio load, pads with pure Ruby
- Knowledge doc updated with Phase 3 scar tissue (array limits, gem naming,
Wayland screenshot gap)
Verification: build clean, pure Core smoke test passes (CRuby), game runs
with country.mp3 without overflow, load system processes the file.
|
|
(no require, int32_t, keyword_init, ARGV, non-blocking seek)
|
|
(orchestrator-committed: Phase 2 agent (deepseek-v4-pro) completed the work
and verified via build+run+screenshot, but its turn timed out before committing.)
|
|
|
|
|
|
The help text and study-mode checkbox were inside ui_render_player, so they
only appeared when an audio file was loaded. In the original single-file
main.c they rendered unconditionally (outside the 'if loaded' block).
Extracted ui_render_overlay() — renders help text + checkbox — and call it
from main.c after either ui_render_player or ui_render_empty, matching the
original behavior.
Also added a screenshot mode (env STUDY_PLAYER_SCREENSHOT) for automated
visual testing: renders to an offscreen RenderTexture, fixes FBO alpha
artifacts (ClearBackground doesn't fill alpha on some Mesa drivers), and
exports a PNG. Verified all UI elements render correctly.
|
|
Decompose the 778-line src/main.c into 7 focused modules with separate
headers for code isolation and parallel agent development:
types.h shared types: PlayerState, SilenceRegion, UILayout, constants
player.{h,c} audio playback: load, play, pause, seek, update, format_time
study.{h,c} study mode: silence detection, portion navigation, auto-pause
ui.{h,c} rendering + input: fonts, colors, drawing, keyboard/mouse
config.{h,c} UI layout persistence (moved UILayout to types.h)
layout_editor.{h,c} layout editor tab (unchanged)
main.c thin composition root (main loop, tabs, platform glue)
Module boundaries follow the dispatch-project style:
- .h files are contracts (self-contained, #pragma once, forward-declare)
- .c files are private (static helpers, no cross-module .c includes)
- All shared state passed by pointer (PlayerState*/UIState*)
- font_data.h (xxd-generated array definition) included in exactly one .c
Updated documentation (AGENTS.md, ORCHESTRATOR.md, GLOSSARY.md, README.md,
tasks.md) and bin/ scripts (dispatch-style conventions, added bin/build-web).
Build: make clean && make -j$(nproc) exits 0 with zero warnings.
|
|
|
|
- UILayout gains titleX, statusX, helpX, smartPlayX, secNavX
- All elements freely draggable in both X and Y in Layout editor
- draw_text_centered() now takes centerX parameter
- section nav positions relative to secNavX
|
|
- UILayout gains smartPlayY and secNavY fields
- Smart play HOLD button now uses layout.smartPlayY
- Section nav prev/next buttons use layout.secNavY
- Both are draggable in Layout editor tab
- config_load/config_save handle new fields
|
|
- GuiTabBar from raygui v5.0 for Player/Layout tab switching
- Layout tab: 5 draggable element placeholders (Title, Bar, Status,
Play button, Help) — press+hold+drag to reposition
- Auto-save config file on tab switch from Layout back to Player
- config_save() added to config module
- raygui include path added to Makefile, warnings suppressed via
#pragma for third-party header
|
|
- src/config.h: UILayout struct + config_load() declaration
- src/config.c: key=value parser with defaults fallback
- src/main.c: replace hardcoded layout constants with config-driven UILayout
- Config file loaded from next to binary (study-player.cfg)
- Missing config file falls back to hardcoded defaults
|
|
- Default target (make) now builds for Linux native (gcc)
- Windows cross-compile preserved as x86_64-w64-mingw32-gcc -std=c99 -O2 -Ibuild -Ideps/raylib/src -Ideps/raylib/src/external/glfw/include -Wall -Wextra -DPLATFORM_DESKTOP -D_GLFW_WIN32 -o build/study-player.exe build/main.o build/libraylib.a -lgdi32 -lwinmm -lcomdlg32 -lole32
- Raylib built from source and statically linked (no .so/.dll)
- Font embedded at compile time via xxd (best-effort)
- Auto-discovery of src/*.c files via wildcard
- Target-specific variables for clean dual-target architecture
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|