diff --git a/examples/chatty_client.py b/examples/chatty_client.py index fb9119c..7728c76 100755 --- a/examples/chatty_client.py +++ b/examples/chatty_client.py @@ -10,20 +10,19 @@ from __future__ import print_function # only needed for Python 2.x import jack +print("setting error/info functions") + +@jack.set_error_function def error(msg): print("Error:", msg) +@jack.set_info_function def info(msg): print("Info:", msg) -print("setting error/info functions") -jack.set_error_function(error) -jack.set_info_function(info) - - print("starting chatty client") client = jack.Client("Chatty-Client") @@ -39,71 +38,62 @@ def info(msg): print("registering callbacks") -def shutdown(status, reason, userdata): +@client.set_shutdown_callback +def shutdown(status, reason): print("JACK shutdown!") print("status:", status) print("reason:", reason) -client.set_shutdown_callback(shutdown) - -def freewheel(starting, userdata): +@client.set_freewheel_callback +def freewheel(starting): print(["stopping", "starting"][starting], "freewheel mode") -client.set_freewheel_callback(freewheel) - -def blocksize(blocksize, userdata): +@client.set_blocksize_callback +def blocksize(blocksize): print("setting blocksize to", blocksize) return jack.SUCCESS -client.set_blocksize_callback(blocksize) - -def samplerate(samplerate, userdata): +@client.set_samplerate_callback +def samplerate(samplerate): print("setting samplerate to", samplerate) return jack.SUCCESS -client.set_samplerate_callback(samplerate) - -def client_registration(name, register, userdata): +@client.set_client_registration_callback +def client_registration(name, register): print("client", repr(name), ["unregistered", "registered"][register]) -client.set_client_registration_callback(client_registration) - -def port_registration(port, register, userdata): +@client.set_port_registration_callback +def port_registration(port, register): print(repr(port), ["unregistered", "registered"][register]) -client.set_port_registration_callback(port_registration) - -def port_connect(a, b, connect, userdata): +@client.set_port_connect_callback +def port_connect(a, b, connect): print(["disconnected", "connected"][connect], a, "and", b) -client.set_port_connect_callback(port_connect) - -def port_rename(port, old, new, userdata): +@client.set_port_rename_callback +def port_rename(port, old, new): print("renamed", port, "from", repr(old), "to", repr(new)) return jack.SUCCESS -client.set_port_rename_callback(port_rename) - -def graph_order(userdata): +@client.set_graph_order_callback +def graph_order(): print("graph order changed") return jack.SUCCESS -client.set_graph_order_callback(graph_order) - -def xrun(userdata): +@client.set_xrun_callback +def xrun(): print("xrun; delay", client.xrun_delayed_usecs, "microseconds") return jack.SUCCESS -client.set_xrun_callback(xrun) print("activating JACK") with client: diff --git a/examples/midi_chords.py b/examples/midi_chords.py index cf26ded..ee9d2e5 100755 --- a/examples/midi_chords.py +++ b/examples/midi_chords.py @@ -20,7 +20,8 @@ outport = client.midi_outports.register("output") -def callback(frames, userdata): +@client.set_process_callback +def process(frames): outport.clear_buffer() for offset, indata in inport.incoming_midi_events(): # Note: This may raise an exception: @@ -33,8 +34,6 @@ def callback(frames, userdata): outport.write_midi_event(offset, (status, pitch + i, vel)) return jack.CALL_AGAIN -client.set_process_callback(callback) - with client: print("#" * 80) print("press Return to quit") diff --git a/examples/midi_monitor.py b/examples/midi_monitor.py index f1341f0..af73e17 100755 --- a/examples/midi_monitor.py +++ b/examples/midi_monitor.py @@ -9,15 +9,14 @@ port = client.midi_inports.register("input") -def callback(frames, userdata): +@client.set_process_callback +def process(frames): for offset, data in port.incoming_midi_events(): # TODO: use ringbuffer print("{0}: 0x{1}".format(client.last_frame_time + offset, binascii.hexlify(data).decode())) return jack.CALL_AGAIN -client.set_process_callback(callback) - with client: print("#" * 80) print("press Return to quit") diff --git a/examples/thru_client.py b/examples/thru_client.py index 15fbbb8..da1cce5 100755 --- a/examples/thru_client.py +++ b/examples/thru_client.py @@ -41,23 +41,22 @@ event = threading.Event() -def process(frames, userdata): +@client.set_process_callback +def process(frames): assert len(client.inports) == len(client.outports) assert frames == client.blocksize for i, o in zip(client.inports, client.outports): o.get_buffer()[:] = i.get_buffer() return jack.CALL_AGAIN -client.set_process_callback(process) - -def shutdown(status, reason, userdata): +@client.set_shutdown_callback +def shutdown(status, reason): print("JACK shutdown!") print("status:", status) print("reason:", reason) event.set() -client.set_shutdown_callback(shutdown) # create two port pairs for number in 1, 2: diff --git a/jack.py b/jack.py index 09e5bf7..c5532e3 100644 --- a/jack.py +++ b/jack.py @@ -636,6 +636,10 @@ def connect(self, source, destination): destination : str or Port The other end of the connection. Must be an input port. + See Also + -------- + OwnPort.connect + """ if isinstance(source, Port): source = source.name @@ -741,7 +745,7 @@ def set_freewheel(self, onoff): _check(_lib.jack_set_freewheel(self._ptr, onoff), "Error setting freewheel mode") - def set_shutdown_callback(self, callback, userdata=None): + def set_shutdown_callback(self, callback): """Register shutdown callback. Register a function (and optional argument) to be called if and @@ -753,14 +757,14 @@ def set_shutdown_callback(self, callback, userdata=None): the rest of the application knows that the JACK client thread has shut down. - .. note:: clients do not need to call this. It exists only to + .. note:: Clients do not need to call this. It exists only to help more complex clients understand what is going on. It should be called before :meth:`activate`. - .. note:: application should typically signal another thread to - correctly finish cleanup, that is by calling :meth:`close` - (since :meth:`close` cannot be called directly in the context - of the thread that calls the shutdown callback). + .. note:: The `callback` should typically signal another thread + to correctly finish cleanup by calling :meth:`close` (since + :meth:`close` cannot be called directly in the context of the + thread that calls the shutdown callback). Parameters ---------- @@ -768,35 +772,31 @@ def set_shutdown_callback(self, callback, userdata=None): User-supplied function that is called whenever the JACK daemon is shutdown. It must have this signature:: - callback(status:Status, reason:str, userdata) -> None + callback(status:Status, reason:str) -> None The argument `status` is of type :class:`jack.Status`. - Note that after server shutdown, `self` - is *not* deallocated by libjack, the application is - responsible to properly use :meth:`close` to release client - ressources. + .. note:: After server shutdown, the client is *not* + deallocated by JACK, the user (that's you!) is + responsible to properly use :meth:`close` to release + client ressources. .. warning:: :meth:`close` cannot be safely used inside the shutdown callback and has to be called outside of the callback context. - userdata : anything - This will be passed as third argument when `callback` is - called. """ @self._callback("JackInfoShutdownCallback") def callback_wrapper(code, reason, _): - return callback(Status(code), _ffi.string(reason).decode(), - userdata) + return callback(Status(code), _ffi.string(reason).decode()) _lib.jack_on_info_shutdown(self._ptr, callback_wrapper, _ffi.NULL) - def set_process_callback(self, callback, userdata=None): + def set_process_callback(self, callback): """Register process callback. Tell the JACK server to call `callback` whenever there is work - be done, passing `userdata` as the second argument. + be done. The code in the supplied function must be suitable for real-time execution. That means that it cannot call functions that might @@ -813,7 +813,7 @@ def set_process_callback(self, callback, userdata=None): User-supplied function that is called by the engine anytime there is work to be done. It must have this signature:: - callback(frames:int, userdata) -> int + callback(frames:int) -> int The argument `frames` specifies the number of frames that have to be processed in the current audio block. It will be @@ -824,45 +824,41 @@ def set_process_callback(self, callback, userdata=None): on error (if `callback` shall not be called again). You can use the module constants :data:`CALL_AGAIN` and :data:`STOP_CALLING`, respectively. - userdata : anything - This will be passed as second argument whenever `callback` - is called. """ @self._callback("JackProcessCallback", error=STOP_CALLING) def callback_wrapper(frames, _): - return callback(frames, userdata) + return callback(frames) _check(_lib.jack_set_process_callback( self._ptr, callback_wrapper, _ffi.NULL), "Error setting process callback") - def set_freewheel_callback(self, callback, userdata=None): + def set_freewheel_callback(self, callback): """Register freewheel callback. Tell the JACK server to call `callback` whenever we enter or - leave "freewheel" mode, passing `userdata` as the second - argument. The first argument to the callback will be ``True`` if - JACK is entering freewheel mode, and ``False`` otherwise. + leave "freewheel" mode. + The argument to the callback will be ``True`` if JACK is + entering freewheel mode, and ``False`` otherwise. All "notification events" are received in a separated non RT thread, the code in the supplied function does not need to be suitable for real-time execution. - .. note:: this function cannot be called while the client is + .. note:: This function cannot be called while the client is activated (after :meth:`activate` has been called). Parameters ---------- callback : callable - User-supplied function that is called whenever jackd starts + User-supplied function that is called whenever JACK starts or stops freewheeling. It must have this signature:: - callback(starting:bool, userdata) -> None + callback(starting:bool) -> None - userdata : anything - This will be passed as second argument whenever `callback` - is called. + The argument `starting` is ``True`` if we start to + freewheel, ``False`` otherwise. See Also -------- @@ -871,13 +867,13 @@ def set_freewheel_callback(self, callback, userdata=None): """ @self._callback("JackFreewheelCallback") def callback_wrapper(starting, _): - return callback(bool(starting), userdata) + return callback(bool(starting)) _check(_lib.jack_set_freewheel_callback( self._ptr, callback_wrapper, _ffi.NULL), "Error setting freewheel callback") - def set_blocksize_callback(self, callback, userdata=None): + def set_blocksize_callback(self, callback): """Register blocksize callback. Tell JACK to call `callback` whenever the size of the the buffer @@ -889,7 +885,7 @@ def set_blocksize_callback(self, callback, userdata=None): thread, the code in the supplied function does not need to be suitable for real-time execution. - .. note:: this function cannot be called while the client is + .. note:: This function cannot be called while the client is activated (after :meth:`activate` has been called). Parameters @@ -898,31 +894,34 @@ def set_blocksize_callback(self, callback, userdata=None): User-supplied function that is invoked whenever the JACK engine buffer size changes. It must have this signature:: - callback(blocksize:int, userdata) -> int + callback(blocksize:int) -> int + The argument `blocksize` is the new buffer size. The `callback` must return zero on success and non-zero on error. You can use the module constants :data:`jack.SUCCESS` and :data:`jack.FAILURE`, respectively. - Although this function is called in the JACK process thread, - the normal process cycle is suspended during its operation, - causing a gap in the audio flow. So, the `callback` can - allocate storage, touch memory not previously referenced, - and perform other operations that are not realtime safe. - userdata : anything - This will be passed as second argument whenever `callback` - is called. + .. note:: Although this function is called in the JACK + process thread, the normal process cycle is suspended + during its operation, causing a gap in the audio flow. + So, the `callback` can allocate storage, touch memory not + previously referenced, and perform other operations that + are not realtime safe. + + See Also + -------- + :attr:`blocksize` """ @self._callback("JackBufferSizeCallback", error=FAILURE) def callback_wrapper(blocksize, _): - return callback(blocksize, userdata) + return callback(blocksize) _check(_lib.jack_set_buffer_size_callback( self._ptr, callback_wrapper, _ffi.NULL), "Error setting blocksize callback") - def set_samplerate_callback(self, callback, userdata=None): + def set_samplerate_callback(self, callback): """Register samplerate callback. Tell the JACK server to call `callback` whenever the system @@ -932,7 +931,7 @@ def set_samplerate_callback(self, callback, userdata=None): thread, the code in the supplied function does not need to be suitable for real-time execution. - .. note:: this function cannot be called while the client is + .. note:: This function cannot be called while the client is activated (after :meth:`activate` has been called). Parameters @@ -941,36 +940,37 @@ def set_samplerate_callback(self, callback, userdata=None): User-supplied function that is called when the engine sample rate changes. It must have this signature:: - callback(samplerate:int, userdata) -> int + callback(samplerate:int) -> int The argument `samplerate` is the new engine sample rate. The `callback` must return zero on success and non-zero on error. You can use the module constants :data:`jack.SUCCESS` and :data:`jack.FAILURE`, respectively. - userdata : anything - This will be passed as second argument whenever `callback` - is called. + + See Also + -------- + :attr:`samplerate` """ @self._callback("JackSampleRateCallback", error=FAILURE) def callback_wrapper(samplerate, _): - return callback(samplerate, userdata) + return callback(samplerate) _check(_lib.jack_set_sample_rate_callback( self._ptr, callback_wrapper, _ffi.NULL), "Error setting samplerate callback") - def set_client_registration_callback(self, callback, userdata=None): + def set_client_registration_callback(self, callback): """Register client registration callback. Tell the JACK server to call `callback` whenever a client is - registered or unregistered, passing `userdata` as a parameter. + registered or unregistered. All "notification events" are received in a separated non RT thread, the code in the supplied function does not need to be suitable for real-time execution. - .. note:: this function cannot be called while the client is + .. note:: This function cannot be called while the client is activated (after :meth:`activate` has been called). Parameters @@ -979,36 +979,32 @@ def set_client_registration_callback(self, callback, userdata=None): User-supplied function that is called whenever a client is registered or unregistered. It must have this signature:: - callback(name:str, register:bool, userdata) -> None + callback(name:str, register:bool) -> None The first argument contains the client name, the second argument is ``True`` if the client is being registered and ``False`` if the client is being unregistered. - userdata : anything - This will be passed as third argument whenever `callback` - is called. """ @self._callback("JackClientRegistrationCallback") def callback_wrapper(name, register, _): - return callback(_ffi.string(name).decode(), bool(register), - userdata) + return callback(_ffi.string(name).decode(), bool(register)) _check(_lib.jack_set_client_registration_callback( self._ptr, callback_wrapper, _ffi.NULL), "Error setting client registration callback") - def set_port_registration_callback(self, callback, userdata=None): + def set_port_registration_callback(self, callback): """Register port registration callback. Tell the JACK server to call `callback` whenever a port is - registered or unregistered, passing `userdata` as a parameter. + registered or unregistered. All "notification events" are received in a separated non RT thread, the code in the supplied function does not need to be suitable for real-time execution. - .. note:: this function cannot be called while the client is + .. note:: This function cannot be called while the client is activated (after :meth:`activate` has been called). Parameters @@ -1018,37 +1014,38 @@ def set_port_registration_callback(self, callback, userdata=None): port is registered or unregistered. It must have this signature:: - callback(port:Port, register:bool, userdata) -> None + callback(port:Port, register:bool) -> None The first argument is a :class:`Port`, :class:`MidiPort`, :class:`OwnPort` or :class:`OwnMidiPort` object, the second argument is ``True`` if the port is being registered, ``False`` if the port is being unregistered. - userdata : anything - This will be passed as third argument whenever `callback` is - called. + + See Also + -------- + Ports.register """ @self._callback("JackPortRegistrationCallback") def callback_wrapper(port, register, _): port = self._wrap_port_ptr(_lib.jack_port_by_id(self._ptr, port)) - return callback(port, bool(register), userdata) + return callback(port, bool(register)) _check(_lib.jack_set_port_registration_callback( self._ptr, callback_wrapper, _ffi.NULL), "Error setting port registration callback") - def set_port_connect_callback(self, callback, userdata=None): + def set_port_connect_callback(self, callback): """Register port connect callback. Tell the JACK server to call `callback` whenever a port is - connected or disconnected, passing `userdata` as a parameter. + connected or disconnected. All "notification events" are received in a separated non RT thread, the code in the supplied function does not need to be suitable for real-time execution. - .. note:: this function cannot be called while the client is + .. note:: This function cannot be called while the client is activated (after :meth:`activate` has been called). Parameters @@ -1057,39 +1054,40 @@ def set_port_connect_callback(self, callback, userdata=None): User-supplied function that is called whenever a port is connected or disconnected. It must have this signature:: - callback(a:Port, b:Port, connect:bool, userdata) -> None + callback(a:Port, b:Port, connect:bool) -> None The first and second arguments contain :class:`Port`, :class:`MidiPort`, :class:`OwnPort` or :class:`OwnMidiPort` objects of the ports which are connected or disconnected. The third argument is ``True`` if the ports were connected and ``False`` if the ports were disconnected. - userdata : anything - This will be passed as fourth argument whenever `callback` - is called. + + See Also + -------- + Client.connect, OwnPort.connect """ @self._callback("JackPortConnectCallback") def callback_wrapper(a, b, connect, _): a = self._wrap_port_ptr(_lib.jack_port_by_id(self._ptr, a)) b = self._wrap_port_ptr(_lib.jack_port_by_id(self._ptr, b)) - return callback(a, b, bool(connect), userdata) + return callback(a, b, bool(connect)) _check(_lib.jack_set_port_connect_callback( self._ptr, callback_wrapper, _ffi.NULL), "Error setting port connect callback") - def set_port_rename_callback(self, callback, userdata=None): + def set_port_rename_callback(self, callback): """Register port rename callback. Tell the JACK server to call `callback` whenever a port is - renamed, passing `userdata` as a parameter. + renamed. All "notification events" are received in a separated non RT thread, the code in the supplied function does not need to be suitable for real-time execution. - .. note:: this function cannot be called while the client is + .. note:: This function cannot be called while the client is activated (after :meth:`activate` has been called). Parameters @@ -1098,7 +1096,7 @@ def set_port_rename_callback(self, callback, userdata=None): User-supplied function that is called whenever the port name has been changed. It must have this signature:: - callback(port:Port, old:str, new:str, userdata) -> int + callback(port:Port, old:str, new:str) -> int The first argument is the port that has been renamed (a :class:`Port`, :class:`MidiPort`, :class:`OwnPort` or @@ -1107,32 +1105,33 @@ def set_port_rename_callback(self, callback, userdata=None): The `callback` must return zero on success and non-zero on error. You can use the module constants :data:`jack.SUCCESS` and :data:`jack.FAILURE`, respectively. - userdata : anything - This will be passed as fourth argument whenever `callback` - is called. + + See Also + -------- + :attr:`Port.shortname` """ @self._callback("JackPortRenameCallback", error=FAILURE) def callback_wrapper(port, old_name, new_name, _): port = self._wrap_port_ptr(_lib.jack_port_by_id(self._ptr, port)) return callback(port, _ffi.string(old_name).decode(), - _ffi.string(new_name).decode(), userdata) + _ffi.string(new_name).decode()) _check(_lib.jack_set_port_rename_callback( self._ptr, callback_wrapper, _ffi.NULL), "Error setting port rename callback") - def set_graph_order_callback(self, callback, userdata=None): + def set_graph_order_callback(self, callback): """Register graph order callback. Tell the JACK server to call `callback` whenever the processing - graph is reordered, passing `userdata` as a parameter. + graph is reordered. All "notification events" are received in a separated non RT thread, the code in the supplied function does not need to be suitable for real-time execution. - .. note:: this function cannot be called while the client is + .. note:: This function cannot be called while the client is activated (after :meth:`activate` has been called). Parameters @@ -1142,35 +1141,32 @@ def set_graph_order_callback(self, callback, userdata=None): processing graph is reordered. It must have this signature:: - callback(userdata) -> int + callback() -> int The `callback` must return zero on success and non-zero on error. You can use the module constants :data:`jack.SUCCESS` and :data:`jack.FAILURE`, respectively. - userdata : anything - This will be passed as argument whenever `callback` is - called. """ @self._callback("JackGraphOrderCallback", error=FAILURE) def callback_wrapper(_): - return callback(userdata) + return callback() _check(_lib.jack_set_graph_order_callback( self._ptr, callback_wrapper, _ffi.NULL), "Error setting graph order callback") - def set_xrun_callback(self, callback, userdata=None): + def set_xrun_callback(self, callback): """Register xrun callback. Tell the JACK server to call `callback` whenever there is an - xrun, passing `userdata` as a parameter. + xrun. All "notification events" are received in a separated non RT thread, the code in the supplied function does not need to be suitable for real-time execution. - .. note:: this function cannot be called while the client is + .. note:: This function cannot be called while the client is activated (after :meth:`activate` has been called). Parameters @@ -1179,14 +1175,11 @@ def set_xrun_callback(self, callback, userdata=None): User-supplied function that is called whenever an xrun has occured. It must have this signature:: - callback(userdata) -> int + callback() -> int The `callback` must return zero on success and non-zero on error. You can use the module constants :data:`jack.SUCCESS` and :data:`jack.FAILURE`, respectively. - userdata : anything - This will be passed as argument whenever `callback` is - called. See Also -------- @@ -1195,7 +1188,7 @@ def set_xrun_callback(self, callback, userdata=None): """ @self._callback("JackXRunCallback", error=FAILURE) def callback_wrapper(_): - return callback(userdata) + return callback() _check(_lib.jack_set_xrun_callback( self._ptr, callback_wrapper, _ffi.NULL),