Skip to content

Commit b56efbc

Browse files
committed
Use CallbackExit exception instead of callback return values
1 parent 8b12c30 commit b56efbc

File tree

6 files changed

+87
-64
lines changed

6 files changed

+87
-64
lines changed

examples/chatty_client.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,11 @@ def freewheel(starting):
5353
@client.set_blocksize_callback
5454
def blocksize(blocksize):
5555
print("setting blocksize to", blocksize)
56-
return jack.SUCCESS
5756

5857

5958
@client.set_samplerate_callback
6059
def samplerate(samplerate):
6160
print("setting samplerate to", samplerate)
62-
return jack.SUCCESS
6361

6462

6563
@client.set_client_registration_callback
@@ -81,21 +79,18 @@ def port_connect(a, b, connect):
8179
@client.set_port_rename_callback
8280
def port_rename(port, old, new):
8381
print("renamed", port, "from", repr(old), "to", repr(new))
84-
return jack.SUCCESS
8582
except AttributeError:
8683
print("Could not register port rename callback (not available on JACK1).")
8784

8885

8986
@client.set_graph_order_callback
9087
def graph_order():
9188
print("graph order changed")
92-
return jack.SUCCESS
9389

9490

9591
@client.set_xrun_callback
9692
def xrun():
9793
print("xrun; delay", client.xrun_delayed_usecs, "microseconds")
98-
return jack.SUCCESS
9994

10095

10196
print("activating JACK")

examples/midi_chords.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ def process(frames):
3232
for i in INTERVALS:
3333
# Note: This may raise an exception:
3434
outport.write_midi_event(offset, (status, pitch + i, vel))
35-
return jack.CALL_AGAIN
3635

3736
with client:
3837
print("#" * 80)

examples/midi_monitor.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ def process(frames):
1414
for offset, data in port.incoming_midi_events():
1515
print("{0}: 0x{1}".format(client.last_frame_time + offset,
1616
binascii.hexlify(data).decode()))
17-
return jack.CALL_AGAIN
1817

1918
with client:
2019
print("#" * 80)

examples/midi_sine.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,13 @@ def process(frames):
122122
dead = [k for k, v in voices.items() if v.weight <= 0]
123123
for pitch in dead:
124124
del voices[pitch]
125-
return jack.CALL_AGAIN
126125

127126

128127
@client.set_samplerate_callback
129128
def samplerate(samplerate):
130129
global fs
131130
fs = samplerate
132131
voices.clear()
133-
return jack.SUCCESS
134132

135133

136134
@client.set_shutdown_callback

examples/thru_client.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ def process(frames):
4747
assert frames == client.blocksize
4848
for i, o in zip(client.inports, client.outports):
4949
o.get_buffer()[:] = i.get_buffer()
50-
return jack.CALL_AGAIN
5150

5251

5352
@client.set_shutdown_callback

jack.py

Lines changed: 87 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -316,14 +316,8 @@
316316
NETSTARTING = _lib.JackTransportNetStarting
317317
"""Waiting for sync ready on the network."""
318318

319-
CALL_AGAIN = 0
320-
"""Possible return value for process callback."""
321-
STOP_CALLING = 1
322-
"""Possible return value for process callback."""
323-
SUCCESS = 0
324-
"""Possible return value for several callbacks."""
325-
FAILURE = 1
326-
"""Possible return value for several callbacks."""
319+
_SUCCESS = 0
320+
_FAILURE = 1
327321

328322

329323
class Client(object):
@@ -835,7 +829,7 @@ def set_shutdown_callback(self, callback):
835829
"""
836830
@self._callback("JackInfoShutdownCallback")
837831
def callback_wrapper(code, reason, _):
838-
return callback(Status(code), _ffi.string(reason).decode())
832+
callback(Status(code), _ffi.string(reason).decode())
839833

840834
_lib.jack_on_info_shutdown(self._ptr, callback_wrapper, _ffi.NULL)
841835

@@ -877,22 +871,28 @@ def set_process_callback(self, callback):
877871
User-supplied function that is called by the engine anytime
878872
there is work to be done. It must have this signature::
879873
880-
callback(frames:int) -> int
874+
callback(frames:int) -> None
881875
882876
The argument `frames` specifies the number of frames that
883877
have to be processed in the current audio block. It will be
884878
the same number as :attr:`blocksize` and it will be a power
885879
of two.
886-
The `callback` must return zero on success (if `callback`
887-
shall be called again for the next audio block) and non-zero
888-
on error (if `callback` shall not be called again).
889-
You can use the module constants :data:`CALL_AGAIN` and
890-
:data:`STOP_CALLING`, respectively.
880+
881+
As long as the client is active, the `callback` will be
882+
called once in each process cycle. However, if an exception
883+
is raised inside of a `callback`, it will not be called
884+
anymore. The exception :class:`CallbackExit` can be used to
885+
silently prevent further callback invocations, all other
886+
exceptions will print an error message to *stderr*.
891887
892888
"""
893-
@self._callback("JackProcessCallback", error=STOP_CALLING)
889+
@self._callback("JackProcessCallback", error=_FAILURE)
894890
def callback_wrapper(frames, _):
895-
return callback(frames)
891+
try:
892+
callback(frames)
893+
except CallbackExit:
894+
return _FAILURE
895+
return _SUCCESS
896896

897897
_check(_lib.jack_set_process_callback(
898898
self._ptr, callback_wrapper, _ffi.NULL),
@@ -931,7 +931,7 @@ def set_freewheel_callback(self, callback):
931931
"""
932932
@self._callback("JackFreewheelCallback")
933933
def callback_wrapper(starting, _):
934-
return callback(bool(starting))
934+
callback(bool(starting))
935935

936936
_check(_lib.jack_set_freewheel_callback(
937937
self._ptr, callback_wrapper, _ffi.NULL),
@@ -958,12 +958,11 @@ def set_blocksize_callback(self, callback):
958958
User-supplied function that is invoked whenever the JACK
959959
engine buffer size changes. It must have this signature::
960960
961-
callback(blocksize:int) -> int
961+
callback(blocksize:int) -> None
962962
963963
The argument `blocksize` is the new buffer size.
964-
The `callback` must return zero on success and non-zero on
965-
error. You can use the module constants :data:`jack.SUCCESS`
966-
and :data:`jack.FAILURE`, respectively.
964+
The `callback` is supposed to raise :class:`CallbackExit` on
965+
error.
967966
968967
.. note:: Although this function is called in the JACK
969968
process thread, the normal process cycle is suspended
@@ -977,9 +976,13 @@ def set_blocksize_callback(self, callback):
977976
:attr:`blocksize`
978977
979978
"""
980-
@self._callback("JackBufferSizeCallback", error=FAILURE)
979+
@self._callback("JackBufferSizeCallback", error=_FAILURE)
981980
def callback_wrapper(blocksize, _):
982-
return callback(blocksize)
981+
try:
982+
callback(blocksize)
983+
except CallbackExit:
984+
return _FAILURE
985+
return _SUCCESS
983986

984987
_check(_lib.jack_set_buffer_size_callback(
985988
self._ptr, callback_wrapper, _ffi.NULL),
@@ -1004,21 +1007,24 @@ def set_samplerate_callback(self, callback):
10041007
User-supplied function that is called when the engine sample
10051008
rate changes. It must have this signature::
10061009
1007-
callback(samplerate:int) -> int
1010+
callback(samplerate:int) -> None
10081011
10091012
The argument `samplerate` is the new engine sample rate.
1010-
The `callback` must return zero on success and non-zero on
1011-
error. You can use the module constants :data:`jack.SUCCESS`
1012-
and :data:`jack.FAILURE`, respectively.
1013+
The `callback` is supposed to raise :class:`CallbackExit` on
1014+
error.
10131015
10141016
See Also
10151017
--------
10161018
:attr:`samplerate`
10171019
10181020
"""
1019-
@self._callback("JackSampleRateCallback", error=FAILURE)
1021+
@self._callback("JackSampleRateCallback", error=_FAILURE)
10201022
def callback_wrapper(samplerate, _):
1021-
return callback(samplerate)
1023+
try:
1024+
callback(samplerate)
1025+
except CallbackExit:
1026+
return _FAILURE
1027+
return _SUCCESS
10221028

10231029
_check(_lib.jack_set_sample_rate_callback(
10241030
self._ptr, callback_wrapper, _ffi.NULL),
@@ -1052,7 +1058,7 @@ def set_client_registration_callback(self, callback):
10521058
"""
10531059
@self._callback("JackClientRegistrationCallback")
10541060
def callback_wrapper(name, register, _):
1055-
return callback(_ffi.string(name).decode(), bool(register))
1061+
callback(_ffi.string(name).decode(), bool(register))
10561062

10571063
_check(_lib.jack_set_client_registration_callback(
10581064
self._ptr, callback_wrapper, _ffi.NULL),
@@ -1093,7 +1099,7 @@ def set_port_registration_callback(self, callback):
10931099
@self._callback("JackPortRegistrationCallback")
10941100
def callback_wrapper(port, register, _):
10951101
port = self._wrap_port_ptr(_lib.jack_port_by_id(self._ptr, port))
1096-
return callback(port, bool(register))
1102+
callback(port, bool(register))
10971103

10981104
_check(_lib.jack_set_port_registration_callback(
10991105
self._ptr, callback_wrapper, _ffi.NULL),
@@ -1135,7 +1141,7 @@ def set_port_connect_callback(self, callback):
11351141
def callback_wrapper(a, b, connect, _):
11361142
a = self._wrap_port_ptr(_lib.jack_port_by_id(self._ptr, a))
11371143
b = self._wrap_port_ptr(_lib.jack_port_by_id(self._ptr, b))
1138-
return callback(a, b, bool(connect))
1144+
callback(a, b, bool(connect))
11391145

11401146
_check(_lib.jack_set_port_connect_callback(
11411147
self._ptr, callback_wrapper, _ffi.NULL),
@@ -1160,15 +1166,14 @@ def set_port_rename_callback(self, callback):
11601166
User-supplied function that is called whenever the port name
11611167
has been changed. It must have this signature::
11621168
1163-
callback(port:Port, old:str, new:str) -> int
1169+
callback(port:Port, old:str, new:str) -> None
11641170
11651171
The first argument is the port that has been renamed (a
11661172
:class:`Port`, :class:`MidiPort`, :class:`OwnPort` or
11671173
:class:`OwnMidiPort` object); the second and third argument
11681174
is the old and new name, respectively.
1169-
The `callback` must return zero on success and non-zero on
1170-
error. You can use the module constants :data:`jack.SUCCESS`
1171-
and :data:`jack.FAILURE`, respectively.
1175+
The `callback` is supposed to raise :class:`CallbackExit` on
1176+
error.
11721177
11731178
See Also
11741179
--------
@@ -1184,11 +1189,15 @@ def set_port_rename_callback(self, callback):
11841189
94c819accfab2612050e875c24cf325daa0fd26d
11851190
11861191
"""
1187-
@self._callback("JackPortRenameCallback", error=FAILURE)
1192+
@self._callback("JackPortRenameCallback", error=_FAILURE)
11881193
def callback_wrapper(port, old_name, new_name, _):
11891194
port = self._wrap_port_ptr(_lib.jack_port_by_id(self._ptr, port))
1190-
return callback(port, _ffi.string(old_name).decode(),
1191-
_ffi.string(new_name).decode())
1195+
try:
1196+
callback(port, _ffi.string(old_name).decode(),
1197+
_ffi.string(new_name).decode())
1198+
except CallbackExit:
1199+
return _FAILURE
1200+
return _SUCCESS
11921201

11931202
_check(_lib.jack_set_port_rename_callback(
11941203
self._ptr, callback_wrapper, _ffi.NULL),
@@ -1214,16 +1223,19 @@ def set_graph_order_callback(self, callback):
12141223
processing graph is reordered.
12151224
It must have this signature::
12161225
1217-
callback() -> int
1226+
callback() -> None
12181227
1219-
The `callback` must return zero on success and non-zero on
1220-
error. You can use the module constants :data:`jack.SUCCESS`
1221-
and :data:`jack.FAILURE`, respectively.
1228+
The `callback` is supposed to raise :class:`CallbackExit` on
1229+
error.
12221230
12231231
"""
1224-
@self._callback("JackGraphOrderCallback", error=FAILURE)
1232+
@self._callback("JackGraphOrderCallback", error=_FAILURE)
12251233
def callback_wrapper(_):
1226-
return callback()
1234+
try:
1235+
callback()
1236+
except CallbackExit:
1237+
return _FAILURE
1238+
return _SUCCESS
12271239

12281240
_check(_lib.jack_set_graph_order_callback(
12291241
self._ptr, callback_wrapper, _ffi.NULL),
@@ -1248,20 +1260,23 @@ def set_xrun_callback(self, callback):
12481260
User-supplied function that is called whenever an xrun has
12491261
occured. It must have this signature::
12501262
1251-
callback() -> int
1263+
callback() -> None
12521264
1253-
The `callback` must return zero on success and non-zero on
1254-
error. You can use the module constants :data:`jack.SUCCESS`
1255-
and :data:`jack.FAILURE`, respectively.
1265+
The `callback` is supposed to raise :class:`CallbackExit` on
1266+
error.
12561267
12571268
See Also
12581269
--------
12591270
:attr:`xrun_delayed_usecs`
12601271
12611272
"""
1262-
@self._callback("JackXRunCallback", error=FAILURE)
1273+
@self._callback("JackXRunCallback", error=_FAILURE)
12631274
def callback_wrapper(_):
1264-
return callback()
1275+
try:
1276+
callback()
1277+
except CallbackExit:
1278+
return _FAILURE
1279+
return _SUCCESS
12651280

12661281
_check(_lib.jack_set_xrun_callback(
12671282
self._ptr, callback_wrapper, _ffi.NULL),
@@ -1338,7 +1353,7 @@ def set_timebase_callback(self, callback=None, conditional=False):
13381353

13391354
@self._callback("JackTimebaseCallback")
13401355
def callback_wrapper(state, blocksize, pos, new_pos, _):
1341-
return callback(state, blocksize, pos, bool(new_pos))
1356+
callback(state, blocksize, pos, bool(new_pos))
13421357

13431358
err = _lib.jack_set_timebase_callback(self._ptr, conditional,
13441359
callback_wrapper, _ffi.NULL)
@@ -2439,6 +2454,24 @@ class JackError(Exception):
24392454
pass
24402455

24412456

2457+
class CallbackExit(Exception):
2458+
2459+
"""To be raised in a callback function to signal failure.
2460+
2461+
See Also
2462+
--------
2463+
:meth:`Client.set_process_callback`
2464+
:meth:`Client.set_blocksize_callback`
2465+
:meth:`Client.set_samplerate_callback`
2466+
:meth:`Client.set_port_rename_callback`
2467+
:meth:`Client.set_graph_order_callback`
2468+
:meth:`Client.set_xrun_callback`
2469+
2470+
"""
2471+
2472+
pass
2473+
2474+
24422475
def position2dict(pos):
24432476
"""Convert CFFI position struct to a dict."""
24442477
assert pos.unique_1 == pos.unique_2
@@ -2543,7 +2576,7 @@ def _set_error_or_info_function(callback, setter):
25432576
else:
25442577
@_ffi.callback("void (*)(const char*)")
25452578
def callback_wrapper(msg):
2546-
return callback(_ffi.string(msg).decode())
2579+
callback(_ffi.string(msg).decode())
25472580

25482581
_keepalive[setter] = callback_wrapper
25492582
setter(callback_wrapper)

0 commit comments

Comments
 (0)