rockbox_ffi 0.2.0 → 0.3.0
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/README.md +4 -0
- data/examples/play.rb +9 -2
- data/lib/rockbox_ffi/enums.rb +50 -0
- data/lib/rockbox_ffi/ffi.rb +26 -0
- data/lib/rockbox_ffi/player.rb +183 -0
- data/lib/rockbox_ffi/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 65435e6c7a7b4ef8e59f3bc088ce2c9eb978b34d49e134c3e42413e9790bb333
|
|
4
|
+
data.tar.gz: 0d14838882902eaa6818a9726518f0c782848ad34e09b6afe6ca9ddbbf6cdd1a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f4275075ebc6d35b7b495dfc3a081b97960f5dc81f8f279372acf5b852fc0723776f536f9f87602811499a23d1653de9a8c5b072144444fe15dd0cd4b4dc1066
|
|
7
|
+
data.tar.gz: 5b4a35ca244aed1f570cf2d639a131eb8244645fe4ebe86513193345a95716107c72c67f7037f195e8048bff4f885c1d3c8af1fdd218ffabcf200860b841e363
|
data/README.md
CHANGED
|
@@ -10,6 +10,10 @@ via [`fiddle`](https://docs.ruby-lang.org/en/master/Fiddle.html) (Ruby stdlib)
|
|
|
10
10
|
over the prebuilt `librockbox_ffi` shared library. No native extension is
|
|
11
11
|
compiled — the gem `dlopen`s the shared library at load time.
|
|
12
12
|
|
|
13
|
+
> 📖 **Sound settings reference** — the equalizer, tone, crossfeed, compressor
|
|
14
|
+
> and other DSP controls mirror Rockbox's own. See the official
|
|
15
|
+
> [Rockbox manual — Sound Settings](https://download.rockbox.org/daily/manual/rockbox-ipodvideo/rockbox-buildch6.html).
|
|
16
|
+
|
|
13
17
|
## Setup
|
|
14
18
|
|
|
15
19
|
Build the shared library once (from the repo root):
|
data/examples/play.rb
CHANGED
|
@@ -13,9 +13,16 @@ FIXTURE = File.join(REPO, "crates", "rocksky", "fixtures", "08 - Internet Money
|
|
|
13
13
|
file = ARGV[0] || FIXTURE
|
|
14
14
|
|
|
15
15
|
player = RockboxFFI::Player.new(volume: 0.8)
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
# Mutating setters return self, so the setup reads as one fluent chain.
|
|
17
|
+
# DSP: Bass Boost preset + a +7 dB bass / +4 dB treble lift.
|
|
18
|
+
player
|
|
19
|
+
.set_queue([file])
|
|
20
|
+
.set_eq_preset(RockboxFFI::EqPreset::BASS_BOOST)
|
|
21
|
+
.set_bass(7)
|
|
22
|
+
.set_treble(4)
|
|
23
|
+
.play
|
|
18
24
|
puts "▶ playing #{file}"
|
|
25
|
+
puts "eq: BassBoost preset, bass +7 dB, treble +4 dB"
|
|
19
26
|
|
|
20
27
|
# Reinstall a SIGINT handler AFTER the player boots: the native audio engine
|
|
21
28
|
# installs its own signal handler while starting the output device, which
|
data/lib/rockbox_ffi/enums.rb
CHANGED
|
@@ -18,6 +18,13 @@ module RockboxFFI
|
|
|
18
18
|
ALBUM = 2
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
# Values for Player#set_repeat / #repeat.
|
|
22
|
+
module RepeatMode
|
|
23
|
+
OFF = 0
|
|
24
|
+
ONE = 1
|
|
25
|
+
ALL = 2
|
|
26
|
+
end
|
|
27
|
+
|
|
21
28
|
module CrossfadeMode
|
|
22
29
|
OFF = 0
|
|
23
30
|
AUTO_SKIP = 1
|
|
@@ -54,4 +61,47 @@ module RockboxFFI
|
|
|
54
61
|
KARAOKE = 5
|
|
55
62
|
SWAP = 6
|
|
56
63
|
end
|
|
64
|
+
|
|
65
|
+
# Built-in EQ presets for Player#set_eq_preset.
|
|
66
|
+
module EqPreset
|
|
67
|
+
FLAT = 0
|
|
68
|
+
ACOUSTIC = 1
|
|
69
|
+
BASS_BOOST = 2
|
|
70
|
+
BASS_REDUCER = 3
|
|
71
|
+
CLASSICAL = 4
|
|
72
|
+
DANCE = 5
|
|
73
|
+
DEEP = 6
|
|
74
|
+
ELECTRONIC = 7
|
|
75
|
+
HIP_HOP = 8
|
|
76
|
+
JAZZ = 9
|
|
77
|
+
LATIN = 10
|
|
78
|
+
LOUDNESS = 11
|
|
79
|
+
LOUNGE = 12
|
|
80
|
+
PIANO = 13
|
|
81
|
+
POP = 14
|
|
82
|
+
RNB = 15
|
|
83
|
+
ROCK = 16
|
|
84
|
+
SMALL_SPEAKERS = 17
|
|
85
|
+
TREBLE_BOOST = 18
|
|
86
|
+
TREBLE_REDUCER = 19
|
|
87
|
+
VOCAL_BOOST = 20
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Crossfeed mode for Player#set_crossfeed.
|
|
91
|
+
module CrossfeedMode
|
|
92
|
+
OFF = 0
|
|
93
|
+
MEIER = 1
|
|
94
|
+
CUSTOM = 2
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Channel mode for Player#set_channel_mode.
|
|
98
|
+
module ChannelMode
|
|
99
|
+
STEREO = 0
|
|
100
|
+
MONO = 1
|
|
101
|
+
CUSTOM = 2
|
|
102
|
+
MONO_LEFT = 3
|
|
103
|
+
MONO_RIGHT = 4
|
|
104
|
+
KARAOKE = 5
|
|
105
|
+
SWAP = 6
|
|
106
|
+
end
|
|
57
107
|
end
|
data/lib/rockbox_ffi/ffi.rb
CHANGED
|
@@ -121,6 +121,32 @@ module RockboxFFI
|
|
|
121
121
|
extern "float rb_player_volume(void*)"
|
|
122
122
|
extern "uint32_t rb_player_sample_rate(void*)"
|
|
123
123
|
extern "void* rb_player_status_json(void*)"
|
|
124
|
+
extern "void rb_player_set_shuffle(void*, bool)"
|
|
125
|
+
extern "bool rb_player_is_shuffle_enabled(void*)"
|
|
126
|
+
extern "void rb_player_set_repeat(void*, int32_t)"
|
|
127
|
+
extern "int32_t rb_player_repeat(void*)"
|
|
128
|
+
|
|
129
|
+
# ---- player DSP ---------------------------------------------------
|
|
130
|
+
extern "void rb_player_set_eq_enabled(void*, bool)"
|
|
131
|
+
extern "bool rb_player_is_eq_enabled(void*)"
|
|
132
|
+
extern "void rb_player_set_eq_band(void*, size_t, int32_t, float, float)"
|
|
133
|
+
extern "void rb_player_set_eq_precut(void*, float)"
|
|
134
|
+
extern "void rb_player_set_eq_preset(void*, int32_t)"
|
|
135
|
+
extern "void rb_player_set_tone(void*, int32_t, int32_t, int32_t, int32_t)"
|
|
136
|
+
extern "void rb_player_set_bass(void*, int32_t)"
|
|
137
|
+
extern "void rb_player_set_treble(void*, int32_t)"
|
|
138
|
+
extern "void rb_player_set_bass_cutoff(void*, int32_t)"
|
|
139
|
+
extern "void rb_player_set_treble_cutoff(void*, int32_t)"
|
|
140
|
+
extern "void rb_player_set_crossfeed(void*, int32_t, int32_t, int32_t, int32_t, int32_t)"
|
|
141
|
+
extern "void rb_player_set_bass_enhancement(void*, int32_t, int32_t)"
|
|
142
|
+
extern "void rb_player_set_fatigue_reduction(void*, int32_t)"
|
|
143
|
+
extern "void rb_player_set_surround(void*, int32_t, int32_t, int32_t, int32_t)"
|
|
144
|
+
extern "void rb_player_set_channel_mode(void*, int32_t)"
|
|
145
|
+
extern "void rb_player_set_stereo_width(void*, int32_t)"
|
|
146
|
+
extern "void rb_player_set_compressor(void*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t)"
|
|
147
|
+
extern "void rb_player_set_dither(void*, bool)"
|
|
148
|
+
extern "void rb_player_set_pitch(void*, int32_t)"
|
|
149
|
+
extern "void* rb_player_dsp_settings_json(void*)"
|
|
124
150
|
|
|
125
151
|
# ---- resume -------------------------------------------------------
|
|
126
152
|
extern "void* rb_player_resume(void*)"
|
data/lib/rockbox_ffi/player.rb
CHANGED
|
@@ -11,6 +11,11 @@ module RockboxFFI
|
|
|
11
11
|
#
|
|
12
12
|
# ReplayGain +mode+ here uses the *player* values: 0 off, 1 track, 2 album
|
|
13
13
|
# (see ReplayGainMode) — distinct from the DSP encoding.
|
|
14
|
+
#
|
|
15
|
+
# Mutating setters (queue, transport, settings, DSP) return +self+ so calls
|
|
16
|
+
# can be fluently chained, e.g.
|
|
17
|
+
# player.set_queue([file]).set_shuffle(true).play
|
|
18
|
+
# Getters/queries and lifecycle methods keep their own return values.
|
|
14
19
|
class Player
|
|
15
20
|
DEFAULT_CONFIG = {
|
|
16
21
|
sample_rate: 0, # 0 => device default
|
|
@@ -85,12 +90,18 @@ module RockboxFFI
|
|
|
85
90
|
private_class_method :finalizer
|
|
86
91
|
|
|
87
92
|
# -- queue ------------------------------------------------------------
|
|
93
|
+
# Replace the queue. Each entry may be a local file path, an http(s)://
|
|
94
|
+
# URL to a finite remote file, or a live-radio / streaming URL.
|
|
88
95
|
def set_queue(paths)
|
|
89
96
|
Lib.rb_player_set_queue_json(@ptr, JSON.generate(Array(paths).map(&:to_s)))
|
|
97
|
+
self
|
|
90
98
|
end
|
|
91
99
|
|
|
100
|
+
# Append one track to the queue. +path+ may be a local file path, an
|
|
101
|
+
# http(s):// URL to a finite remote file, or a live-radio / streaming URL.
|
|
92
102
|
def enqueue(path)
|
|
93
103
|
Lib.rb_player_enqueue(@ptr, path.to_s)
|
|
104
|
+
self
|
|
94
105
|
end
|
|
95
106
|
|
|
96
107
|
# Insert +paths+ (a path/URL or Array of them) into the queue at
|
|
@@ -100,6 +111,7 @@ module RockboxFFI
|
|
|
100
111
|
Lib.rb_player_insert_json(
|
|
101
112
|
@ptr, JSON.generate(Array(paths).map(&:to_s)), Integer(position), Integer(index)
|
|
102
113
|
)
|
|
114
|
+
self
|
|
103
115
|
end
|
|
104
116
|
|
|
105
117
|
# The current queue as an Array of String paths/URLs.
|
|
@@ -113,39 +125,48 @@ module RockboxFFI
|
|
|
113
125
|
# -- transport --------------------------------------------------------
|
|
114
126
|
def play
|
|
115
127
|
Lib.rb_player_play(@ptr)
|
|
128
|
+
self
|
|
116
129
|
end
|
|
117
130
|
|
|
118
131
|
def pause
|
|
119
132
|
Lib.rb_player_pause(@ptr)
|
|
133
|
+
self
|
|
120
134
|
end
|
|
121
135
|
|
|
122
136
|
def toggle
|
|
123
137
|
Lib.rb_player_toggle(@ptr)
|
|
138
|
+
self
|
|
124
139
|
end
|
|
125
140
|
|
|
126
141
|
def stop
|
|
127
142
|
Lib.rb_player_stop(@ptr)
|
|
143
|
+
self
|
|
128
144
|
end
|
|
129
145
|
|
|
130
146
|
def next
|
|
131
147
|
Lib.rb_player_next(@ptr)
|
|
148
|
+
self
|
|
132
149
|
end
|
|
133
150
|
|
|
134
151
|
def previous
|
|
135
152
|
Lib.rb_player_previous(@ptr)
|
|
153
|
+
self
|
|
136
154
|
end
|
|
137
155
|
|
|
138
156
|
def skip_to(index)
|
|
139
157
|
Lib.rb_player_skip_to(@ptr, Integer(index))
|
|
158
|
+
self
|
|
140
159
|
end
|
|
141
160
|
|
|
142
161
|
def seek_ms(ms)
|
|
143
162
|
Lib.rb_player_seek_ms(@ptr, Integer(ms))
|
|
163
|
+
self
|
|
144
164
|
end
|
|
145
165
|
|
|
146
166
|
# -- settings ---------------------------------------------------------
|
|
147
167
|
def set_volume(vol)
|
|
148
168
|
Lib.rb_player_set_volume(@ptr, Float(vol))
|
|
169
|
+
self
|
|
149
170
|
end
|
|
150
171
|
|
|
151
172
|
def volume
|
|
@@ -163,11 +184,173 @@ module RockboxFFI
|
|
|
163
184
|
@ptr, Integer(mode), Integer(fade_out_delay_ms), Integer(fade_out_duration_ms),
|
|
164
185
|
Integer(fade_in_delay_ms), Integer(fade_in_duration_ms), Integer(mix_mode)
|
|
165
186
|
)
|
|
187
|
+
self
|
|
166
188
|
end
|
|
167
189
|
|
|
168
190
|
# mode: see ReplayGainMode (OFF=0, TRACK=1, ALBUM=2).
|
|
169
191
|
def set_replaygain(mode, preamp_db, prevent_clipping)
|
|
170
192
|
Lib.rb_player_set_replaygain(@ptr, Integer(mode), Float(preamp_db), RockboxFFI.b(prevent_clipping))
|
|
193
|
+
self
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Enable/disable shuffle.
|
|
197
|
+
def set_shuffle(enabled)
|
|
198
|
+
Lib.rb_player_set_shuffle(@ptr, RockboxFFI.b(enabled))
|
|
199
|
+
self
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Whether shuffle is currently enabled.
|
|
203
|
+
def shuffle_enabled?
|
|
204
|
+
!Lib.rb_player_is_shuffle_enabled(@ptr).zero?
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Set the repeat mode (see RepeatMode: OFF=0, ONE=1, ALL=2).
|
|
208
|
+
def set_repeat(mode)
|
|
209
|
+
Lib.rb_player_set_repeat(@ptr, Integer(mode))
|
|
210
|
+
self
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# The current repeat mode as an Integer (see RepeatMode).
|
|
214
|
+
def repeat
|
|
215
|
+
Lib.rb_player_repeat(@ptr)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# -- DSP --------------------------------------------------------------
|
|
219
|
+
# Enable/disable the parametric equalizer.
|
|
220
|
+
def set_eq_enabled(enabled)
|
|
221
|
+
Lib.rb_player_set_eq_enabled(@ptr, RockboxFFI.b(enabled))
|
|
222
|
+
self
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Whether the parametric equalizer is currently enabled.
|
|
226
|
+
def eq_enabled?
|
|
227
|
+
!Lib.rb_player_is_eq_enabled(@ptr).zero?
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Configure one EQ band: +band+ index, +cutoff_hz+ center frequency,
|
|
231
|
+
# +q+ factor, +gain_db+ gain in dB.
|
|
232
|
+
def set_eq_band(band, cutoff_hz, q, gain_db)
|
|
233
|
+
Lib.rb_player_set_eq_band(@ptr, Integer(band), Integer(cutoff_hz), Float(q), Float(gain_db))
|
|
234
|
+
self
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Global EQ pre-cut in dB.
|
|
238
|
+
def set_eq_precut(db)
|
|
239
|
+
Lib.rb_player_set_eq_precut(@ptr, Float(db))
|
|
240
|
+
self
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Apply a built-in EQ preset (see EqPreset).
|
|
244
|
+
def set_eq_preset(preset)
|
|
245
|
+
Lib.rb_player_set_eq_preset(@ptr, Integer(preset))
|
|
246
|
+
self
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# Bass/treble tone controls with explicit cutoff frequencies.
|
|
250
|
+
def set_tone(bass_db, treble_db, bass_cutoff_hz, treble_cutoff_hz)
|
|
251
|
+
Lib.rb_player_set_tone(
|
|
252
|
+
@ptr, Integer(bass_db), Integer(treble_db),
|
|
253
|
+
Integer(bass_cutoff_hz), Integer(treble_cutoff_hz)
|
|
254
|
+
)
|
|
255
|
+
self
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
# Bass gain in dB.
|
|
259
|
+
def set_bass(bass_db)
|
|
260
|
+
Lib.rb_player_set_bass(@ptr, Integer(bass_db))
|
|
261
|
+
self
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Treble gain in dB.
|
|
265
|
+
def set_treble(treble_db)
|
|
266
|
+
Lib.rb_player_set_treble(@ptr, Integer(treble_db))
|
|
267
|
+
self
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Bass tone-control cutoff frequency in Hz.
|
|
271
|
+
def set_bass_cutoff(hz)
|
|
272
|
+
Lib.rb_player_set_bass_cutoff(@ptr, Integer(hz))
|
|
273
|
+
self
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# Treble tone-control cutoff frequency in Hz.
|
|
277
|
+
def set_treble_cutoff(hz)
|
|
278
|
+
Lib.rb_player_set_treble_cutoff(@ptr, Integer(hz))
|
|
279
|
+
self
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# Crossfeed for headphone listening. +mode+ (see CrossfeedMode: OFF=0,
|
|
283
|
+
# MEIER=1, CUSTOM=2), plus direct/cross/high-frequency gains and the
|
|
284
|
+
# high-frequency cutoff (Hz) used in CUSTOM mode.
|
|
285
|
+
def set_crossfeed(mode, direct_gain, cross_gain, hf_gain, hf_cutoff)
|
|
286
|
+
Lib.rb_player_set_crossfeed(
|
|
287
|
+
@ptr, Integer(mode), Integer(direct_gain), Integer(cross_gain),
|
|
288
|
+
Integer(hf_gain), Integer(hf_cutoff)
|
|
289
|
+
)
|
|
290
|
+
self
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# Bass enhancement: +strength+ and +precut+ (in dB).
|
|
294
|
+
def set_bass_enhancement(strength, precut)
|
|
295
|
+
Lib.rb_player_set_bass_enhancement(@ptr, Integer(strength), Integer(precut))
|
|
296
|
+
self
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
# Listening-fatigue reduction (treble roll-off): +strength+.
|
|
300
|
+
def set_fatigue_reduction(strength)
|
|
301
|
+
Lib.rb_player_set_fatigue_reduction(@ptr, Integer(strength))
|
|
302
|
+
self
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# Surround effect: delay (ms), balance, low/high cutoff frequencies (Hz).
|
|
306
|
+
def set_surround(delay_ms, balance, cutoff_low_hz, cutoff_high_hz)
|
|
307
|
+
Lib.rb_player_set_surround(
|
|
308
|
+
@ptr, Integer(delay_ms), Integer(balance),
|
|
309
|
+
Integer(cutoff_low_hz), Integer(cutoff_high_hz)
|
|
310
|
+
)
|
|
311
|
+
self
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
# Channel mode (see ChannelMode).
|
|
315
|
+
def set_channel_mode(mode)
|
|
316
|
+
Lib.rb_player_set_channel_mode(@ptr, Integer(mode))
|
|
317
|
+
self
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
# Stereo width as a percentage.
|
|
321
|
+
def set_stereo_width(percent)
|
|
322
|
+
Lib.rb_player_set_stereo_width(@ptr, Integer(percent))
|
|
323
|
+
self
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
# Dynamic-range compressor: threshold (dB), makeup gain, ratio, knee,
|
|
327
|
+
# attack (ms), release (ms).
|
|
328
|
+
def set_compressor(threshold_db, makeup_gain, ratio, knee, attack_ms, release_ms)
|
|
329
|
+
Lib.rb_player_set_compressor(
|
|
330
|
+
@ptr, Integer(threshold_db), Integer(makeup_gain), Integer(ratio),
|
|
331
|
+
Integer(knee), Integer(attack_ms), Integer(release_ms)
|
|
332
|
+
)
|
|
333
|
+
self
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
# Enable/disable output dithering.
|
|
337
|
+
def set_dither(enabled)
|
|
338
|
+
Lib.rb_player_set_dither(@ptr, RockboxFFI.b(enabled))
|
|
339
|
+
self
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# Pitch shift ratio.
|
|
343
|
+
def set_pitch(ratio)
|
|
344
|
+
Lib.rb_player_set_pitch(@ptr, Integer(ratio))
|
|
345
|
+
self
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
# A snapshot of the current DSP settings as a Hash with symbol keys.
|
|
349
|
+
def dsp_settings
|
|
350
|
+
s = RockboxFFI.take_string(Lib.rb_player_dsp_settings_json(@ptr))
|
|
351
|
+
raise "rb_player_dsp_settings_json returned NULL" if s.nil?
|
|
352
|
+
|
|
353
|
+
JSON.parse(s, symbolize_names: true)
|
|
171
354
|
end
|
|
172
355
|
|
|
173
356
|
# -- status -----------------------------------------------------------
|
data/lib/rockbox_ffi/version.rb
CHANGED