Skip to content

Commit 3233a0c

Browse files
committed
Switch to CFFI out-of-line ABI mode
1 parent 951eac1 commit 3233a0c

File tree

7 files changed

+303
-278
lines changed

7 files changed

+303
-278
lines changed

CONTRIBUTING.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ If you prefer, you can also replace the last command with::
2424

2525
... where ``-e`` stands for ``--editable``.
2626

27+
Whenever the file ``jack_build.py`` changes (either because you edited it or it
28+
was updated by pulling from Github or switching branches), you have to run the
29+
last command again.
30+
2731
If you make changes to the documentation, you can locally re-create the HTML
2832
pages using Sphinx_.
2933
You can install it and a few other necessary packages with::

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
include LICENSE
2+
include jack_build.py
23
include *.rst
34
include doc/requirements.txt
45
recursive-include doc *.rst *.py

doc/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
sys.path.insert(0, os.path.abspath('.'))
2424

2525
# Fake import to avoid actually loading CFFI and the JACK library
26-
import fake_cffi
27-
sys.modules['cffi'] = sys.modules['fake_cffi']
26+
import fake__jack
27+
sys.modules['_jack'] = sys.modules['fake__jack']
2828

2929
# -- General configuration ------------------------------------------------
3030

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
"""Mock module for Sphinx autodoc."""
22

33

4-
class FFI(object):
4+
import ctypes
55

6-
def cdef(self, _, packed=NotImplemented):
7-
pass
86

9-
def dlopen(self, _):
10-
return self
7+
# Monkey-patch ctypes to disable searching for JACK
8+
ctypes.util.find_library = lambda _: NotImplemented
9+
10+
11+
class Fake(object):
1112

1213
NULL = NotImplemented
1314

1415
JackTransportStopped = 0
1516
JackTransportRolling = 1
1617
JackTransportStarting = 3
1718
JackTransportNetStarting = 4
19+
20+
def dlopen(self, _):
21+
return self
22+
23+
24+
ffi = Fake()

jack_build.py

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
from cffi import FFI
2+
3+
ffibuilder = FFI()
4+
ffibuilder.set_source("_jack", None)
5+
ffibuilder.cdef("""
6+
7+
/* types.h */
8+
9+
typedef uint64_t jack_uuid_t;
10+
typedef uint32_t jack_nframes_t;
11+
typedef uint64_t jack_time_t;
12+
typedef struct _jack_port jack_port_t;
13+
typedef struct _jack_client jack_client_t;
14+
typedef uint32_t jack_port_id_t;
15+
typedef uint32_t jack_port_type_id_t;
16+
enum JackOptions {
17+
JackNullOption = 0x00,
18+
JackNoStartServer = 0x01,
19+
JackUseExactName = 0x02,
20+
JackServerName = 0x04,
21+
JackLoadName = 0x08,
22+
JackLoadInit = 0x10,
23+
JackSessionID = 0x20
24+
};
25+
typedef enum JackOptions jack_options_t;
26+
enum JackStatus {
27+
JackFailure = 0x01,
28+
JackInvalidOption = 0x02,
29+
JackNameNotUnique = 0x04,
30+
JackServerStarted = 0x08,
31+
JackServerFailed = 0x10,
32+
JackServerError = 0x20,
33+
JackNoSuchClient = 0x40,
34+
JackLoadFailure = 0x80,
35+
JackInitFailure = 0x100,
36+
JackShmFailure = 0x200,
37+
JackVersionError = 0x400,
38+
JackBackendError = 0x800,
39+
JackClientZombie = 0x1000
40+
};
41+
typedef enum JackStatus jack_status_t;
42+
typedef int (*JackProcessCallback)(jack_nframes_t nframes, void* arg);
43+
typedef int (*JackGraphOrderCallback)(void* arg);
44+
typedef int (*JackXRunCallback)(void* arg);
45+
typedef int (*JackBufferSizeCallback)(jack_nframes_t nframes, void* arg);
46+
typedef int (*JackSampleRateCallback)(jack_nframes_t nframes, void* arg);
47+
typedef void (*JackPortRegistrationCallback)(jack_port_id_t port, int /* register */, void* arg);
48+
typedef void (*JackClientRegistrationCallback)(const char* name, int /* register */, void* arg);
49+
typedef void (*JackPortConnectCallback)(jack_port_id_t a, jack_port_id_t b, int connect, void* arg);
50+
typedef int (*JackPortRenameCallback)(jack_port_id_t port, const char* old_name, const char* new_name, void* arg);
51+
typedef void (*JackFreewheelCallback)(int starting, void* arg);
52+
/* not implemented: JackShutdownCallback (only JackInfoShutdownCallback is used) */
53+
typedef void (*JackInfoShutdownCallback)(jack_status_t code, const char* reason, void* arg);
54+
/* JACK_DEFAULT_AUDIO_TYPE: see _AUDIO */
55+
/* JACK_DEFAULT_MIDI_TYPE: see _MIDI */
56+
/* not implemented: jack_default_audio_sample_t (hard-coded as float) */
57+
enum JackPortFlags {
58+
JackPortIsInput = 0x1,
59+
JackPortIsOutput = 0x2,
60+
JackPortIsPhysical = 0x4,
61+
JackPortCanMonitor = 0x8,
62+
JackPortIsTerminal = 0x10,
63+
};
64+
typedef enum {
65+
JackTransportStopped = 0,
66+
JackTransportRolling = 1,
67+
JackTransportLooping = 2, /* deprecated */
68+
JackTransportStarting = 3,
69+
JackTransportNetStarting = 4,
70+
} jack_transport_state_t;
71+
typedef uint64_t jack_unique_t;
72+
typedef enum {
73+
JackPositionBBT = 0x10,
74+
JackPositionTimecode = 0x20,
75+
JackBBTFrameOffset = 0x40,
76+
JackAudioVideoRatio = 0x80,
77+
JackVideoFrameOffset = 0x100,
78+
} jack_position_bits_t;
79+
/* _jack_position: see below in "packed" section */
80+
typedef struct _jack_position jack_position_t;
81+
typedef void (*JackTimebaseCallback)(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos, void *arg);
82+
/* deprecated: jack_transport_bits_t */
83+
/* deprecated: jack_transport_info_t */
84+
85+
/* jack.h */
86+
87+
void jack_get_version(int* major_ptr, int* minor_ptr, int* micro_ptr, int* proto_ptr);
88+
const char* jack_get_version_string();
89+
jack_client_t* jack_client_open(const char* client_name, jack_options_t options, jack_status_t* status, ...);
90+
/* deprecated: jack_client_new */
91+
int jack_client_close(jack_client_t* client);
92+
int jack_client_name_size(void);
93+
char* jack_get_client_name(jack_client_t* client);
94+
char* jack_get_uuid_for_client_name(jack_client_t* client, const char* client_name);
95+
char* jack_get_client_name_by_uuid(jack_client_t* client, const char* client_uuid);
96+
/* deprecated: jack_internal_client_new */
97+
/* deprecated: jack_internal_client_close */
98+
int jack_activate(jack_client_t* client);
99+
int jack_deactivate(jack_client_t* client);
100+
int jack_get_client_pid(const char* name);
101+
/* not implemented: jack_client_thread_id */
102+
int jack_is_realtime(jack_client_t* client);
103+
/* deprecated: jack_thread_wait */
104+
/* not implemented: jack_cycle_wait */
105+
/* not implemented: jack_cycle_signal */
106+
/* not implemented: jack_set_process_thread */
107+
/* not implemented: jack_set_thread_init_callback */
108+
/* not implemented (jack_on_info_shutdown is used): jack_on_shutdown */
109+
void jack_on_info_shutdown(jack_client_t* client, JackInfoShutdownCallback shutdown_callback, void* arg);
110+
int jack_set_process_callback(jack_client_t* client, JackProcessCallback process_callback, void* arg);
111+
int jack_set_freewheel_callback(jack_client_t* client, JackFreewheelCallback freewheel_callback, void* arg);
112+
int jack_set_buffer_size_callback(jack_client_t* client, JackBufferSizeCallback bufsize_callback, void* arg);
113+
int jack_set_sample_rate_callback(jack_client_t* client, JackSampleRateCallback srate_callback, void* arg);
114+
int jack_set_client_registration_callback(jack_client_t* client, JackClientRegistrationCallback registration_callback, void* arg);
115+
int jack_set_port_registration_callback(jack_client_t* client, JackPortRegistrationCallback registration_callback, void* arg);
116+
int jack_set_port_connect_callback(jack_client_t* client, JackPortConnectCallback connect_callback, void* arg);
117+
int jack_set_port_rename_callback(jack_client_t* client, JackPortRenameCallback rename_callback, void* arg);
118+
int jack_set_graph_order_callback(jack_client_t* client, JackGraphOrderCallback graph_callback, void*);
119+
int jack_set_xrun_callback(jack_client_t* client, JackXRunCallback xrun_callback, void* arg);
120+
/* TODO: jack_set_latency_callback */
121+
int jack_set_freewheel(jack_client_t* client, int onoff);
122+
int jack_set_buffer_size(jack_client_t* client, jack_nframes_t nframes);
123+
jack_nframes_t jack_get_sample_rate(jack_client_t*);
124+
jack_nframes_t jack_get_buffer_size(jack_client_t*);
125+
/* deprecated: jack_engine_takeover_timebase */
126+
float jack_cpu_load(jack_client_t* client);
127+
jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size);
128+
int jack_port_unregister(jack_client_t* client, jack_port_t* port);
129+
void* jack_port_get_buffer(jack_port_t* port, jack_nframes_t);
130+
jack_uuid_t jack_port_uuid(const jack_port_t* port);
131+
const char* jack_port_name(const jack_port_t* port);
132+
const char* jack_port_short_name(const jack_port_t* port);
133+
int jack_port_flags(const jack_port_t* port);
134+
const char* jack_port_type(const jack_port_t* port);
135+
/* not implemented: jack_port_type_id */
136+
int jack_port_is_mine(const jack_client_t* client, const jack_port_t* port);
137+
int jack_port_connected(const jack_port_t* port);
138+
int jack_port_connected_to(const jack_port_t* port, const char* port_name);
139+
const char** jack_port_get_connections(const jack_port_t* port);
140+
const char** jack_port_get_all_connections(const jack_client_t* client, const jack_port_t* port);
141+
/* deprecated: jack_port_tie */
142+
/* deprecated: jack_port_untie */
143+
int jack_port_set_name(jack_port_t* port, const char* port_name);
144+
/* TODO: jack_port_set_alias */
145+
/* TODO: jack_port_unset_alias */
146+
/* TODO: jack_port_get_aliases */
147+
int jack_port_request_monitor(jack_port_t *port, int onoff);
148+
/* not implemented (use jack_port_request_monitor): jack_port_request_monitor_by_name */
149+
/* TODO: jack_port_ensure_monitor */
150+
/* TODO: jack_port_monitoring_input */
151+
int jack_connect(jack_client_t* client, const char* source_port, const char* destination_port);
152+
int jack_disconnect(jack_client_t* client, const char* source_port, const char* destination_port);
153+
int jack_port_disconnect(jack_client_t* client, jack_port_t* port);
154+
int jack_port_name_size(void);
155+
/* not implemented: jack_port_type_size */
156+
/* not implemented: jack_port_type_get_buffer_size */
157+
/* TODO: jack_port_set_latency */
158+
/* TODO: jack_port_get_latency_range */
159+
/* TODO: jack_port_set_latency_range */
160+
/* TODO: jack_recompute_total_latencies */
161+
/* TODO: jack_port_get_latency */
162+
/* TODO: jack_port_get_total_latency */
163+
/* TODO: jack_recompute_total_latency */
164+
const char** jack_get_ports(jack_client_t* client, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags);
165+
jack_port_t* jack_port_by_name(jack_client_t* client, const char* port_name);
166+
jack_port_t* jack_port_by_id(jack_client_t* client, jack_port_id_t port_id);
167+
jack_nframes_t jack_frames_since_cycle_start(const jack_client_t*);
168+
jack_nframes_t jack_frame_time(const jack_client_t*);
169+
jack_nframes_t jack_last_frame_time(const jack_client_t* client);
170+
/* TODO: jack_get_cycle_times */
171+
/* TODO: jack_frames_to_time */
172+
/* TODO: jack_time_to_frames */
173+
/* TODO: jack_get_time */
174+
void jack_set_error_function(void (*func)(const char*));
175+
void jack_set_info_function(void (*func)(const char*));
176+
void jack_free(void* ptr);
177+
178+
/* ringbuffer.h */
179+
180+
typedef struct {
181+
char* buf;
182+
size_t len;
183+
} jack_ringbuffer_data_t;
184+
typedef struct {
185+
char* buf;
186+
volatile size_t write_ptr;
187+
volatile size_t read_ptr;
188+
size_t size;
189+
size_t size_mask;
190+
int mlocked;
191+
} jack_ringbuffer_t;
192+
jack_ringbuffer_t* jack_ringbuffer_create(size_t sz);
193+
void jack_ringbuffer_free(jack_ringbuffer_t* rb);
194+
void jack_ringbuffer_get_read_vector(const jack_ringbuffer_t* rb, jack_ringbuffer_data_t* vec);
195+
void jack_ringbuffer_get_write_vector(const jack_ringbuffer_t* rb, jack_ringbuffer_data_t* vec);
196+
size_t jack_ringbuffer_read(jack_ringbuffer_t* rb, char* dest, size_t cnt);
197+
size_t jack_ringbuffer_peek(jack_ringbuffer_t* rb, char* dest, size_t cnt);
198+
void jack_ringbuffer_read_advance(jack_ringbuffer_t* rb, size_t cnt);
199+
size_t jack_ringbuffer_read_space(const jack_ringbuffer_t* rb);
200+
int jack_ringbuffer_mlock(jack_ringbuffer_t* rb);
201+
void jack_ringbuffer_reset(jack_ringbuffer_t* rb);
202+
void jack_ringbuffer_reset_size (jack_ringbuffer_t* rb, size_t sz);
203+
/* Note: "char*" was changed to "unsigned char*" to support iterables of int */
204+
size_t jack_ringbuffer_write(jack_ringbuffer_t* rb, const unsigned char* src, size_t cnt);
205+
void jack_ringbuffer_write_advance(jack_ringbuffer_t* rb, size_t cnt);
206+
size_t jack_ringbuffer_write_space(const jack_ringbuffer_t* rb);
207+
208+
/* transport.h */
209+
210+
/* TODO: jack_release_timebase */
211+
/* TODO: jack_set_sync_callback */
212+
/* TODO: jack_set_sync_timeout */
213+
int jack_set_timebase_callback(jack_client_t* client, int conditional, JackTimebaseCallback timebase_callback, void* arg);
214+
int jack_transport_locate(jack_client_t* client, jack_nframes_t frame);
215+
jack_transport_state_t jack_transport_query(const jack_client_t* client, jack_position_t* pos);
216+
jack_nframes_t jack_get_current_transport_frame(const jack_client_t* client);
217+
int jack_transport_reposition(jack_client_t* client, const jack_position_t* pos);
218+
void jack_transport_start(jack_client_t* client);
219+
void jack_transport_stop(jack_client_t* client);
220+
/* deprecated: jack_get_transport_info */
221+
/* deprecated: jack_set_transport_info */
222+
223+
/* statistics.h */
224+
225+
float jack_get_xrun_delayed_usecs(jack_client_t* client);
226+
227+
/* midiport.h */
228+
229+
typedef unsigned char jack_midi_data_t;
230+
typedef struct _jack_midi_event {
231+
jack_nframes_t time;
232+
size_t size;
233+
jack_midi_data_t* buffer;
234+
} jack_midi_event_t;
235+
uint32_t jack_midi_get_event_count(void* port_buffer);
236+
int jack_midi_event_get(jack_midi_event_t* event, void* port_buffer, uint32_t event_index);
237+
void jack_midi_clear_buffer(void* port_buffer);
238+
/* not implemented: jack_midi_reset_buffer */
239+
size_t jack_midi_max_event_size(void* port_buffer);
240+
jack_midi_data_t* jack_midi_event_reserve(void* port_buffer, jack_nframes_t time, size_t data_size);
241+
int jack_midi_event_write(void* port_buffer, jack_nframes_t time, const jack_midi_data_t* data, size_t data_size);
242+
uint32_t jack_midi_get_lost_event_count(void* port_buffer);
243+
""")
244+
245+
# Packed structure
246+
ffibuilder.cdef("""
247+
struct _jack_position {
248+
jack_unique_t unique_1;
249+
jack_time_t usecs;
250+
jack_nframes_t frame_rate;
251+
jack_nframes_t frame;
252+
jack_position_bits_t valid;
253+
int32_t bar;
254+
int32_t beat;
255+
int32_t tick;
256+
double bar_start_tick;
257+
float beats_per_bar;
258+
float beat_type;
259+
double ticks_per_beat;
260+
double beats_per_minute;
261+
double frame_time;
262+
double next_time;
263+
jack_nframes_t bbt_offset;
264+
float audio_frames_per_video_frame;
265+
jack_nframes_t video_offset;
266+
int32_t padding[7];
267+
jack_unique_t unique_2;
268+
};
269+
""", packed=True)
270+
271+
if __name__ == "__main__":
272+
ffibuilder.compile(verbose=True)

setup.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ def run_tests(self):
2929
version=__version__,
3030
package_dir={'': 'src'},
3131
py_modules=['jack'],
32-
install_requires=['CFFI'],
32+
setup_requires=['CFFI>=1.0'],
33+
install_requires=['CFFI>=1.0'],
3334
extras_require={'NumPy': ['NumPy']},
35+
cffi_modules=['jack_build.py:ffibuilder'],
3436
author='Matthias Geier',
3537
author_email='[email protected]',
3638
description='JACK Audio Connection Kit (JACK) Client for Python',

0 commit comments

Comments
 (0)