Current section
Files
Jump to
Current section
Files
src/rockbox@decoder.erl
-module(rockbox@decoder).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/rockbox/decoder.gleam").
-export([open/1, metadata/1, next_chunk/1, seek_ms/2, elapsed_ms/1, finished/1]).
-export_type([decoder/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Decode an audio file to interleaved-stereo S16LE PCM, one chunk at a time.\n"
"\n"
" Wraps the Rockbox codec engine. The codec state is process-wide, so only\n"
" one `Decoder` may decode at a time — opening a second one blocks until the\n"
" first is freed. It is a NIF resource, freed by the BEAM garbage collector —\n"
" no explicit close.\n"
).
-type decoder() :: any().
-file("src/rockbox/decoder.gleam", 18).
?DOC(" Open a decoder for the local audio file at `path`.\n").
-spec open(binary()) -> decoder().
open(Path) ->
rockbox_ffi_nif:decoder_open(Path).
-file("src/rockbox/decoder.gleam", 21).
?DOC(" Tags and stream properties (same shape as `metadata.read`).\n").
-spec metadata(decoder()) -> rockbox@metadata:metadata().
metadata(Decoder) ->
Meta@1 = case gleam@dynamic@decode:run(
json:decode(rockbox_ffi_nif:decoder_metadata_json(Decoder)),
rockbox@metadata:decoder()
) of
{ok, Meta} -> Meta;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"rockbox/decoder"/utf8>>,
function => <<"metadata"/utf8>>,
line => 22,
value => _assert_fail,
start => 826,
'end' => 923,
pattern_start => 837,
pattern_end => 845})
end,
Meta@1.
-file("src/rockbox/decoder.gleam", 55).
-spec chunk_decoder() -> gleam@dynamic@decode:decoder({bitstring(), integer()}).
chunk_decoder() ->
gleam@dynamic@decode:field(
0,
{decoder, fun gleam@dynamic@decode:decode_bit_array/1},
fun(Samples) ->
gleam@dynamic@decode:field(
1,
{decoder, fun gleam@dynamic@decode:decode_int/1},
fun(Rate) -> gleam@dynamic@decode:success({Samples, Rate}) end
)
end
).
-file("src/rockbox/decoder.gleam", 30).
?DOC(
" Next buffer of decoded PCM as `#(samples, sample_rate)`, where `samples` is\n"
" a little-endian int16 buffer of interleaved stereo PCM. `None` at end of\n"
" track (or after a codec error — see `finished`).\n"
).
-spec next_chunk(decoder()) -> gleam@option:option({bitstring(), integer()}).
next_chunk(Decoder) ->
case gleam@dynamic@decode:run(
rockbox_ffi_nif:decoder_next_chunk(Decoder),
chunk_decoder()
) of
{ok, Chunk} ->
{some, Chunk};
{error, _} ->
none
end.
-file("src/rockbox/decoder.gleam", 39).
?DOC(" Request a seek to `ms` milliseconds.\n").
-spec seek_ms(decoder(), integer()) -> nil.
seek_ms(Decoder, Ms) ->
rockbox_ffi_nif:decoder_seek_ms(Decoder, Ms).
-file("src/rockbox/decoder.gleam", 43).
?DOC(" Playback position last reported by the codec, in milliseconds.\n").
-spec elapsed_ms(decoder()) -> integer().
elapsed_ms(Decoder) ->
rockbox_ffi_nif:decoder_elapsed_ms(Decoder).
-file("src/rockbox/decoder.gleam", 49).
?DOC(
" `#(done, code)`: `done` is `True` once the track has ended; `code` is the\n"
" exit status (`0` = clean end, negative = codec error), valid only when\n"
" `done`.\n"
).
-spec finished(decoder()) -> {boolean(), integer()}.
finished(Decoder) ->
rockbox_ffi_nif:decoder_finished(Decoder).