Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix CPAL sink start and codec/m4a symbol conflicts

Re-arm the CPAL ring on DMA start by exporting pcm_cpal_start() and
calling it from sink_dma_start to avoid silently discarding data after
pcm_cpal_stop.

Prefix m4a stream helpers (m4a_stream_*) and update headers/usages to
avoid global symbol collisions. Add CODECS_STATIC guards in codec_crt0
so
stubs/symbols are omitted for static codec builds. Add
--allow-multiple-definition for headless linker to tolerate duplicate
symbols from bundled libraries.

+160 -12
+64
.github/workflows/linux-aarch64-check.yml
··· 1 + name: linux-aarch64-check 2 + on: 3 + push: 4 + branches: 5 + - "**" 6 + pull_request: 7 + 8 + jobs: 9 + build: 10 + runs-on: ubuntu-24.04-arm 11 + steps: 12 + - uses: actions/checkout@v4 13 + with: 14 + submodules: true 15 + 16 + - uses: mlugg/setup-zig@v2 17 + with: 18 + version: 0.16.0 19 + 20 + - name: Install dependencies 21 + run: | 22 + sudo apt-get update 23 + sudo apt-get install -y \ 24 + build-essential \ 25 + libunwind-dev \ 26 + libasound2-dev \ 27 + libdbus-1-dev \ 28 + protobuf-compiler \ 29 + cmake 30 + 31 + - uses: actions-rust-lang/setup-rust-toolchain@v1 32 + 33 + - name: Cache Cargo 34 + uses: actions/cache@v4 35 + with: 36 + path: | 37 + ~/.cargo/registry 38 + ~/.cargo/git 39 + zig/.zig-cache 40 + target 41 + key: linux-aarch64-check-cargo-${{ hashFiles('**/Cargo.lock') }} 42 + restore-keys: linux-aarch64-check-cargo- 43 + 44 + - uses: denoland/setup-deno@v2 45 + with: 46 + deno-version: v2.x 47 + 48 + - name: Build Web UI 49 + run: | 50 + cd webui/rockbox 51 + deno install 52 + deno run build 53 + 54 + - name: Rust flags 55 + run: echo "RUSTFLAGS=-A warnings" >> $GITHUB_ENV 56 + 57 + - name: Build rockboxd (headless) 58 + run: bash scripts/build-headless.sh 59 + 60 + - name: Build rockbox CLI 61 + run: cargo build -p rockbox --release 62 + 63 + - name: Show artifacts 64 + run: ls -lh target/release/rockbox zig/zig-out/bin/rockboxd
+64
.github/workflows/linux-x86_64-check.yml
··· 1 + name: linux-x86_64-check 2 + on: 3 + push: 4 + branches: 5 + - "**" 6 + pull_request: 7 + 8 + jobs: 9 + build: 10 + runs-on: ubuntu-latest 11 + steps: 12 + - uses: actions/checkout@v4 13 + with: 14 + submodules: true 15 + 16 + - uses: mlugg/setup-zig@v2 17 + with: 18 + version: 0.16.0 19 + 20 + - name: Install dependencies 21 + run: | 22 + sudo apt-get update 23 + sudo apt-get install -y \ 24 + build-essential \ 25 + libunwind-dev \ 26 + libasound2-dev \ 27 + libdbus-1-dev \ 28 + protobuf-compiler \ 29 + cmake 30 + 31 + - uses: actions-rust-lang/setup-rust-toolchain@v1 32 + 33 + - name: Cache Cargo 34 + uses: actions/cache@v4 35 + with: 36 + path: | 37 + ~/.cargo/registry 38 + ~/.cargo/git 39 + zig/.zig-cache 40 + target 41 + key: linux-x86_64-check-cargo-${{ hashFiles('**/Cargo.lock') }} 42 + restore-keys: linux-x86_64-check-cargo- 43 + 44 + - uses: denoland/setup-deno@v2 45 + with: 46 + deno-version: v2.x 47 + 48 + - name: Build Web UI 49 + run: | 50 + cd webui/rockbox 51 + deno install 52 + deno run build 53 + 54 + - name: Rust flags 55 + run: echo "RUSTFLAGS=-C target-cpu=x86-64 -A warnings" >> $GITHUB_ENV 56 + 57 + - name: Build rockboxd (headless) 58 + run: bash scripts/build-headless.sh 59 + 60 + - name: Build rockbox CLI 61 + run: cargo build -p rockbox --release 62 + 63 + - name: Show artifacts 64 + run: ls -lh target/release/rockbox zig/zig-out/bin/rockboxd
+7
crates/cpal-sink/src/lib.rs
··· 380 380 } 381 381 382 382 #[no_mangle] 383 + pub extern "C" fn pcm_cpal_start() { 384 + let (lock, _cvar) = ring(); 385 + let mut r = lock.lock().unwrap(); 386 + r.running = true; 387 + } 388 + 389 + #[no_mangle] 383 390 pub extern "C" fn pcm_cpal_stop() { 384 391 let (lock, cvar) = ring(); 385 392 let mut r = lock.lock().unwrap();
+5
firmware/target/hosted/headless/pcm-cpal.c
··· 34 34 extern void pcm_cpal_init(void); 35 35 extern void pcm_cpal_postinit(void); 36 36 extern void pcm_cpal_set_sample_rate(uint32_t rate_hz); 37 + extern void pcm_cpal_start(void); 37 38 extern void pcm_cpal_push(const void *data, size_t size); 38 39 extern void pcm_cpal_stop(void); 39 40 ··· 121 122 static void sink_dma_start(const void *addr, size_t size) 122 123 { 123 124 logf("pcm-cpal: start (%p, %zu)", addr, size); 125 + 126 + /* Re-arm the ring so pcm_cpal_push() doesn't silently discard data after 127 + * a previous pcm_cpal_stop() set running=false. */ 128 + pcm_cpal_start(); 124 129 125 130 pthread_mutex_lock(&cpal_mtx); 126 131 pcm_data = addr;
+4
lib/rbcodec/codecs/codec_crt0.c
··· 22 22 #include "config.h" 23 23 #include "codecs.h" 24 24 25 + #ifndef CODECS_STATIC 25 26 struct codec_api *ci DATA_ATTR; 27 + #endif 26 28 27 29 extern unsigned char plugin_bss_start[]; 28 30 extern unsigned char plugin_end_addr[]; 29 31 30 32 /* stub, the entry point is called via its reference in __header to 31 33 * avoid warning with certain compilers */ 34 + #ifndef CODECS_STATIC 32 35 int _start(void) {return 0;} 36 + #endif 33 37 34 38 #ifdef CTRU 35 39 /* dummy undefined symbols */
+1 -1
lib/rbcodec/codecs/libm4a/demux.c
··· 238 238 ((unsigned int*)qtmovie->res->codecdata)[2] = MAKEFOURCC('c','a','l','a'); 239 239 #endif 240 240 241 - stream_read(qtmovie->stream, 241 + m4a_stream_read(qtmovie->stream, 242 242 entry_remaining, 243 243 ((char*)qtmovie->res->codecdata) + 12); 244 244 entry_remaining -= entry_remaining;
+10 -10
lib/rbcodec/codecs/libm4a/m4a.c
··· 43 43 (((v) & 0xFF00) >> 0x08); } while (0) 44 44 45 45 /* A normal read without any byte-swapping */ 46 - void stream_read(stream_t *stream, size_t size, void *buf) 46 + void m4a_stream_read(stream_t *stream, size_t size, void *buf) 47 47 { 48 48 stream->ci->read_filebuf(buf,size); 49 49 if (stream->ci->curpos >= stream->ci->filesize) { stream->eof=1; } 50 50 } 51 51 52 - int32_t stream_read_int32(stream_t *stream) 52 + int32_t m4a_stream_read_int32(stream_t *stream) 53 53 { 54 54 int32_t v; 55 - stream_read(stream, 4, &v); 55 + m4a_stream_read(stream, 4, &v); 56 56 #ifdef ROCKBOX_LITTLE_ENDIAN 57 57 _Swap32(v); 58 58 #endif ··· 64 64 return stream->ci->curpos; 65 65 } 66 66 67 - uint32_t stream_read_uint32(stream_t *stream) 67 + uint32_t m4a_stream_read_uint32(stream_t *stream) 68 68 { 69 69 uint32_t v; 70 - stream_read(stream, 4, &v); 70 + m4a_stream_read(stream, 4, &v); 71 71 #ifdef ROCKBOX_LITTLE_ENDIAN 72 72 _Swap32(v); 73 73 #endif 74 74 return v; 75 75 } 76 76 77 - uint16_t stream_read_uint16(stream_t *stream) 77 + uint16_t m4a_stream_read_uint16(stream_t *stream) 78 78 { 79 79 uint16_t v; 80 - stream_read(stream, 2, &v); 80 + m4a_stream_read(stream, 2, &v); 81 81 #ifdef ROCKBOX_LITTLE_ENDIAN 82 82 _Swap16(v); 83 83 #endif 84 84 return v; 85 85 } 86 86 87 - uint8_t stream_read_uint8(stream_t *stream) 87 + uint8_t m4a_stream_read_uint8(stream_t *stream) 88 88 { 89 89 uint8_t v; 90 - stream_read(stream, 1, &v); 90 + m4a_stream_read(stream, 1, &v); 91 91 return v; 92 92 } 93 93 ··· 229 229 time_dur = tts_tab[time].sample_duration; 230 230 } 231 231 232 - offset += tsz_tab ? tsz_tab[i] : stream_read_uint32(stream); 232 + offset += tsz_tab ? tsz_tab[i] : m4a_stream_read_uint32(stream); 233 233 sound_sample_i += time_dur; 234 234 time_cnt--; 235 235 }
+1 -1
lib/rbcodec/codecs/libm4a/m4a.h
··· 113 113 (char)code 114 114 #endif 115 115 116 - void stream_read(stream_t *stream, size_t len, void *buf); 116 + void m4a_stream_read(stream_t *stream, size_t len, void *buf); 117 117 118 118 int32_t stream_tell(stream_t *stream); 119 119 int32_t stream_read_int32(stream_t *stream);
+4
zig/build.zig
··· 116 116 if (headless) { 117 117 // cpal uses ALSA on Linux by default. 118 118 exe.root_module.linkSystemLibrary("asound", .{}); 119 + // libopus and libtremor both bundle identical Ogg framing symbols; 120 + // libspeex and libspeex-voice share bits.c symbols. lld errors on 121 + // duplicates while macOS ld64 silently picks first. 122 + exe.addLinkerArg("--allow-multiple-definition"); 119 123 } 120 124 } 121 125