### Install setuptools with pip Source: https://jackclient-python.readthedocs.io/en/0.5.5/installation Installs or upgrades the setuptools package using pip. Setuptools is a dependency for installing Python modules and is often required if pip is present but setuptools is not. ```bash python3 -m pip install setuptools ``` -------------------------------- ### Install NumPy with pip Source: https://jackclient-python.readthedocs.io/en/0.5.5/installation Installs the NumPy library using pip. NumPy is optional for JACK-Client but required if you need to access audio buffers as NumPy arrays. Installation may require a compiler and additional libraries. ```bash python3 -m pip install NumPy ``` -------------------------------- ### Install JACK-Client with pip Source: https://jackclient-python.readthedocs.io/en/0.5.5/installation Installs the JACK-Client Python module using pip. This command ensures you have the latest version of the library. Depending on your system, you might need to use 'python' instead of 'python3'. ```bash python3 -m pip install JACK-Client ``` -------------------------------- ### Pass-Through Client Example using Python Source: https://jackclient-python.readthedocs.io/en/0.5.5/examples This Python script implements a JACK client that copies audio data from its input ports directly to its output ports. It's designed to mirror the functionality of the 'thru_client.c' example from JACK 2. The script handles client naming, server connection, and defines a process callback to perform the audio data copying. It also includes a shutdown callback to signal program termination. ```python #!/usr/bin/env python3 """Create a JACK client that copies input audio directly to the outputs. This is somewhat modeled after the "thru_client.c" example of JACK 2: http://github.com/jackaudio/jack2/blob/master/example-clients/thru_client.c If you have a microphone and loudspeakers connected, this might cause an acoustical feedback! """ import sys import os import jack import threading argv = iter(sys.argv) # By default, use script name without extension as client name: defaultclientname = os.path.splitext(os.path.basename(next(argv)))[0] clientname = next(argv, defaultclientname) servername = next(argv, None) client = jack.Client(clientname, servername=servername) if client.status.server_started: print('JACK server started') if client.status.name_not_unique: print(f'unique name {client.name!r} assigned') event = threading.Event() @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() @client.set_shutdown_callback def shutdown(status, reason): print('JACK shutdown!') print('status:', status) print('reason:', reason) event.set() ``` -------------------------------- ### Chatty Client Example using Python Source: https://jackclient-python.readthedocs.io/en/0.5.5/examples This Python script creates a JACK client that registers and prints information for most available JACK callbacks. It demonstrates how to set up error, info, shutdown, freewheel, blocksize, samplerate, client/port registration, port connection/rename, graph order, xrun, and property change callbacks. The client activates and stays active until the user presses Enter. ```python #!/usr/bin/env python3 """Create a JACK client that prints a lot of information. This client registers all possible callbacks (except the process callback and the timebase callback, which would be just too much noise) and prints some information whenever they are called. """ 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('starting chatty client') client = jack.Client('Chatty-Client') if client.status.server_started: print('JACK server was started') else: print('JACK server was already running') if client.status.name_not_unique: print('unique client name generated:', client.name) print('registering callbacks') @client.set_shutdown_callback def shutdown(status, reason): print('JACK shutdown!') print('status:', status) print('reason:', reason) @client.set_freewheel_callback def freewheel(starting): print(['stopping', 'starting'][starting], 'freewheel mode') @client.set_blocksize_callback def blocksize(blocksize): print('setting blocksize to', blocksize) @client.set_samplerate_callback def samplerate(samplerate): print('setting samplerate to', samplerate) @client.set_client_registration_callback def client_registration(name, register): print('client', repr(name), ['unregistered', 'registered'][register]) @client.set_port_registration_callback def port_registration(port, register): print(repr(port), ['unregistered', 'registered'][register]) @client.set_port_connect_callback def port_connect(a, b, connect): print(['disconnected', 'connected'][connect], a, 'and', b) try: @client.set_port_rename_callback def port_rename(port, old, new): print('renamed', port, 'from', repr(old), 'to', repr(new)) except AttributeError: print('Could not register port rename callback (not available on JACK1).') @client.set_graph_order_callback def graph_order(): print('graph order changed') @client.set_xrun_callback def xrun(delay): print('xrun; delay', delay, 'microseconds') try: @client.set_property_change_callback def property_change(subject, key, changed): print(f'subject {subject}: ', end='') if not key: assert changed == jack.PROPERTY_DELETED print('all properties were removed') return print('property {!r} was {}'.format(key, { jack.PROPERTY_CREATED: 'created', jack.PROPERTY_CHANGED: 'changed', jack.PROPERTY_DELETED: 'removed', }[changed])) except jack.JackError as e: print(e) print('activating JACK') with client: print('#' * 80) print('press Return to quit') print('#' * 80) input() print('closing JACK') ``` -------------------------------- ### Start JACK Transport Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Starts the JACK transport mechanism. This is used for synchronizing playback or recording across multiple JACK clients. ```python def transport_start(self): """Start JACK transport.""" _lib.jack_transport_start(self._ptr) ``` -------------------------------- ### Simple MIDI Synthesizer with JACK (Python) Source: https://jackclient-python.readthedocs.io/en/0.5.5/examples A basic MIDI synthesizer written in Python 3, inspired by the JACK 'jack_midisine' example. It features an ASR envelope, unlimited polyphony, and can handle multiple MIDI events per block. However, it is noted as inefficient due to dynamic allocations and sample-wise processing. ```python #!/usr/bin/env python3 """Very basic MIDI synthesizer. This only works in Python 3.x because it uses memoryview.cast() and a few other sweet Python-3-only features. This is inspired by the JACK example program "jack_midisine": http://github.com/jackaudio/jack2/blob/master/example-clients/midisine.c But it is actually better: + ASR envelope + unlimited polyphony (well, "only" limited by CPU and memory) + arbitrarily many MIDI events per block + can handle NoteOn and NoteOff event of the same pitch in one block It is also worse: - horribly inefficient (dynamic allocations, sample-wise processing) - unpredictable because of garbage collection (?) It sounds a little better than the original, but still quite boring. """ import jack import math import operator import threading ``` -------------------------------- ### Main Execution Block Source: https://jackclient-python.readthedocs.io/en/0.5.5/examples The main execution block that starts the JACK client, prints a message, and waits for the JACK server to shut down or for a user interruption (Ctrl+C). ```python with client: print('Press Ctrl+C to stop') try: event.wait() except KeyboardInterrupt: print(' Interrupted by user') ``` -------------------------------- ### Initialize JACK Client and Ports Source: https://jackclient-python.readthedocs.io/en/0.5.5/examples Sets up a JACK client named 'MIDI-Sine' and registers MIDI input and audio output ports. This is the initial step for any JACK application. ```python import jack client = jack.Client('MIDI-Sine') midiport = client.midi_inports.register('midi_in') audioport = client.outports.register('audio_out') ``` -------------------------------- ### Get All Properties Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Retrieves all metadata properties for all subjects. ```APIDOC ## GET /api/properties ### Description Retrieves all metadata properties for all subjects that have metadata. ### Method GET ### Endpoint `/api/properties` ### Response #### Success Response (200) - **dict** (dict) - A dictionary where keys are subject UUIDs and values are nested dictionaries of properties (as returned by `get_properties`). #### Response Example ```json { "example": "{'uuid1': {'prop1': ('value1', 'type1')}, 'uuid2': {'prop2': ('value2', 'type2')}}" } ``` ``` -------------------------------- ### JACK Samplerate Callback Source: https://jackclient-python.readthedocs.io/en/0.5.5/examples Callback function for JACK samplerate changes. It updates the global sample rate and clears existing voices. ```python @client.set_samplerate_callback def samplerate(samplerate): global fs fs = samplerate voices.clear() ``` -------------------------------- ### Voice Class for Synthesizer Source: https://jackclient-python.readthedocs.io/en/0.5.5/examples Represents a single voice in the synthesizer, managing its pitch, time, and amplitude envelope. It handles triggering notes and updating their weights. ```python import operator import math attack = 0.01 # seconds release = 0.2 # seconds fs = None voices = {} class Voice: def __init__(self, pitch): self.time = 0 self.time_increment = m2f(pitch) / fs self.weight = 0 self.target_weight = 0 self.weight_step = 0 self.compare = None def trigger(self, vel): if vel: dur = attack * fs else: dur = release * fs self.target_weight = vel / 127 self.weight_step = (self.target_weight - self.weight) / dur self.compare = operator.ge if self.weight_step > 0 else operator.le def update(self): """Increment weight.""" if self.weight_step: self.weight += self.weight_step if self.compare(self.weight, self.target_weight): self.weight = self.target_weight self.weight_step = 0 ``` -------------------------------- ### Get JACK Version Information Source: https://jackclient-python.readthedocs.io/en/0.5.5/api Retrieves version information for the JACK library. This includes both a tuple of major, minor, micro, and protocol versions, as well as a human-readable string representation of the version. ```python jack.version() jack.version_string() ``` -------------------------------- ### Convert MIDI Note to Frequency Source: https://jackclient-python.readthedocs.io/en/0.5.5/examples Converts a MIDI note number to its corresponding frequency in Hertz (Hz). This function is based on the MIDI Tuning Standard. ```python def m2f(note): """Convert MIDI note number to frequency in Hertz. See https://en.wikipedia.org/wiki/MIDI_Tuning_Standard. """ return 2 ** ((note - 69) / 12) * 440 ``` -------------------------------- ### Get Input Ports Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Provides a list of audio input `Ports`. New ports can be registered using `inports.register()`, and existing ports can be unregistered using `unregister()` or cleared using `inports.clear()`. ```python return self._inports ``` -------------------------------- ### Uninstall JACK-Client with pip Source: https://jackclient-python.readthedocs.io/en/0.5.5/installation Removes the JACK-Client Python module from your system using pip. This command is useful for cleaning up installations or before reinstalling. ```bash python3 -m pip uninstall JACK-Client ``` -------------------------------- ### Create JACK Client Instance (Python) Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Initializes a new JACK client instance. This constructor handles setting up client options, opening a connection to the JACK server using `jack_client_open()`, and raising `JackOpenError` if the connection fails. It also initializes internal port and position structures. ```python class Client: """A client that can connect to the JACK audio server.""" def __init__(self, name, use_exact_name=False, no_start_server=False, servername=None, session_id=None): """Create a new JACK client. A client object is a *context manager*, i.e. it can be used in a *with statement* to automatically call `activate()` in the beginning of the statement and `deactivate()` and `close()` on exit. Parameters ---------- name : str The desired client name of at most `client_name_size()` characters. The name scope is local to each server. Unless forbidden by the *use_exact_name* option, the server will modify this name to create a unique variant, if needed. Other Parameters ---------------- use_exact_name : bool Whether an error should be raised if *name* is not unique. See `Status.name_not_unique`. no_start_server : bool Do not automatically start the JACK server when it is not already running. This option is always selected if ``JACK_NO_START_SERVER`` is defined in the calling process environment. servername : str Selects from among several possible concurrent server instances. Server names are unique to each user. If unspecified, use ``'default'`` unless ``JACK_DEFAULT_SERVER`` is defined in the process environment. session_id : str Pass a SessionID Token. This allows the sessionmanager to identify the client again. Raises ------ JackOpenError If the session with the JACK server could not be opened. """ status = _ffi.new('jack_status_t*') options = _lib.JackNullOption optargs = [] if use_exact_name: options |= _lib.JackUseExactName if no_start_server: options |= _lib.JackNoStartServer if servername: options |= _lib.JackServerName optargs.append(_ffi.new('char[]', servername.encode())) if session_id: options |= _lib.JackSessionID optargs.append(_ffi.new('char[]', session_id.encode())) self._ptr = _lib.jack_client_open(name.encode(), options, status, *optargs) self._status = Status(status[0]) if not self._ptr: raise JackOpenError(name, self._status) self._inports = Ports(self, _AUDIO, _lib.JackPortIsInput) self._outports = Ports(self, _AUDIO, _lib.JackPortIsOutput) self._midi_inports = Ports(self, _MIDI, _lib.JackPortIsInput) self._midi_outports = Ports(self, _MIDI, _lib.JackPortIsOutput) self._keepalive = [] self._position = _ffi.new('jack_position_t*') # Avoid confusion if something goes wrong before opening the client: _ptr = _ffi.NULL def __enter__(self): self.activate() return self def __exit__(self, *args): self.deactivate() self.close() def __del__(self): """Close JACK client on garbage collection.""" self.close() @property def name(self): """The name of the JACK client (read-only).""" ``` -------------------------------- ### Client Creation Source: https://jackclient-python.readthedocs.io/en/0.5.5/api This section details how to create a new JACK client. The Client object can be used as a context manager for automatic activation and deactivation. ```APIDOC ## POST /jack/client ### Description Creates a new JACK client instance. This client can be used within a `with` statement to manage its lifecycle automatically. ### Method POST ### Endpoint /jack/client ### Parameters #### Path Parameters None #### Query Parameters - **name** (str) - Required - The desired name for the JACK client. - **use_exact_name** (bool) - Optional - If True, raises an error if the provided name is not unique. - **no_start_server** (bool) - Optional - If True, does not automatically start the JACK server if it's not running. - **servername** (str) - Optional - Specifies which JACK server instance to connect to. Defaults to 'default'. - **session_id** (str) - Optional - A SessionID Token for session management. #### Request Body None ### Request Example ```python import jack # Example using default parameters with jack.Client('MyClient') as client: print(f"Client name: {client.name}") # Example with specific options with jack.Client('AnotherClient', use_exact_name=True, no_start_server=True) as client: print(f"Client name: {client.name}") ``` ### Response #### Success Response (200) - **client_name** (str) - The unique name assigned to the JACK client by the server. - **client_uuid** (str) - The UUID of the JACK client. #### Response Example ```json { "client_name": "MyClient#1234", "client_uuid": "a1b2c3d4-e5f6-7890-1234-567890abcdef" } ``` ### Errors - **JackOpenError**: Raised if the session with the JACK server could not be opened. ``` -------------------------------- ### Get JACK Transport State Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Retrieves the current state of the JACK transport. The state can be one of STOPPED, ROLLING, STARTING, or NETSTARTING. ```python @property def transport_state(self): """JACK transport state. This is one of `STOPPED`, `ROLLING`, `STARTING`, `NETSTARTING`. See Also -------- transport_query """ return TransportState(_lib.jack_transport_query(self._ptr, _ffi.NULL)) ``` -------------------------------- ### Get Frames Since Cycle Start Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Returns the estimated time in frames that has passed since the JACK server began the current process cycle. This is a read-only property. ```python return _lib.jack_frames_since_cycle_start(self._ptr) ``` -------------------------------- ### Play MIDI File with mido and JACK (Python) Source: https://jackclient-python.readthedocs.io/en/0.5.5/examples Plays a MIDI file using the 'mido' library and the JACK audio connection kit. It takes the MIDI file name as a command-line argument and optionally a JACK port name to connect to. The script handles MIDI events, samplerate changes, and JACK shutdown events. ```python #!/usr/bin/env python3 """Play a MIDI file. This uses the "mido" module for handling MIDI: https://mido.readthedocs.io/ Pass the MIDI file name as first command line argument. If a MIDI port name is passed as second argument, a connection is made. """ import sys import threading import jack from mido import MidiFile argv = iter(sys.argv) next(argv) filename = next(argv, '') connect_to = next(argv, '') if not filename: sys.exit('Please specify a MIDI file') try: mid = iter(MidiFile(filename)) except Exception as e: sys.exit(type(e).__name__ + ' while loading MIDI: ' + str(e)) client = jack.Client('MIDI-File-Player') port = client.midi_outports.register('output') event = threading.Event() msg = next(mid) fs = None # sampling rate offset = 0 @client.set_process_callback def process(frames): global offset global msg port.clear_buffer() while True: if offset >= frames: offset -= frames return # We'll take care of this in the next block ... # Note: This may raise an exception: port.write_midi_event(offset, msg.bytes()) try: msg = next(mid) except StopIteration: event.set() raise jack.CallbackExit offset += round(msg.time * fs) @client.set_samplerate_callback def samplerate(samplerate): global fs fs = samplerate @client.set_shutdown_callback def shutdown(status, reason): print('JACK shutdown:', reason, status) event.set() with client: if connect_to: port.connect(connect_to) print('Playing', repr(filename), '... press Ctrl+C to stop') try: event.wait() except KeyboardInterrupt: print('\nInterrupted by user') ``` -------------------------------- ### MIDI Synth Core Logic with JACK and NumPy Source: https://jackclient-python.readthedocs.io/en/0.5.5/examples This Python code implements a real-time MIDI synthesizer using the jackclient-python library and NumPy. It sets up JACK client, MIDI input, and audio output ports. The core functionality lies in the `process` callback, which handles incoming MIDI events, updates voice envelopes, generates sine wave tones based on MIDI pitch, applies amplitude envelopes, and mixes them into the audio output buffer. The `samplerate` callback adjusts audio parameters based on the JACK server's sample rate, and `shutdown` handles client disconnection. ```python import jack import numpy as np import threading # MIDI status byte constants NOTEON = 0x9 NOTEOFF = 0x8 # Envelope parameters (in seconds) attack_seconds = 0.01 release_seconds = 0.2 # Global variables for envelope, sample rate, and active voices attack = None release = None fs = None voices = {} # Initialize JACK client and ports client = jack.Client('MIDI-Sine-NumPy') midiport = client.midi_inports.register('midi_in') audioport = client.outports.register('audio_out') event = threading.Event() def m2f(note): """Convert MIDI note number to frequency in Hertz. See https://en.wikipedia.org/wiki/MIDI_Tuning_Standard. """ return 2 ** ((note - 69) / 12) * 440 def update_envelope(envelope, begin, target, vel): """Helper function to calculate envelopes. envelope: array of velocities, will be mutated begin: sample index where ramp begins target: sample index where *vel* shall be reached vel: final velocity value If the ramp goes beyond the blocksize, it is supposed to be continued in the next block. A reference to *envelope* is returned, as well as the (unchanged) *vel* and the target index of the following block where *vel* shall be reached. """ blocksize = len(envelope) old_vel = envelope[begin] slope = (vel - old_vel) / (target - begin + 1) ramp = np.arange(min(target, blocksize) - begin) + 1 envelope[begin:target] = ramp * slope + old_vel if target < blocksize: envelope[target:] = vel target = 0 else: target -= blocksize return envelope, vel, target @client.set_process_callback def process(blocksize): """Main callback.""" # Step 1: Update/delete existing voices from previous block # Iterating over a copy because items may be deleted: for pitch in list(voices): envelope, vel, target = voices[pitch] if any([vel, target]): envelope[0] = envelope[-1] voices[pitch] = update_envelope(envelope, 0, target, vel) else: del voices[pitch] # Step 2: Create envelopes from the MIDI events of the current block for offset, data in midiport.incoming_midi_events(): if len(data) == 3: status, pitch, vel = bytes(data) # MIDI channel number is ignored! status >>= 4 if status == NOTEON and vel > 0: try: envelope, _, _ = voices[pitch] except KeyError: envelope = np.zeros(blocksize) voices[pitch] = update_envelope( envelope, offset, offset + attack, vel) elif status in (NOTEON, NOTEOFF): # NoteOff velocity is ignored! try: envelope, _, _ = voices[pitch] except KeyError: print('NoteOff without NoteOn (ignored)') continue voices[pitch] = update_envelope( envelope, offset, offset + release, 0) else: pass # ignore else: pass # ignore # Step 3: Create sine tones, apply envelopes, add to output buffer buf = audioport.get_array() buf.fill(0) for pitch, (envelope, _, _) in voices.items(): t = (np.arange(blocksize) + client.last_frame_time) / fs tone = np.sin(2 * np.pi * m2f(pitch) * t) buf += tone * envelope / 127 @client.set_samplerate_callback def samplerate(samplerate): global fs, attack, release fs = samplerate attack = int(attack_seconds * fs) release = int(release_seconds * fs) voices.clear() @client.set_shutdown_callback def shutdown(status, reason): print('JACK shutdown:', reason, status) event.set() with client: print('Press Ctrl+C to stop') try: event.wait() except KeyboardInterrupt: print('\nInterrupted by user') ``` -------------------------------- ### Get Last Frame Time Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Returns the precise time at the start of the current process cycle. This should only be used from the process callback and provides monotonic and linear time, unless an xrun occurs. ```python return _lib.jack_last_frame_time(self._ptr) ``` -------------------------------- ### Register and Connect Ports in Python Source: https://jackclient-python.readthedocs.io/en/0.5.5/examples This Python code snippet demonstrates how to register input and output ports with a JACK client, activate the client, and then connect these ports to physical capture and playback ports. It includes error handling for missing physical ports and uses a context manager for automatic client deactivation. Dependencies include the 'jackclient' library. ```python import event # Assuming 'client' is an initialized jackclient.Client instance # Create two port pairs for number in 1, 2: client.inports.register(f'input_{number}') client.outports.register(f'output_{number}') with client: # When entering this with-statement, client.activate() is called. # This tells the JACK server that we are ready to roll. # Our process() callback will start running now. # Connect the ports. You can't do this before the client is activated, # because we can't make connections to clients that aren't running. # Note the confusing (but necessary) orientation of the driver backend # ports: playback ports are "input" to the backend, and capture ports # are "output" from it. capture = client.get_ports(is_physical=True, is_output=True) if not capture: raise RuntimeError('No physical capture ports') for src, dest in zip(capture, client.inports): client.connect(src, dest) playback = client.get_ports(is_physical=True, is_input=True) if not playback: raise RuntimeError('No physical playback ports') for src, dest in zip(client.outports, playback): client.connect(src, dest) print('Press Ctrl+C to stop') try: event.wait() except KeyboardInterrupt: print('\nInterrupted by user') # When the above with-statement is left (either because the end of the # code block is reached, or because an exception was raised inside), # client.deactivate() and client.close() are called automatically. ``` -------------------------------- ### Play Sound File using Python and JACK Source: https://jackclient-python.readthedocs.io/en/0.5.5/examples This script plays a specified audio file using the JACK Audio Connection Kit. It requires NumPy and the `soundfile` module. The script buffers audio data in chunks to handle large files and can connect to output ports automatically or manually. ```python #!/usr/bin/env python3 """Play a sound file. This only reads a certain number of blocks at a time into memory, therefore it can handle very long files and also files with many channels. NumPy and the soundfile module (http://PySoundFile.rtfd.io/) must be installed for this to work. """ import argparse try: import queue # Python 3.x except ImportError: import Queue as queue # Python 2.x import sys import threading parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('filename', help='audio file to be played back') parser.add_argument( '-b', '--buffersize', type=int, default=20, help='number of blocks used for buffering (default: %(default)s)') parser.add_argument('-c', '--clientname', default='file player', help='JACK client name') parser.add_argument('-m', '--manual', action='store_true', help="don't connect to output ports automatically") args = parser.parse_args() if args.buffersize < 1: parser.error('buffersize must be at least 1') q = queue.Queue(maxsize=args.buffersize) event = threading.Event() def print_error(*args): print(*args, file=sys.stderr) def xrun(delay): print_error("An xrun occured, increase JACK's period size?") def shutdown(status, reason): print_error('JACK shutdown!') print_error('status:', status) print_error('reason:', reason) event.set() def stop_callback(msg=''): if msg: print_error(msg) for port in client.outports: port.get_array().fill(0) event.set() raise jack.CallbackExit def process(frames): if frames != blocksize: stop_callback('blocksize must not be changed, I quit!') try: data = q.get_nowait() except queue.Empty: stop_callback('Buffer is empty: increase buffersize?') if data is None: stop_callback() # Playback is finished for channel, port in zip(data.T, client.outports): port.get_array()[:] = channel try: import jack import soundfile as sf client = jack.Client(args.clientname) blocksize = client.blocksize samplerate = client.samplerate client.set_xrun_callback(xrun) client.set_shutdown_callback(shutdown) client.set_process_callback(process) with sf.SoundFile(args.filename) as f: for ch in range(f.channels): client.outports.register(f'out_{ch + 1}') block_generator = f.blocks(blocksize=blocksize, dtype='float32', always_2d=True, fill_value=0) for _, data in zip(range(args.buffersize), block_generator): q.put_nowait(data) # Pre-fill queue with client: if not args.manual: target_ports = client.get_ports( is_physical=True, is_input=True, is_audio=True) if len(client.outports) == 1 and len(target_ports) > 1: # Connect mono file to stereo output client.outports[0].connect(target_ports[0]) client.outports[0].connect(target_ports[1]) else: for source, target in zip(client.outports, target_ports): source.connect(target) timeout = blocksize * args.buffersize / samplerate for data in block_generator: q.put(data, timeout=timeout) q.put(None, timeout=timeout) # Signal end of file event.wait() # Wait until playback is finished except KeyboardInterrupt: parser.exit('\nInterrupted by user') except (queue.Full): # A timeout occured, i.e. there was an error in the callback parser.exit(1) except Exception as e: parser.exit(type(e).__name__ + ': ' + str(e)) ``` -------------------------------- ### Get JACK Transport Frame Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Gets or sets the current frame number for the JACK transport. This allows for precise control over playback position. ```python @property def transport_frame(self): """Get/set current JACK transport frame. Return an estimate of the current transport frame, including any ``` -------------------------------- ### Activate JACK Client Source: https://jackclient-python.readthedocs.io/en/0.5.5/usage Activates the JACK client, making it ready to process audio and establish connections. Activation must occur before making any connections. ```python client.activate() ``` -------------------------------- ### Enable/Disable JACK Freewheel Mode Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Starts or stops JACK's "freewheel" mode. In this mode, JACK does not wait for external events to start the next process cycle, potentially leading to faster-than-realtime execution. Real-time scheduling may be dropped and reacquired. ```python _check(_lib.jack_set_freewheel(self._ptr, onoff), 'Error setting freewheel mode') ``` -------------------------------- ### Get Properties Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Retrieves all metadata properties for a given subject. ```APIDOC ## GET /api/properties/{subject} ### Description Retrieves all metadata properties associated with a specific subject. ### Method GET ### Endpoint `/api/properties/{subject}` ### Parameters #### Path Parameters - **subject** (str or int) - Required - The subject (UUID) to get all properties of. ### Response #### Success Response (200) - **dict** (dict) - A dictionary where keys are property names and values are tuples of (value, type). #### Response Example ```json { "example": "{'prop1': ('value1', 'type1'), 'prop2': ('value2', 'type2')}" } ``` ``` -------------------------------- ### Python: Create and Manage JACK Ports Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Demonstrates how to register new audio or MIDI ports with a JACK client. It handles port types (audio/MIDI), flags (terminal/physical), and raises an error if registration fails due to non-unique names or exceeding length limits. ```python def _register_port(self, name, porttype, is_terminal, is_physical, flags): """Create a new port. Raises ------ JackError If the port can not be registered, e.g. because the name is non-unique or too long. """ if is_terminal: flags |= _lib.JackPortIsTerminal if is_physical: flags |= _lib.JackPortIsPhysical port_ptr = _lib.jack_port_register(self._ptr, name.encode(), porttype, flags, 0) if not port_ptr: raise JackError( f'{name!r}: port registration failed') return self._wrap_port_ptr(port_ptr) ``` -------------------------------- ### Get Property Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Retrieves a specific metadata property for a given subject. ```APIDOC ## GET /api/properties/{subject}/{key} ### Description Retrieves the value and type of a specific metadata property for a given subject. ### Method GET ### Endpoint `/api/properties/{subject}/{key}` ### Parameters #### Path Parameters - **subject** (str or int) - Required - The subject (UUID) to get the property from. - **key** (str) - Required - The name of the property to retrieve. ### Response #### Success Response (200) - **tuple** (tuple) - A tuple containing the value (str) and type (str) of the property, or None if the property is not found. #### Response Example ```json { "example": "('property_value', 'property_type')" } ``` ``` -------------------------------- ### Basic MIDI Synthesizer (NumPy Edition) Header Source: https://jackclient-python.readthedocs.io/en/0.5.5/examples Header for the NumPy edition of the MIDI synthesizer, indicating its purpose and efficiency improvements over the standard version. It imports necessary libraries. ```python #!/usr/bin/env python3 """Very basic MIDI synthesizer. This does the same as midi_sine.py, but it uses NumPy and block processing. It is therefore much more efficient. But there are still many allocations and dynamically growing and shrinking data structures. """ import jack import numpy as np import threading ``` -------------------------------- ### JACK Client Methods Source: https://jackclient-python.readthedocs.io/en/0.5.5/genindex This section details various methods available on the JACK Client object for managing audio connections and client properties. ```APIDOC ## Client Methods ### activate() **Description**: Activates the JACK client. ### close() **Description**: Closes the JACK client connection. ### connect() **Description**: Establishes a connection between ports. ### cpu_load() **Description**: Returns the current CPU load of the JACK client. ### deactivate() **Description**: Deactivates the JACK client. ### disconnect() **Description**: Removes a connection between ports. ### get_all_connections() **Description**: Retrieves all current connections for the client. ### get_client_name_by_uuid() **Description**: Gets the client name associated with a given UUID. ### get_port_by_name() **Description**: Retrieves a port object by its name. ### get_ports() **Description**: Gets a list of available ports. ### get_uuid_for_client_name() **Description**: Gets the UUID for a given client name. ### owns() **Description**: Checks if the client owns a specific port. ### release_timebase() **Description**: Releases the timebase control. ### remove_all_properties() **Description**: Removes all properties from the client. ### remove_properties() **Description**: Removes specified properties from the client. ### remove_property() **Description**: Removes a single property from the client. ``` -------------------------------- ### Get Property Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Retrieves a metadata property associated with a given subject (UUID). ```APIDOC ## GET /get_property ### Description Get a metadata property on a specified subject (identified by its UUID). This function allows you to retrieve custom metadata associated with JACK clients, ports, or other JACK objects. ### Method GET ### Endpoint `/get_property` (This is a conceptual representation; the actual implementation is a Python function call) ### Parameters #### Query Parameters - **subject** (int or str) - Required - The subject (UUID) to get the property from. UUIDs can be obtained using `Client.uuid`, `Port.uuid`, and `Client.get_uuid_for_client_name()`. - **key** (str) - Required - The key of the property to retrieve. ### Returns - **(bytes, str)** - A tuple containing the property data (as bytes) and its type (as a string). Returns an empty tuple or raises an error if the property is not found or an issue occurs. ### Example ```python # Assuming 'client' is a jack.Client instance client_uuid = client.uuid property_data, property_type = jack.get_property(client_uuid, "my_custom_property") if property_data: print(f"Property data: {property_data.decode()}, Type: {property_type}") ``` ``` -------------------------------- ### JACK Process Callback for MIDI and Audio Source: https://jackclient-python.readthedocs.io/en/0.5.5/examples The main JACK process callback function. It handles incoming MIDI events, updates voice states, generates audio output, and manages active voices. ```python import threading NOTEON = 0x9 NOTEOFF = 0x8 event = threading.Event() @client.set_process_callback def process(frames): """Main callback.""" events = {} buf = memoryview(audioport.get_buffer()).cast('f') for offset, data in midiport.incoming_midi_events(): if len(data) == 3: status, pitch, vel = bytes(data) # MIDI channel number is ignored! status >>= 4 if status == NOTEON and vel > 0: events.setdefault(offset, []).append((pitch, vel)) elif status in (NOTEON, NOTEOFF): # NoteOff velocity is ignored! events.setdefault(offset, []).append((pitch, 0)) else: pass # ignore else: pass # ignore for i in range(len(buf)): buf[i] = 0 try: eventlist = events[i] except KeyError: pass else: for pitch, vel in eventlist: if pitch not in voices: if not vel: break voices[pitch] = Voice(pitch) voices[pitch].trigger(vel) for voice in voices.values(): voice.update() if voice.weight > 0: buf[i] += voice.weight * math.sin(2 * math.pi * voice.time) voice.time += voice.time_increment if voice.time >= 1: voice.time -= 1 dead = [k for k, v in voices.items() if v.weight <= 0] for pitch in dead: del voices[pitch] ``` -------------------------------- ### Utility Functions Source: https://jackclient-python.readthedocs.io/en/0.5.5/api Documentation for global utility functions provided by the jackclient-python library. ```APIDOC ## Utility Functions ### Description Provides various utility functions for interacting with the JACK system and managing JACK-related data. ### Functions - **`get_property(key)`**: Retrieves a global JACK property. - **`get_properties()`**: Retrieves all global JACK properties. - **`get_all_properties()`**: Retrieves all properties, including client-specific ones. - **`position2dict(pos)`**: Converts a JACK position structure to a dictionary. - **`version()`**: Returns the JACK client library version as an integer. - **`version_string()`**: Returns the JACK client library version as a string. - **`client_name_size()`**: Returns the maximum size for a client name. - **`port_name_size()`**: Returns the maximum size for a port name. - **`set_error_function(func)`**: Sets a custom error handling function. - **`set_info_function(func)`**: Sets a custom information logging function. - **`client_pid()`**: Returns the process ID of the JACK server. ``` -------------------------------- ### Get JACK Samplerate Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Retrieves the sample rate of the JACK system. This is a read-only property. ```python return _lib.jack_get_sample_rate(self._ptr) ``` -------------------------------- ### Create a JACK Client Instance Source: https://jackclient-python.readthedocs.io/en/0.5.5/usage Demonstrates the creation of a new JACK client instance with a specified name. This is the primary object for interacting with the JACK server. ```python client = jack.Client('MyGreatClient') ``` -------------------------------- ### Get JACK Client Name Source: https://jackclient-python.readthedocs.io/en/0.5.5/_modules/jack Retrieves the name of the JACK client. This is a read-only property. ```python return _decode(_lib.jack_get_client_name(self._ptr)) ``` -------------------------------- ### Client Class Methods Source: https://jackclient-python.readthedocs.io/en/0.5.5/api Documentation for methods available on the Client class, used for managing JACK client connections and operations. ```APIDOC ## Client Class Methods ### Description Provides methods for managing JACK client connections, including activation, deactivation, port management, and transport control. ### Methods - **`Client.owns()`**: Checks if the client owns a specific port. - **`Client.activate()`**: Activates the JACK client. - **`Client.deactivate()`**: Deactivates the JACK client. - **`Client.cpu_load()`**: Returns the current CPU load of the client. - **`Client.close()`**: Closes the JACK client connection. - **`Client.connect()`**: Connects the client to the JACK server. - **`Client.disconnect()`**: Disconnects the client from the JACK server. - **`Client.transport_start()`**: Starts the JACK transport. - **`Client.transport_stop()`**: Stops the JACK transport. - **`Client.transport_locate()`**: Locates a specific frame in the JACK transport. - **`Client.transport_query()`**: Queries the current state of the JACK transport. - **`Client.transport_query_struct()`**: Queries the JACK transport state as a structure. - **`Client.transport_reposition_struct()`**: Repositions the JACK transport using a structure. - **`Client.set_sync_timeout()`**: Sets the synchronization timeout for the client. - **`Client.set_freewheel()`**: Enables or disables freewheeling for the client. - **`Client.set_shutdown_callback()`**: Sets a callback function for client shutdown. - **`Client.set_process_callback()`**: Sets a callback function for the processing cycle. - **`Client.set_freewheel_callback()`**: Sets a callback function for freewheel state changes. - **`Client.set_blocksize_callback()`**: Sets a callback function for block size changes. - **`Client.set_samplerate_callback()`**: Sets a callback function for sample rate changes. - **`Client.set_client_registration_callback()`**: Sets a callback for client registration events. - **`Client.set_port_registration_callback()`**: Sets a callback for port registration events. - **`Client.set_port_connect_callback()`**: Sets a callback for port connection events. - **`Client.set_port_rename_callback()`**: Sets a callback for port rename events. - **`Client.set_graph_order_callback()`**: Sets a callback for graph order changes. - **`Client.set_xrun_callback()`**: Sets a callback function for xrun (underrun/overrun) events. - **`Client.set_sync_callback()`**: Sets a callback function for synchronization events. - **`Client.release_timebase()`**: Releases the timebase control. - **`Client.set_timebase_callback()`**: Sets a callback function for timebase changes. - **`Client.set_property_change_callback()`**: Sets a callback for property change events. - **`Client.get_uuid_for_client_name()`**: Retrieves the UUID for a given client name. - **`Client.get_client_name_by_uuid()`**: Retrieves the client name for a given UUID. - **`Client.get_port_by_name()`**: Retrieves a port object by its name. - **`Client.get_all_connections()`**: Retrieves all active connections. - **`Client.get_ports()`**: Retrieves a list of all ports. - **`Client.set_property()`**: Sets a property for the client. - **`Client.remove_property()`**: Removes a property from the client. - **`Client.remove_properties()`**: Removes multiple properties from the client. - **`Client.remove_all_properties()`**: Removes all properties from the client. ### Properties - **`Client.name`** (str): The name of the client. - **`Client.uuid`** (str): The UUID of the client. - **`Client.samplerate`** (int): The current sample rate. - **`Client.blocksize`** (int): The current block size. - **`Client.status`** (int): The current status of the client. - **`Client.realtime`** (bool): Indicates if the client is running in real-time mode. - **`Client.frames_since_cycle_start`** (int): Frames processed since the cycle started. - **`Client.frame_time`** (float): The current frame time. - **`Client.last_frame_time`** (float): The time of the last processed frame. - **`Client.inports`** (list): A list of input ports. - **`Client.outports`** (list): A list of output ports. - **`Client.midi_inports`** (list): A list of MIDI input ports. - **`Client.midi_outports`** (list): A list of MIDI output ports. - **`Client.transport_state`** (int): The current state of the transport. - **`Client.transport_frame`** (int): The current frame of the transport. ```