Something went wrong. Try again.
A modern, network-enabled music player platform built on Rockbox technology. rockboxd.tsiry-sandratraina.com
rust deno navidrome airplay libadwaita zig mpris snapcast mpd rockbox audio subsonic
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220"""cffi (ABI mode) loader for librockbox_ffi.
Declares exactly the functions we call and ``dlopen``s the prebuilt sharedlibrary — no C is compiled here. The library is located via the``ROCKBOX_FFI_LIB`` env var, then by walking up to the repo's``target/release`` directory."""
from __future__ import annotations
import osfrom pathlib import Path
from cffi import FFI
ffi = FFI()
# Mirrors include/rockbox_ffi.h — keep in sync with the C ABI.ffi.cdef( """ typedef struct RbDsp RbDsp; typedef struct RbPlayer RbPlayer; typedef struct RbDecoder RbDecoder;
uint32_t rb_ffi_abi_version(void);
void rb_string_free(char *p); void rb_buffer_free(int16_t *p, size_t len);
RbDecoder *rb_decoder_open(const char *path); void rb_decoder_free(RbDecoder *d); char *rb_decoder_metadata_json(RbDecoder *d); int16_t *rb_decoder_next_chunk(RbDecoder *d, size_t *out_len, uint32_t *out_sample_rate); void rb_decoder_seek_ms(RbDecoder *d, uint64_t ms); uint64_t rb_decoder_elapsed_ms(RbDecoder *d); bool rb_decoder_finished(RbDecoder *d, int32_t *out_code);
RbDsp *rb_dsp_new(uint32_t sample_rate); void rb_dsp_free(RbDsp *p); void rb_dsp_set_input_frequency(RbDsp *p, uint32_t hz); void rb_dsp_flush(RbDsp *p); void rb_dsp_eq_enable(RbDsp *p, bool enable); void rb_dsp_set_tone(RbDsp *p, int32_t bass_db, int32_t treble_db); void rb_dsp_set_tone_cutoffs(RbDsp *p, int32_t bass_hz, int32_t treble_hz); void rb_dsp_set_surround(RbDsp *p, int32_t delay_ms, int32_t balance, int32_t fx1, int32_t fx2); void rb_dsp_set_channel_config(RbDsp *p, int32_t mode); void rb_dsp_set_stereo_width(RbDsp *p, int32_t percent); void rb_dsp_set_compressor(RbDsp *p, int32_t threshold, int32_t makeup_gain, int32_t ratio, int32_t knee, int32_t release_time, int32_t attack_time); void rb_dsp_set_replaygain(RbDsp *p, int32_t mode, bool noclip, float preamp_db); void rb_dsp_set_replaygain_gains(RbDsp *p, float track_gain_db, float album_gain_db, float track_peak, float album_peak); void rb_dsp_set_replaygain_gains_raw(RbDsp *p, int64_t track_gain, int64_t album_gain, int64_t track_peak, int64_t album_peak); void rb_dsp_set_eq_band(RbDsp *p, size_t band, int32_t cutoff_hz, float q, float gain_db); void rb_dsp_set_eq_precut(RbDsp *p, float db); int16_t *rb_dsp_process(RbDsp *p, const int16_t *input, size_t in_len, size_t *out_len);
char *rb_meta_read_json(const char *path); char *rb_meta_probe(const char *filename);
RbPlayer *rb_player_new(void); RbPlayer *rb_player_new_with_config(uint32_t sample_rate, float buffer_seconds, float volume, int32_t rg_mode, float rg_preamp_db, bool rg_prevent_clipping, int32_t xfade_mode, uint32_t fo_delay_ms, uint32_t fo_dur_ms, uint32_t fi_delay_ms, uint32_t fi_dur_ms, int32_t mix_mode); RbPlayer *rb_player_new_with_config_ex(uint32_t sample_rate, float buffer_seconds, float volume, int32_t rg_mode, float rg_preamp_db, bool rg_prevent_clipping, int32_t xfade_mode, uint32_t fo_delay_ms, uint32_t fo_dur_ms, uint32_t fi_delay_ms, uint32_t fi_dur_ms, int32_t mix_mode, const char *resume_file, uint32_t resume_save_interval_ms); RbPlayer *rb_player_new_with_output(const char *output, uint32_t sample_rate, float buffer_seconds, float volume, int32_t rg_mode, float rg_preamp_db, bool rg_prevent_clipping, int32_t xfade_mode, uint32_t fo_delay_ms, uint32_t fo_dur_ms, uint32_t fi_delay_ms, uint32_t fi_dur_ms, int32_t mix_mode, const char *resume_file, uint32_t resume_save_interval_ms); void rb_player_free(RbPlayer *p); void rb_player_set_queue_json(RbPlayer *p, const char *json); void rb_player_enqueue(RbPlayer *p, const char *path); void rb_player_insert_json(RbPlayer *p, const char *json, int32_t position, size_t index); char *rb_player_queue_json(RbPlayer *p); void rb_player_play(RbPlayer *p); void rb_player_pause(RbPlayer *p); void rb_player_toggle(RbPlayer *p); void rb_player_stop(RbPlayer *p); void rb_player_next(RbPlayer *p); void rb_player_previous(RbPlayer *p); void rb_player_skip_to(RbPlayer *p, size_t index); void rb_player_remove(RbPlayer *p, size_t index); void rb_player_clear_queue(RbPlayer *p); void rb_player_seek_ms(RbPlayer *p, uint64_t ms); void rb_player_set_volume(RbPlayer *p, float vol); void rb_player_set_balance(RbPlayer *p, int32_t balance); void rb_player_set_crossfade(RbPlayer *p, int32_t mode, uint32_t fo_delay_ms, uint32_t fo_dur_ms, uint32_t fi_delay_ms, uint32_t fi_dur_ms, int32_t mix_mode); void rb_player_set_replaygain(RbPlayer *p, int32_t mode, float preamp_db, bool prevent_clipping); void rb_player_set_shuffle(RbPlayer *p, bool enabled); bool rb_player_is_shuffle_enabled(RbPlayer *p); void rb_player_set_repeat(RbPlayer *p, int32_t mode); int32_t rb_player_repeat(RbPlayer *p); void rb_player_set_eq_enabled(RbPlayer *p, bool enabled); bool rb_player_is_eq_enabled(RbPlayer *p); void rb_player_set_eq_band(RbPlayer *p, size_t band, int32_t cutoff_hz, float q, float gain_db); void rb_player_set_eq_precut(RbPlayer *p, float db); void rb_player_set_eq_preset(RbPlayer *p, int32_t preset); void rb_player_set_tone(RbPlayer *p, int32_t bass_db, int32_t treble_db, int32_t bass_cutoff_hz, int32_t treble_cutoff_hz); void rb_player_set_bass(RbPlayer *p, int32_t bass_db); void rb_player_set_treble(RbPlayer *p, int32_t treble_db); void rb_player_set_surround(RbPlayer *p, int32_t delay_ms, int32_t balance, int32_t cutoff_low_hz, int32_t cutoff_high_hz); void rb_player_set_channel_mode(RbPlayer *p, int32_t mode); void rb_player_set_stereo_width(RbPlayer *p, int32_t percent); void rb_player_set_compressor(RbPlayer *p, int32_t threshold_db, int32_t makeup_gain, int32_t ratio, int32_t knee, int32_t attack_ms, int32_t release_ms); void rb_player_set_bass_cutoff(RbPlayer *p, int32_t hz); void rb_player_set_treble_cutoff(RbPlayer *p, int32_t hz); void rb_player_set_crossfeed(RbPlayer *p, int32_t mode, int32_t direct_gain, int32_t cross_gain, int32_t hf_gain, int32_t hf_cutoff); void rb_player_set_bass_enhancement(RbPlayer *p, int32_t strength, int32_t precut); void rb_player_set_fatigue_reduction(RbPlayer *p, int32_t strength); void rb_player_set_dither(RbPlayer *p, bool enabled); void rb_player_set_pitch(RbPlayer *p, int32_t ratio); char *rb_player_dsp_settings_json(RbPlayer *p); float rb_player_volume(RbPlayer *p); int32_t rb_player_balance(RbPlayer *p); uint32_t rb_player_sample_rate(RbPlayer *p); char *rb_player_status_json(RbPlayer *p);
char *rb_player_resume(RbPlayer *p); void rb_player_save_resume(RbPlayer *p); void rb_player_clear_resume(RbPlayer *p); char *rb_load_resume_json(const char *path);
char *rb_player_import_m3u(RbPlayer *p, const char *path, int32_t position, size_t index); char *rb_player_load_m3u(RbPlayer *p, const char *path); int32_t rb_player_export_m3u(RbPlayer *p, const char *path); char *rb_m3u_read_json(const char *path); int32_t rb_m3u_write_json(const char *path, const char *json); bool rb_is_url(const char *s); """)
def _candidate_paths() -> list[Path]: names = ["librockbox_ffi.dylib", "librockbox_ffi.so", "rockbox_ffi.dll"] paths: list[Path] = []
# 1. Explicit override. env = os.environ.get("ROCKBOX_FFI_LIB") if env: paths.append(Path(env))
# 2. Bundled binary (platform wheels ship one in the package's _lib/ dir). lib_dir = Path(__file__).resolve().parent / "_lib" for name in names: paths.append(lib_dir / name)
# 3. Walk up from this file looking for target/release (repo checkout). here = Path(__file__).resolve() for parent in here.parents: rel = parent / "target" / "release" if rel.is_dir(): for name in names: paths.append(rel / name) return paths
def _load(): tried: list[str] = [] for path in _candidate_paths(): tried.append(str(path)) if path.exists(): return ffi.dlopen(str(path)) raise OSError( "could not locate librockbox_ffi shared library. Set ROCKBOX_FFI_LIB " "or run `cargo build --release -p rockbox-ffi`. Tried:\n " + "\n ".join(tried) )
lib = _load()
def take_string(ptr) -> str | None: """Copy a heap C string returned by the ABI into a str, then free it.
Returns ``None`` for a NULL pointer (the ABI's error/absent signal). """ if ptr == ffi.NULL: return None try: return ffi.string(ptr).decode("utf-8", "replace") finally: lib.rb_string_free(ptr)