rockbox_ffi 0.3.0-x86_64-linux → 0.4.0-x86_64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rockbox_ffi/decoder.rb +113 -0
- data/lib/rockbox_ffi/ffi.rb +11 -0
- data/lib/rockbox_ffi/player.rb +11 -0
- data/lib/rockbox_ffi/version.rb +1 -1
- data/lib/rockbox_ffi.rb +2 -1
- data/vendor/librockbox_ffi.so +0 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4e35ed08865d334c859871d63d0b7599d05bdce99f42c41fe9ab3e0f80278f9c
|
|
4
|
+
data.tar.gz: 6aa2a2005ba3b9eaf949678ddcda94d8da0bb0410d7f18e565ab1bbbf58396c2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '09503d7c32511c00a392769ea4202ee21f140457e4beb21106b31da4949d681d530945ac2da51108846b93075192b1c7cc2e4932e4201cd51a1cbcbe2fc551ee'
|
|
7
|
+
data.tar.gz: 8e40d3a60b54597cd08361ad80aa151e20e48ce257469b09fc80c157679f597970843ed9a5ac442c7414134a97fb33551239f0ca417695da0297ffcc5279314b
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module RockboxFFI
|
|
6
|
+
# Decode a local audio file to interleaved-stereo S16 PCM, one chunk at a
|
|
7
|
+
# time, using the Rockbox codec engine.
|
|
8
|
+
#
|
|
9
|
+
# The codec state is process-wide, so only one Decoder may decode at a time
|
|
10
|
+
# and it must be used from one thread. Call #close when done, or use the block
|
|
11
|
+
# form Decoder.open(path) { |dec| ... }.
|
|
12
|
+
class Decoder
|
|
13
|
+
# Open a Decoder for +path+; if a block is given, close it automatically
|
|
14
|
+
# afterwards.
|
|
15
|
+
def self.open(path)
|
|
16
|
+
dec = new(path)
|
|
17
|
+
return dec unless block_given?
|
|
18
|
+
|
|
19
|
+
begin
|
|
20
|
+
yield dec
|
|
21
|
+
ensure
|
|
22
|
+
dec.close
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def initialize(path)
|
|
27
|
+
@ptr = Lib.rb_decoder_open(path.to_s)
|
|
28
|
+
raise "could not open decoder for #{path.inspect}" if @ptr.null?
|
|
29
|
+
|
|
30
|
+
@finalizer = self.class.send(:finalizer, @ptr)
|
|
31
|
+
ObjectSpace.define_finalizer(self, @finalizer)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# -- lifecycle --------------------------------------------------------
|
|
35
|
+
def close
|
|
36
|
+
return if @ptr.nil?
|
|
37
|
+
|
|
38
|
+
ObjectSpace.undefine_finalizer(self)
|
|
39
|
+
Lib.rb_decoder_free(@ptr)
|
|
40
|
+
@ptr = nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def closed?
|
|
44
|
+
@ptr.nil?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.finalizer(ptr)
|
|
48
|
+
proc { Lib.rb_decoder_free(ptr) }
|
|
49
|
+
end
|
|
50
|
+
private_class_method :finalizer
|
|
51
|
+
|
|
52
|
+
# -- metadata ---------------------------------------------------------
|
|
53
|
+
# Tags and stream properties (same shape as Metadata.read). Returns a Hash
|
|
54
|
+
# with symbol keys. Raises on failure.
|
|
55
|
+
def metadata
|
|
56
|
+
s = RockboxFFI.take_string(Lib.rb_decoder_metadata_json(@ptr))
|
|
57
|
+
raise "rb_decoder_metadata_json returned NULL" if s.nil?
|
|
58
|
+
|
|
59
|
+
JSON.parse(s, symbolize_names: true)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# -- decoding ---------------------------------------------------------
|
|
63
|
+
# Next buffer of decoded PCM as +[samples, sample_rate]+, where +samples+
|
|
64
|
+
# is an Array of interleaved stereo int16 Integers. Returns nil at end of
|
|
65
|
+
# track (or after a codec error — see #finished).
|
|
66
|
+
def next_chunk
|
|
67
|
+
out_len = "\0" * Fiddle::SIZEOF_VOIDP # size_t* out-param (i16 count)
|
|
68
|
+
out_rate = "\0" * Fiddle::SIZEOF_INT # uint32_t* out-param (Hz)
|
|
69
|
+
ptr = Lib.rb_decoder_next_chunk(@ptr, out_len, out_rate)
|
|
70
|
+
|
|
71
|
+
produced = out_len.unpack1(Fiddle::SIZEOF_VOIDP == 8 ? "Q" : "L")
|
|
72
|
+
return nil if ptr.null? || produced.zero?
|
|
73
|
+
|
|
74
|
+
rate = out_rate.unpack1("L")
|
|
75
|
+
begin
|
|
76
|
+
ptr.size = produced * 2
|
|
77
|
+
[ptr[0, produced * 2].unpack("s<*"), rate]
|
|
78
|
+
ensure
|
|
79
|
+
Lib.rb_buffer_free(ptr, produced)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Yield each +[samples, sample_rate]+ chunk until end of track. Returns an
|
|
84
|
+
# Enumerator when no block is given.
|
|
85
|
+
def each_chunk
|
|
86
|
+
return enum_for(:each_chunk) unless block_given?
|
|
87
|
+
|
|
88
|
+
while (chunk = next_chunk)
|
|
89
|
+
yield chunk
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Request a seek to +ms+ milliseconds.
|
|
94
|
+
def seek_ms(ms)
|
|
95
|
+
Lib.rb_decoder_seek_ms(@ptr, Integer(ms))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Playback position last reported by the codec, in milliseconds.
|
|
99
|
+
def elapsed_ms
|
|
100
|
+
Lib.rb_decoder_elapsed_ms(@ptr)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# +[done, code]+: +done+ is true once the track has ended; +code+ is the
|
|
104
|
+
# exit status (0 = clean end, negative = codec error), valid only when
|
|
105
|
+
# +done+.
|
|
106
|
+
def finished
|
|
107
|
+
out_code = "\0" * Fiddle::SIZEOF_INT # int32_t* out-param
|
|
108
|
+
r = Lib.rb_decoder_finished(@ptr, out_code)
|
|
109
|
+
done = r == true || r == 1
|
|
110
|
+
[done, out_code.unpack1("l")]
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
data/lib/rockbox_ffi/ffi.rb
CHANGED
|
@@ -98,6 +98,15 @@ module RockboxFFI
|
|
|
98
98
|
extern "void* rb_meta_read_json(void*)"
|
|
99
99
|
extern "void* rb_meta_probe(void*)"
|
|
100
100
|
|
|
101
|
+
# ---- decoder ------------------------------------------------------
|
|
102
|
+
extern "void* rb_decoder_open(void*)"
|
|
103
|
+
extern "void rb_decoder_free(void*)"
|
|
104
|
+
extern "void* rb_decoder_metadata_json(void*)"
|
|
105
|
+
extern "int16_t* rb_decoder_next_chunk(void*, void*, void*)"
|
|
106
|
+
extern "void rb_decoder_seek_ms(void*, uint64_t)"
|
|
107
|
+
extern "uint64_t rb_decoder_elapsed_ms(void*)"
|
|
108
|
+
extern "bool rb_decoder_finished(void*, void*)"
|
|
109
|
+
|
|
101
110
|
# ---- player -------------------------------------------------------
|
|
102
111
|
extern "void* rb_player_new()"
|
|
103
112
|
extern "void* rb_player_new_with_config(uint32_t, float, float, int32_t, float, bool, int32_t, uint32_t, uint32_t, uint32_t, uint32_t, int32_t)"
|
|
@@ -116,9 +125,11 @@ module RockboxFFI
|
|
|
116
125
|
extern "void rb_player_skip_to(void*, size_t)"
|
|
117
126
|
extern "void rb_player_seek_ms(void*, uint64_t)"
|
|
118
127
|
extern "void rb_player_set_volume(void*, float)"
|
|
128
|
+
extern "void rb_player_set_balance(void*, int32_t)"
|
|
119
129
|
extern "void rb_player_set_crossfade(void*, int32_t, uint32_t, uint32_t, uint32_t, uint32_t, int32_t)"
|
|
120
130
|
extern "void rb_player_set_replaygain(void*, int32_t, float, bool)"
|
|
121
131
|
extern "float rb_player_volume(void*)"
|
|
132
|
+
extern "int32_t rb_player_balance(void*)"
|
|
122
133
|
extern "uint32_t rb_player_sample_rate(void*)"
|
|
123
134
|
extern "void* rb_player_status_json(void*)"
|
|
124
135
|
extern "void rb_player_set_shuffle(void*, bool)"
|
data/lib/rockbox_ffi/player.rb
CHANGED
|
@@ -169,10 +169,21 @@ module RockboxFFI
|
|
|
169
169
|
self
|
|
170
170
|
end
|
|
171
171
|
|
|
172
|
+
# Stereo balance, -100 (full left) to +100 (full right); 0 = centre.
|
|
173
|
+
def set_balance(balance)
|
|
174
|
+
Lib.rb_player_set_balance(@ptr, Integer(balance))
|
|
175
|
+
self
|
|
176
|
+
end
|
|
177
|
+
|
|
172
178
|
def volume
|
|
173
179
|
Lib.rb_player_volume(@ptr)
|
|
174
180
|
end
|
|
175
181
|
|
|
182
|
+
# Current stereo balance, -100 (full left) to +100 (full right).
|
|
183
|
+
def balance
|
|
184
|
+
Lib.rb_player_balance(@ptr)
|
|
185
|
+
end
|
|
186
|
+
|
|
176
187
|
def sample_rate
|
|
177
188
|
Lib.rb_player_sample_rate(@ptr)
|
|
178
189
|
end
|
data/lib/rockbox_ffi/version.rb
CHANGED
data/lib/rockbox_ffi.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Ruby bindings for the Rockbox DSP / metadata / playback engine.
|
|
4
4
|
#
|
|
5
5
|
# Thin Fiddle wrappers over the librockbox_ffi C ABI. See RockboxFFI::Metadata,
|
|
6
|
-
# RockboxFFI::Dsp, and RockboxFFI::
|
|
6
|
+
# RockboxFFI::Dsp, RockboxFFI::Player, and RockboxFFI::Decoder.
|
|
7
7
|
|
|
8
8
|
require "rockbox_ffi/version"
|
|
9
9
|
require "rockbox_ffi/ffi"
|
|
@@ -11,6 +11,7 @@ require "rockbox_ffi/enums"
|
|
|
11
11
|
require "rockbox_ffi/metadata"
|
|
12
12
|
require "rockbox_ffi/dsp"
|
|
13
13
|
require "rockbox_ffi/player"
|
|
14
|
+
require "rockbox_ffi/decoder"
|
|
14
15
|
|
|
15
16
|
require "json"
|
|
16
17
|
|
data/vendor/librockbox_ffi.so
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rockbox_ffi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: x86_64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Tsiry Sandratraina
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-07-
|
|
11
|
+
date: 2026-07-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: fiddle
|
|
@@ -37,6 +37,7 @@ files:
|
|
|
37
37
|
- examples/play.rb
|
|
38
38
|
- examples/smoke.rb
|
|
39
39
|
- lib/rockbox_ffi.rb
|
|
40
|
+
- lib/rockbox_ffi/decoder.rb
|
|
40
41
|
- lib/rockbox_ffi/dsp.rb
|
|
41
42
|
- lib/rockbox_ffi/enums.rb
|
|
42
43
|
- lib/rockbox_ffi/ffi.rb
|