jack-ruby 0.1.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 +7 -0
- data/CHANGELOG.md +28 -0
- data/LICENSE.txt +21 -0
- data/README.md +205 -0
- data/Rakefile +8 -0
- data/examples/audio_passthrough.rb +31 -0
- data/examples/meter.rb +29 -0
- data/examples/midi_generator.rb +35 -0
- data/examples/midi_monitor.rb +29 -0
- data/examples/port_connector.rb +22 -0
- data/examples/ringbuffer_recorder.rb +35 -0
- data/examples/simple_client.rb +20 -0
- data/examples/sine_generator.rb +30 -0
- data/examples/transport_control.rb +21 -0
- data/lib/jack/audio_port.rb +19 -0
- data/lib/jack/callback_manager.rb +29 -0
- data/lib/jack/client.rb +371 -0
- data/lib/jack/error.rb +41 -0
- data/lib/jack/ffi/lib_jack.rb +306 -0
- data/lib/jack/ffi/structs.rb +74 -0
- data/lib/jack/ffi/types.rb +123 -0
- data/lib/jack/metadata.rb +50 -0
- data/lib/jack/midi/event.rb +82 -0
- data/lib/jack/midi_port.rb +71 -0
- data/lib/jack/port.rb +200 -0
- data/lib/jack/ring_buffer.rb +83 -0
- data/lib/jack/session.rb +63 -0
- data/lib/jack/transport.rb +138 -0
- data/lib/jack/uuid.rb +54 -0
- data/lib/jack/version.rb +5 -0
- data/lib/jack.rb +64 -0
- metadata +91 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rbconfig"
|
|
4
|
+
|
|
5
|
+
module Jack
|
|
6
|
+
module FFI
|
|
7
|
+
module LibJack
|
|
8
|
+
extend ::FFI::Library
|
|
9
|
+
|
|
10
|
+
LIBRARY_NAMES = case RbConfig::CONFIG["host_os"]
|
|
11
|
+
when /linux/
|
|
12
|
+
["libjack.so.0", "libjack.so"]
|
|
13
|
+
when /darwin/
|
|
14
|
+
["libjack.0.dylib", "libjack.dylib",
|
|
15
|
+
"/opt/homebrew/lib/libjack.0.dylib",
|
|
16
|
+
"/opt/homebrew/lib/libjack.dylib",
|
|
17
|
+
"/opt/homebrew/opt/jack/lib/libjack.0.dylib",
|
|
18
|
+
"/opt/homebrew/opt/jack/lib/libjack.dylib",
|
|
19
|
+
"/usr/local/opt/jack/lib/libjack.0.dylib",
|
|
20
|
+
"/usr/local/lib/libjack.dylib",
|
|
21
|
+
"/usr/local/opt/jack/lib/libjack.dylib",
|
|
22
|
+
"/usr/local/lib/libjack.0.dylib"]
|
|
23
|
+
when /mswin|mingw/
|
|
24
|
+
["libjack64.dll", "libjack.dll"]
|
|
25
|
+
else
|
|
26
|
+
["libjack.so.0", "libjack.so"]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.load_library
|
|
30
|
+
library_names = ENV["JACK_LIB_PATH"] ? [ENV["JACK_LIB_PATH"]] : LIBRARY_NAMES
|
|
31
|
+
last_error = nil
|
|
32
|
+
|
|
33
|
+
library_names.each do |library_name|
|
|
34
|
+
ffi_lib library_name
|
|
35
|
+
return
|
|
36
|
+
rescue LoadError => e
|
|
37
|
+
last_error = e
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
raise last_error if last_error
|
|
41
|
+
rescue LoadError => e
|
|
42
|
+
raise Jack::Error,
|
|
43
|
+
"libjack not found. Please install JACK: #{e.message}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.function_available?(name)
|
|
47
|
+
ffi_libraries.any? do |lib|
|
|
48
|
+
!lib.find_function(name.to_s).nil?
|
|
49
|
+
end
|
|
50
|
+
rescue StandardError
|
|
51
|
+
false
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.attach_optional(name, args, ret)
|
|
55
|
+
if function_available?(name)
|
|
56
|
+
attach_function name, args, ret
|
|
57
|
+
true
|
|
58
|
+
else
|
|
59
|
+
define_singleton_method(name) { |*| raise Jack::NotImplementedError, "#{name} is not available" }
|
|
60
|
+
false
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
include Types
|
|
65
|
+
Types.apply_to(self)
|
|
66
|
+
|
|
67
|
+
begin
|
|
68
|
+
load_library
|
|
69
|
+
@library_loaded = true
|
|
70
|
+
@load_error = nil
|
|
71
|
+
rescue Jack::Error => e
|
|
72
|
+
@library_loaded = false
|
|
73
|
+
@load_error = e
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def self.library_loaded?
|
|
77
|
+
@library_loaded
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def self.ensure_loaded!
|
|
81
|
+
return if @library_loaded
|
|
82
|
+
|
|
83
|
+
raise(@load_error || Jack::Error.new("libjack not found. Please install JACK or set JACK_LIB_PATH"))
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def self.method_missing(name, *args, &block)
|
|
87
|
+
if name.to_s.start_with?("jack_") && !@library_loaded
|
|
88
|
+
ensure_loaded!
|
|
89
|
+
else
|
|
90
|
+
super
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def self.respond_to_missing?(name, include_private = false)
|
|
95
|
+
(name.to_s.start_with?("jack_") && !@library_loaded) || super
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
if @library_loaded # rubocop:disable Style/IfUnlessModifier
|
|
99
|
+
|
|
100
|
+
# === Client management (jack.h) ===
|
|
101
|
+
attach_function :jack_client_open, [:string, :int, :pointer, :varargs], :jack_client_t
|
|
102
|
+
attach_optional :jack_client_new, [:string], :jack_client_t
|
|
103
|
+
attach_function :jack_client_close, [:jack_client_t], :int
|
|
104
|
+
attach_function :jack_client_name_size, [], :int
|
|
105
|
+
attach_optional :jack_get_version, [:pointer, :pointer, :pointer, :pointer], :void
|
|
106
|
+
attach_optional :jack_get_version_string, [], :string
|
|
107
|
+
attach_function :jack_get_client_name, [:jack_client_t], :string
|
|
108
|
+
attach_function :jack_get_uuid_for_client_name, [:jack_client_t, :string], :string
|
|
109
|
+
attach_function :jack_get_client_name_by_uuid, [:jack_client_t, :string], :string
|
|
110
|
+
attach_function :jack_activate, [:jack_client_t], :int
|
|
111
|
+
attach_function :jack_deactivate, [:jack_client_t], :int
|
|
112
|
+
attach_optional :jack_get_client_pid, [:string], :int
|
|
113
|
+
attach_function :jack_client_thread_id, [:jack_client_t], :ulong
|
|
114
|
+
attach_function :jack_is_realtime, [:jack_client_t], :int
|
|
115
|
+
attach_optional :jack_set_error_function, [:JackMessageCallback], :void
|
|
116
|
+
attach_optional :jack_set_info_function, [:JackMessageCallback], :void
|
|
117
|
+
|
|
118
|
+
# === Callback registration (jack.h) ===
|
|
119
|
+
attach_function :jack_set_process_callback, [:jack_client_t, :JackProcessCallback, :pointer], :int
|
|
120
|
+
attach_function :jack_set_thread_init_callback, [:jack_client_t, :JackThreadInitCallback, :pointer], :int
|
|
121
|
+
attach_function :jack_on_shutdown, [:jack_client_t, :JackShutdownCallback, :pointer], :void
|
|
122
|
+
attach_function :jack_on_info_shutdown, [:jack_client_t, :JackInfoShutdownCallback, :pointer], :void
|
|
123
|
+
attach_function :jack_set_freewheel_callback, [:jack_client_t, :JackFreewheelCallback, :pointer], :int
|
|
124
|
+
attach_function :jack_set_buffer_size_callback, [:jack_client_t, :JackBufferSizeCallback, :pointer], :int
|
|
125
|
+
attach_function :jack_set_sample_rate_callback, [:jack_client_t, :JackSampleRateCallback, :pointer], :int
|
|
126
|
+
attach_function :jack_set_client_registration_callback, [:jack_client_t, :JackClientRegistrationCallback, :pointer], :int
|
|
127
|
+
attach_function :jack_set_port_registration_callback, [:jack_client_t, :JackPortRegistrationCallback, :pointer], :int
|
|
128
|
+
attach_optional :jack_set_port_rename_callback, [:jack_client_t, :JackPortRenameCallback, :pointer], :int
|
|
129
|
+
attach_function :jack_set_port_connect_callback, [:jack_client_t, :JackPortConnectCallback, :pointer], :int
|
|
130
|
+
attach_function :jack_set_graph_order_callback, [:jack_client_t, :JackGraphOrderCallback, :pointer], :int
|
|
131
|
+
attach_function :jack_set_xrun_callback, [:jack_client_t, :JackXRunCallback, :pointer], :int
|
|
132
|
+
attach_function :jack_set_latency_callback, [:jack_client_t, :JackLatencyCallback, :pointer], :int
|
|
133
|
+
|
|
134
|
+
# === Non-Callback API (jack.h) ===
|
|
135
|
+
attach_function :jack_set_process_thread, [:jack_client_t, :JackThreadCallback, :pointer], :int
|
|
136
|
+
attach_optional :jack_thread_wait, [:jack_client_t, :int], :uint32
|
|
137
|
+
attach_function :jack_cycle_wait, [:jack_client_t], :uint32
|
|
138
|
+
attach_function :jack_cycle_signal, [:jack_client_t, :int], :void
|
|
139
|
+
|
|
140
|
+
# === Server control (jack.h) ===
|
|
141
|
+
attach_optional :jack_engine_takeover_timebase, [:jack_client_t], :int
|
|
142
|
+
attach_function :jack_set_freewheel, [:jack_client_t, :int], :int
|
|
143
|
+
attach_function :jack_set_buffer_size, [:jack_client_t, :uint32], :int
|
|
144
|
+
attach_function :jack_get_sample_rate, [:jack_client_t], :uint32
|
|
145
|
+
attach_function :jack_get_buffer_size, [:jack_client_t], :uint32
|
|
146
|
+
attach_function :jack_cpu_load, [:jack_client_t], :float
|
|
147
|
+
|
|
148
|
+
# === Port functions (jack.h) ===
|
|
149
|
+
attach_function :jack_port_register, [:jack_client_t, :string, :string, :ulong, :ulong], :jack_port_t
|
|
150
|
+
attach_function :jack_port_unregister, [:jack_client_t, :jack_port_t], :int
|
|
151
|
+
attach_function :jack_port_get_buffer, [:jack_port_t, :uint32], :pointer
|
|
152
|
+
attach_function :jack_port_uuid, [:jack_port_t], :uint64
|
|
153
|
+
attach_function :jack_port_name, [:jack_port_t], :string
|
|
154
|
+
attach_function :jack_port_short_name, [:jack_port_t], :string
|
|
155
|
+
attach_function :jack_port_flags, [:jack_port_t], :int
|
|
156
|
+
attach_function :jack_port_type, [:jack_port_t], :string
|
|
157
|
+
attach_function :jack_port_type_id, [:jack_port_t], :uint32
|
|
158
|
+
attach_function :jack_port_is_mine, [:jack_client_t, :jack_port_t], :int
|
|
159
|
+
attach_function :jack_port_connected, [:jack_port_t], :int
|
|
160
|
+
attach_function :jack_port_connected_to, [:jack_port_t, :string], :int
|
|
161
|
+
attach_function :jack_port_get_connections, [:jack_port_t], :pointer
|
|
162
|
+
attach_function :jack_port_get_all_connections, [:jack_client_t, :jack_port_t], :pointer
|
|
163
|
+
attach_optional :jack_port_tie, [:jack_port_t, :jack_port_t], :int
|
|
164
|
+
attach_optional :jack_port_untie, [:jack_port_t], :int
|
|
165
|
+
attach_optional :jack_port_rename, [:jack_client_t, :jack_port_t, :string], :int
|
|
166
|
+
attach_optional :jack_port_set_name, [:jack_port_t, :string], :int
|
|
167
|
+
attach_function :jack_port_set_alias, [:jack_port_t, :string], :int
|
|
168
|
+
attach_function :jack_port_unset_alias, [:jack_port_t, :string], :int
|
|
169
|
+
attach_function :jack_port_get_aliases, [:jack_port_t, :pointer], :int
|
|
170
|
+
attach_function :jack_port_request_monitor, [:jack_port_t, :int], :int
|
|
171
|
+
attach_function :jack_port_request_monitor_by_name, [:jack_client_t, :string, :int], :int
|
|
172
|
+
attach_function :jack_port_ensure_monitor, [:jack_port_t, :int], :int
|
|
173
|
+
attach_function :jack_port_monitoring_input, [:jack_port_t], :int
|
|
174
|
+
attach_function :jack_connect, [:jack_client_t, :string, :string], :int
|
|
175
|
+
attach_function :jack_disconnect, [:jack_client_t, :string, :string], :int
|
|
176
|
+
attach_function :jack_port_disconnect, [:jack_client_t, :jack_port_t], :int
|
|
177
|
+
attach_function :jack_port_name_size, [], :int
|
|
178
|
+
attach_function :jack_port_type_size, [], :int
|
|
179
|
+
attach_function :jack_port_type_get_buffer_size, [:jack_client_t, :string], :size_t
|
|
180
|
+
|
|
181
|
+
# === Latency (jack.h) ===
|
|
182
|
+
attach_optional :jack_port_set_latency, [:jack_port_t, :uint32], :void
|
|
183
|
+
attach_function :jack_port_set_latency_range, [:jack_port_t, :int, :pointer], :void
|
|
184
|
+
attach_optional :jack_port_get_latency, [:jack_port_t], :uint32
|
|
185
|
+
attach_function :jack_port_get_latency_range, [:jack_port_t, :int, :pointer], :void
|
|
186
|
+
attach_optional :jack_port_get_total_latency, [:jack_client_t, :jack_port_t], :uint32
|
|
187
|
+
attach_function :jack_recompute_total_latencies, [:jack_client_t], :int
|
|
188
|
+
attach_optional :jack_recompute_total_latency, [:jack_client_t, :jack_port_t], :int
|
|
189
|
+
|
|
190
|
+
# === Port searching (jack.h) ===
|
|
191
|
+
attach_function :jack_get_ports, [:jack_client_t, :string, :string, :ulong], :pointer
|
|
192
|
+
attach_function :jack_port_by_name, [:jack_client_t, :string], :jack_port_t
|
|
193
|
+
attach_function :jack_port_by_id, [:jack_client_t, :uint32], :jack_port_t
|
|
194
|
+
|
|
195
|
+
# === Time functions (jack.h) ===
|
|
196
|
+
attach_function :jack_frames_since_cycle_start, [:jack_client_t], :uint32
|
|
197
|
+
attach_function :jack_frame_time, [:jack_client_t], :uint32
|
|
198
|
+
attach_function :jack_last_frame_time, [:jack_client_t], :uint32
|
|
199
|
+
attach_function :jack_get_cycle_times, [:jack_client_t, :pointer, :pointer, :pointer, :pointer], :int
|
|
200
|
+
attach_function :jack_frames_to_time, [:jack_client_t, :uint32], :uint64
|
|
201
|
+
attach_function :jack_time_to_frames, [:jack_client_t, :uint64], :uint32
|
|
202
|
+
attach_function :jack_get_time, [], :uint64
|
|
203
|
+
|
|
204
|
+
# === Memory (jack.h) ===
|
|
205
|
+
attach_function :jack_free, [:pointer], :void
|
|
206
|
+
|
|
207
|
+
# === MIDI API (midiport.h) ===
|
|
208
|
+
attach_function :jack_midi_get_event_count, [:pointer], :uint32
|
|
209
|
+
attach_function :jack_midi_event_get, [:pointer, :pointer, :uint32], :int
|
|
210
|
+
attach_function :jack_midi_clear_buffer, [:pointer], :void
|
|
211
|
+
attach_optional :jack_midi_reset_buffer, [:pointer], :void
|
|
212
|
+
attach_function :jack_midi_max_event_size, [:pointer], :size_t
|
|
213
|
+
attach_function :jack_midi_event_reserve, [:pointer, :uint32, :size_t], :pointer
|
|
214
|
+
attach_function :jack_midi_event_write, [:pointer, :uint32, :pointer, :size_t], :int
|
|
215
|
+
attach_function :jack_midi_get_lost_event_count, [:pointer], :uint32
|
|
216
|
+
|
|
217
|
+
# === Transport API (transport.h) ===
|
|
218
|
+
attach_function :jack_release_timebase, [:jack_client_t], :int
|
|
219
|
+
attach_function :jack_set_sync_callback, [:jack_client_t, :JackSyncCallback, :pointer], :int
|
|
220
|
+
attach_function :jack_set_sync_timeout, [:jack_client_t, :uint64], :int
|
|
221
|
+
attach_function :jack_set_timebase_callback, [:jack_client_t, :int, :JackTimebaseCallback, :pointer], :int
|
|
222
|
+
attach_function :jack_transport_locate, [:jack_client_t, :uint32], :int
|
|
223
|
+
attach_function :jack_transport_query, [:jack_client_t, :pointer], :int
|
|
224
|
+
attach_optional :jack_get_transport_info, [:jack_client_t, :pointer], :void
|
|
225
|
+
attach_function :jack_get_current_transport_frame, [:jack_client_t], :uint32
|
|
226
|
+
attach_optional :jack_set_transport_info, [:jack_client_t, :pointer], :void
|
|
227
|
+
attach_function :jack_transport_reposition, [:jack_client_t, :pointer], :int
|
|
228
|
+
attach_function :jack_transport_start, [:jack_client_t], :void
|
|
229
|
+
attach_function :jack_transport_stop, [:jack_client_t], :void
|
|
230
|
+
|
|
231
|
+
# === Session API (session.h) ===
|
|
232
|
+
attach_optional :jack_set_session_callback, [:jack_client_t, :JackSessionCallback, :pointer], :int
|
|
233
|
+
attach_optional :jack_session_reply, [:jack_client_t, :pointer], :int
|
|
234
|
+
attach_optional :jack_session_event_free, [:pointer], :void
|
|
235
|
+
attach_function :jack_client_get_uuid, [:jack_client_t], :string
|
|
236
|
+
attach_optional :jack_session_notify, [:jack_client_t, :string, :int, :string], :pointer
|
|
237
|
+
attach_optional :jack_session_commands_free, [:pointer], :void
|
|
238
|
+
attach_optional :jack_reserve_client_name, [:jack_client_t, :string, :string], :int
|
|
239
|
+
attach_optional :jack_client_has_session_callback, [:jack_client_t, :string], :int
|
|
240
|
+
|
|
241
|
+
# === Internal client API (intclient.h) ===
|
|
242
|
+
attach_optional :jack_get_internal_client_name, [:jack_client_t, :jack_intclient_t], :pointer
|
|
243
|
+
attach_optional :jack_internal_client_handle, [:jack_client_t, :string, :pointer], :jack_intclient_t
|
|
244
|
+
attach_optional :jack_internal_client_load, [:jack_client_t, :string, :int, :pointer, :varargs], :jack_intclient_t
|
|
245
|
+
attach_optional :jack_internal_client_unload, [:jack_client_t, :jack_intclient_t], :int
|
|
246
|
+
attach_optional :jack_internal_client_new, [:string, :string, :string], :int
|
|
247
|
+
attach_optional :jack_internal_client_close, [:string], :void
|
|
248
|
+
|
|
249
|
+
# === RingBuffer API (ringbuffer.h) ===
|
|
250
|
+
attach_function :jack_ringbuffer_create, [:size_t], :pointer
|
|
251
|
+
attach_function :jack_ringbuffer_free, [:pointer], :void
|
|
252
|
+
attach_function :jack_ringbuffer_get_read_vector, [:pointer, :pointer], :void
|
|
253
|
+
attach_function :jack_ringbuffer_get_write_vector, [:pointer, :pointer], :void
|
|
254
|
+
attach_function :jack_ringbuffer_read, [:pointer, :pointer, :size_t], :size_t
|
|
255
|
+
attach_function :jack_ringbuffer_peek, [:pointer, :pointer, :size_t], :size_t
|
|
256
|
+
attach_function :jack_ringbuffer_read_advance, [:pointer, :size_t], :void
|
|
257
|
+
attach_function :jack_ringbuffer_read_space, [:pointer], :size_t
|
|
258
|
+
attach_function :jack_ringbuffer_mlock, [:pointer], :int
|
|
259
|
+
attach_function :jack_ringbuffer_reset, [:pointer], :void
|
|
260
|
+
attach_optional :jack_ringbuffer_reset_size, [:pointer, :size_t], :void
|
|
261
|
+
attach_function :jack_ringbuffer_write, [:pointer, :pointer, :size_t], :size_t
|
|
262
|
+
attach_function :jack_ringbuffer_write_advance, [:pointer, :size_t], :void
|
|
263
|
+
attach_function :jack_ringbuffer_write_space, [:pointer], :size_t
|
|
264
|
+
|
|
265
|
+
# === Metadata API (metadata.h) - JACK2 only ===
|
|
266
|
+
attach_optional :jack_set_property, [:jack_client_t, :uint64, :string, :string, :string], :int
|
|
267
|
+
attach_optional :jack_get_property, [:uint64, :string, :pointer, :pointer], :int
|
|
268
|
+
attach_optional :jack_free_description, [:pointer, :int], :void
|
|
269
|
+
attach_optional :jack_get_properties, [:uint64, :pointer], :int
|
|
270
|
+
attach_optional :jack_get_all_properties, [:pointer], :int
|
|
271
|
+
attach_optional :jack_remove_property, [:jack_client_t, :uint64, :string], :int
|
|
272
|
+
attach_optional :jack_remove_properties, [:jack_client_t, :uint64], :int
|
|
273
|
+
attach_optional :jack_remove_all_properties, [:jack_client_t], :int
|
|
274
|
+
attach_optional :jack_set_property_change_callback, [:jack_client_t, :JackPropertyChangeCallback, :pointer], :int
|
|
275
|
+
|
|
276
|
+
# === Statistics API (statistics.h) ===
|
|
277
|
+
attach_optional :jack_get_max_delayed_usecs, [:jack_client_t], :float
|
|
278
|
+
attach_optional :jack_get_xrun_delayed_usecs, [:jack_client_t], :float
|
|
279
|
+
attach_optional :jack_reset_max_delayed_usecs, [:jack_client_t], :void
|
|
280
|
+
attach_optional :jack_max_cpu_load, [:jack_client_t], :float
|
|
281
|
+
|
|
282
|
+
# === Thread API (thread.h) ===
|
|
283
|
+
attach_optional :jack_client_real_time_priority, [:jack_client_t], :int
|
|
284
|
+
attach_optional :jack_client_max_real_time_priority, [:jack_client_t], :int
|
|
285
|
+
attach_optional :jack_acquire_real_time_scheduling, [:ulong, :int], :int
|
|
286
|
+
attach_optional :jack_drop_real_time_scheduling, [:ulong], :int
|
|
287
|
+
attach_optional :jack_client_create_thread, [:jack_client_t, :pointer, :int, :int, :JackThreadCallback, :pointer], :int
|
|
288
|
+
attach_optional :jack_client_stop_thread, [:jack_client_t, :ulong], :int
|
|
289
|
+
attach_optional :jack_client_kill_thread, [:jack_client_t, :ulong], :int
|
|
290
|
+
attach_optional :jack_set_thread_creator, [:pointer], :void
|
|
291
|
+
|
|
292
|
+
# === UUID API (uuid.h) ===
|
|
293
|
+
attach_function :jack_client_uuid_generate, [], :jack_uuid_t
|
|
294
|
+
attach_function :jack_port_uuid_generate, [:uint32], :jack_uuid_t
|
|
295
|
+
attach_function :jack_uuid_to_index, [:jack_uuid_t], :uint32
|
|
296
|
+
attach_function :jack_uuid_compare, [:jack_uuid_t, :jack_uuid_t], :int
|
|
297
|
+
attach_function :jack_uuid_copy, [:pointer, :jack_uuid_t], :void
|
|
298
|
+
attach_function :jack_uuid_clear, [:pointer], :void
|
|
299
|
+
attach_function :jack_uuid_parse, [:string, :pointer], :int
|
|
300
|
+
attach_function :jack_uuid_unparse, [:jack_uuid_t, :pointer], :void
|
|
301
|
+
attach_function :jack_uuid_empty, [:jack_uuid_t], :int
|
|
302
|
+
|
|
303
|
+
end # if @library_loaded
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jack
|
|
4
|
+
module FFI
|
|
5
|
+
module Structs
|
|
6
|
+
class JackLatencyRange < ::FFI::Struct
|
|
7
|
+
layout :min, :uint32,
|
|
8
|
+
:max, :uint32
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class JackPosition < ::FFI::Struct
|
|
12
|
+
layout :unique_1, :uint64,
|
|
13
|
+
:usecs, :uint64,
|
|
14
|
+
:frame_rate, :uint32,
|
|
15
|
+
:frame, :uint32,
|
|
16
|
+
:valid, :int,
|
|
17
|
+
:bar, :int32,
|
|
18
|
+
:beat, :int32,
|
|
19
|
+
:tick, :int32,
|
|
20
|
+
:bar_start_tick, :double,
|
|
21
|
+
:beats_per_bar, :float,
|
|
22
|
+
:beat_type, :float,
|
|
23
|
+
:ticks_per_beat, :double,
|
|
24
|
+
:beats_per_minute, :double,
|
|
25
|
+
:frame_time, :double,
|
|
26
|
+
:next_time, :double,
|
|
27
|
+
:bbt_offset, :uint32,
|
|
28
|
+
:audio_frames_per_video_frame, :float,
|
|
29
|
+
:video_offset, :uint32,
|
|
30
|
+
:tick_double, :double,
|
|
31
|
+
:padding, [:int32, 5],
|
|
32
|
+
:unique_2, :uint64
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class JackTransportInfo < ::FFI::Struct
|
|
36
|
+
layout :frame_rate, :uint32,
|
|
37
|
+
:usecs, :uint64,
|
|
38
|
+
:valid, :int,
|
|
39
|
+
:transport_state, :int,
|
|
40
|
+
:frame, :uint32,
|
|
41
|
+
:loop_start, :uint32,
|
|
42
|
+
:loop_end, :uint32,
|
|
43
|
+
:smpte_offset, :long,
|
|
44
|
+
:smpte_frame_rate, :float,
|
|
45
|
+
:bar, :int,
|
|
46
|
+
:beat, :int,
|
|
47
|
+
:tick, :int,
|
|
48
|
+
:bar_start_tick, :double,
|
|
49
|
+
:beats_per_bar, :float,
|
|
50
|
+
:beat_type, :float,
|
|
51
|
+
:ticks_per_beat, :double,
|
|
52
|
+
:beats_per_minute, :double
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class JackMidiEvent < ::FFI::Struct
|
|
56
|
+
layout :time, :uint32,
|
|
57
|
+
:size, :size_t,
|
|
58
|
+
:buffer, :pointer
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class JackSessionCommand < ::FFI::Struct
|
|
62
|
+
layout :uuid, :string,
|
|
63
|
+
:name, :string,
|
|
64
|
+
:command, :string,
|
|
65
|
+
:flags, :int
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class RingBufferData < ::FFI::Struct
|
|
69
|
+
layout :buf, :pointer,
|
|
70
|
+
:len, :size_t
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jack
|
|
4
|
+
module FFI
|
|
5
|
+
module Types
|
|
6
|
+
TYPEDEFS = {
|
|
7
|
+
jack_nframes_t: :uint32,
|
|
8
|
+
jack_time_t: :uint64,
|
|
9
|
+
jack_uuid_t: :uint64,
|
|
10
|
+
jack_client_t: :pointer,
|
|
11
|
+
jack_port_t: :pointer,
|
|
12
|
+
jack_intclient_t: :uint64,
|
|
13
|
+
jack_midi_data_t: :uchar,
|
|
14
|
+
jack_default_audio_sample_t: :float
|
|
15
|
+
}.freeze
|
|
16
|
+
|
|
17
|
+
LATENCY_CALLBACK_MODE = [
|
|
18
|
+
:JackCaptureLatency, 0,
|
|
19
|
+
:JackPlaybackLatency, 1
|
|
20
|
+
].freeze
|
|
21
|
+
|
|
22
|
+
TRANSPORT_STATE = [
|
|
23
|
+
:JackTransportStopped, 0,
|
|
24
|
+
:JackTransportRolling, 1,
|
|
25
|
+
:JackTransportLooping, 2,
|
|
26
|
+
:JackTransportStarting, 3
|
|
27
|
+
].freeze
|
|
28
|
+
|
|
29
|
+
SESSION_EVENT_TYPE = [
|
|
30
|
+
:JackSessionSave, 1,
|
|
31
|
+
:JackSessionSaveAndQuit, 2,
|
|
32
|
+
:JackSessionSaveTemplate, 3
|
|
33
|
+
].freeze
|
|
34
|
+
|
|
35
|
+
CALLBACKS = {
|
|
36
|
+
JackProcessCallback: [[:jack_nframes_t, :pointer], :int],
|
|
37
|
+
JackShutdownCallback: [[:pointer], :void],
|
|
38
|
+
JackInfoShutdownCallback: [[:int, :string, :pointer], :void],
|
|
39
|
+
JackSampleRateCallback: [[:jack_nframes_t, :pointer], :int],
|
|
40
|
+
JackBufferSizeCallback: [[:jack_nframes_t, :pointer], :int],
|
|
41
|
+
JackXRunCallback: [[:pointer], :int],
|
|
42
|
+
JackPortRegistrationCallback: [[:uint32, :int, :pointer], :void],
|
|
43
|
+
JackClientRegistrationCallback: [[:string, :int, :pointer], :void],
|
|
44
|
+
JackPortConnectCallback: [[:uint32, :uint32, :int, :pointer], :void],
|
|
45
|
+
JackPortRenameCallback: [[:uint32, :string, :string, :pointer], :int],
|
|
46
|
+
JackFreewheelCallback: [[:int, :pointer], :void],
|
|
47
|
+
JackGraphOrderCallback: [[:pointer], :int],
|
|
48
|
+
JackThreadInitCallback: [[:pointer], :void],
|
|
49
|
+
JackLatencyCallback: [[:jack_latency_callback_mode_t, :pointer], :void],
|
|
50
|
+
JackThreadCallback: [[:pointer], :pointer],
|
|
51
|
+
JackSyncCallback: [[:jack_transport_state_t, :pointer, :pointer], :int],
|
|
52
|
+
JackTimebaseCallback: [[:jack_transport_state_t, :jack_nframes_t, :pointer, :int, :pointer], :void],
|
|
53
|
+
JackSessionCallback: [[:pointer, :pointer], :void],
|
|
54
|
+
JackPropertyChangeCallback: [[:jack_uuid_t, :string, :int, :pointer], :void],
|
|
55
|
+
JackMessageCallback: [[:string], :void]
|
|
56
|
+
}.freeze
|
|
57
|
+
|
|
58
|
+
def self.apply_to(target)
|
|
59
|
+
TYPEDEFS.each do |name, native_type|
|
|
60
|
+
target.typedef(native_type, name)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
target.enum(:jack_latency_callback_mode_t, LATENCY_CALLBACK_MODE)
|
|
64
|
+
target.enum(:jack_transport_state_t, TRANSPORT_STATE)
|
|
65
|
+
target.enum(:jack_session_event_type_t, SESSION_EVENT_TYPE)
|
|
66
|
+
|
|
67
|
+
CALLBACKS.each do |name, (params, return_type)|
|
|
68
|
+
target.callback(name, params, return_type)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
JACK_UUID_SIZE = 36
|
|
73
|
+
JACK_UUID_STRING_SIZE = JACK_UUID_SIZE + 1
|
|
74
|
+
|
|
75
|
+
# jack_options_t (bit flags)
|
|
76
|
+
JackNullOption = 0x00
|
|
77
|
+
JackNoStartServer = 0x01
|
|
78
|
+
JackUseExactName = 0x02
|
|
79
|
+
JackServerName = 0x04
|
|
80
|
+
JackLoadName = 0x08
|
|
81
|
+
JackLoadInit = 0x10
|
|
82
|
+
JackSessionID = 0x20
|
|
83
|
+
|
|
84
|
+
# jack_status_t (bit flags)
|
|
85
|
+
JackFailure = 0x01
|
|
86
|
+
JackInvalidOption = 0x02
|
|
87
|
+
JackNameNotUnique = 0x04
|
|
88
|
+
JackServerStarted = 0x08
|
|
89
|
+
JackServerFailed = 0x10
|
|
90
|
+
JackServerError = 0x20
|
|
91
|
+
JackNoSuchClient = 0x40
|
|
92
|
+
JackLoadFailure = 0x80
|
|
93
|
+
JackInitFailure = 0x100
|
|
94
|
+
JackShmFailure = 0x200
|
|
95
|
+
JackVersionError = 0x400
|
|
96
|
+
JackBackendError = 0x800
|
|
97
|
+
JackClientZombie = 0x1000
|
|
98
|
+
|
|
99
|
+
# JackPortFlags
|
|
100
|
+
JackPortIsInput = 0x1
|
|
101
|
+
JackPortIsOutput = 0x2
|
|
102
|
+
JackPortIsPhysical = 0x4
|
|
103
|
+
JackPortCanMonitor = 0x8
|
|
104
|
+
JackPortIsTerminal = 0x10
|
|
105
|
+
|
|
106
|
+
# jack_position_bits_t
|
|
107
|
+
JackPositionBBT = 0x10
|
|
108
|
+
JackPositionTimecode = 0x20
|
|
109
|
+
JackBBTFrameOffset = 0x40
|
|
110
|
+
JackAudioVideoRatio = 0x80
|
|
111
|
+
JackVideoFrameOffset = 0x100
|
|
112
|
+
JackTickDouble = 0x200
|
|
113
|
+
|
|
114
|
+
# jack_session_flags_t
|
|
115
|
+
JackSessionSaveError = 0x01
|
|
116
|
+
JackSessionNeedTerminal = 0x02
|
|
117
|
+
|
|
118
|
+
# Port type constants
|
|
119
|
+
JACK_DEFAULT_AUDIO_TYPE = "32 bit float mono audio"
|
|
120
|
+
JACK_DEFAULT_MIDI_TYPE = "8 bit raw midi"
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jack
|
|
4
|
+
class Metadata
|
|
5
|
+
attr_reader :client
|
|
6
|
+
|
|
7
|
+
def initialize(client)
|
|
8
|
+
@client = client
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def set_property(subject, key, value, type = "")
|
|
12
|
+
result = FFI::LibJack.jack_set_property(@client.handle, subject, key, value, type)
|
|
13
|
+
raise Error, "Failed to set property" unless result.zero?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def get_property(subject, key)
|
|
17
|
+
value_ptr = ::FFI::MemoryPointer.new(:pointer)
|
|
18
|
+
type_ptr = ::FFI::MemoryPointer.new(:pointer)
|
|
19
|
+
result = FFI::LibJack.jack_get_property(subject, key, value_ptr, type_ptr)
|
|
20
|
+
return nil unless result.zero?
|
|
21
|
+
|
|
22
|
+
value = value_ptr.read_pointer.read_string
|
|
23
|
+
type = type_ptr.read_pointer.read_string
|
|
24
|
+
{ value: value, type: type }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def remove_property(subject, key)
|
|
28
|
+
result = FFI::LibJack.jack_remove_property(@client.handle, subject, key)
|
|
29
|
+
raise Error, "Failed to remove property" unless result.zero?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def remove_properties(subject)
|
|
33
|
+
result = FFI::LibJack.jack_remove_properties(@client.handle, subject)
|
|
34
|
+
raise Error, "Failed to remove properties" unless result.zero?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def remove_all_properties
|
|
38
|
+
result = FFI::LibJack.jack_remove_all_properties(@client.handle)
|
|
39
|
+
raise Error, "Failed to remove all properties" unless result.zero?
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def on_property_change(&block)
|
|
43
|
+
ffi_proc = proc { |subject, key, change, _arg|
|
|
44
|
+
block.call(subject, key, change)
|
|
45
|
+
}
|
|
46
|
+
@client.callback_manager.register(:property_change, block, ffi_proc)
|
|
47
|
+
FFI::LibJack.jack_set_property_change_callback(@client.handle, ffi_proc, nil)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jack
|
|
4
|
+
module Midi
|
|
5
|
+
class Event
|
|
6
|
+
attr_reader :time, :data
|
|
7
|
+
|
|
8
|
+
def initialize(time, data)
|
|
9
|
+
@time = time
|
|
10
|
+
@data = data.is_a?(Array) ? data : data.bytes
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def status
|
|
14
|
+
@data[0]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def channel
|
|
18
|
+
return nil if sysex?
|
|
19
|
+
|
|
20
|
+
status & 0x0F
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def note_on?
|
|
24
|
+
(status & 0xF0) == 0x90 && velocity > 0
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def note_off?
|
|
28
|
+
(status & 0xF0) == 0x80 || ((status & 0xF0) == 0x90 && velocity.zero?)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def control_change?
|
|
32
|
+
(status & 0xF0) == 0xB0
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def program_change?
|
|
36
|
+
(status & 0xF0) == 0xC0
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def pitch_bend?
|
|
40
|
+
(status & 0xF0) == 0xE0
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def aftertouch?
|
|
44
|
+
(status & 0xF0) == 0xA0
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def channel_pressure?
|
|
48
|
+
(status & 0xF0) == 0xD0
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def sysex?
|
|
52
|
+
status == 0xF0
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def note
|
|
56
|
+
@data[1]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def velocity
|
|
60
|
+
@data[2] || 0
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def controller
|
|
64
|
+
@data[1]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def cc_value
|
|
68
|
+
@data[2]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def pitch_bend_value
|
|
72
|
+
return nil unless pitch_bend?
|
|
73
|
+
|
|
74
|
+
((@data[2] << 7) | @data[1]) - 8192
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def to_bytes
|
|
78
|
+
@data.dup
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|