Coder Social home page Coder Social logo

jackclient-python's People

Contributors

amstan avatar dependabot[bot] avatar jofemodo avatar lack avatar mauriziob avatar mgeier avatar mk-fg avatar spotlightkid avatar toddrme2178 avatar vampouille avatar vrslev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jackclient-python's Issues

AssertionError: -105

I was trying to make a experimental computer keyboard from a Midi keyboard and was using this code:


import binascii
import  os


from evdev import uinput, ecodes as e
import jack
from subprocess import Popen

Keys={
    "3c":"a",
    "3e":"s",
    "40":"d",
    "41":"f",
    "43":"g",
    "48":"a",
    "4a":"s",
    "4c":"d",
    "4d":"f",
    "4f":"g",
    "51":"DOWN",
    "52":"up",
    "53":"left",
    "54":"right",
    "54":"enter",
    "55":"backspace",
    "56":"p",
}



def press(key):
    pid=os.fork()
    if pid==0:
        with uinput.UInput() as ui:
            eval("ui.write(e.EV_KEY, e.KEY_" + key.upper() +", 1)")
            ui.syn()





setup = ['a2j', 'a2jmidid -e']
a2j = [Popen(cmd, shell=True) for cmd in setup]






client=jack.Client("VirtualControl")
inp=client.midi_inports.register("Input")



@client.set_process_callback
def process(frames):

    for offset, data in inp.incoming_midi_events():
        midihex = binascii.hexlify(data).decode()

        if(midihex!='f8'):
            pressed = midihex[0:2] =='90'
            code=midihex[2:4]
            intensity=midihex[4:6]

            if pressed:
                press(Keys[code])

            #print(midihex)

        #print('{0}: 0x{1}'.format(client.last_frame_time + offset, sbinascii.hexlify(data).decode()))

#press("b")
with client:
    print('#' * 80)
    print('press Return to quit')
    print('#' * 80)
    input()

Problem is that it crashes right after i press one or two keys. With the error:

  File "/usr/local/lib/python3.6/dist-packages/jack.py", line 1787, in incoming_midi_events
    assert not err, err
AssertionError: -105

This fork is there because i first thought it was something related with the small delay on the simulated keypress. If i just use print it works fine. What is causing this issue? The keys get inputed and then it crashes.

I noticed your code:


    for i in range(_lib.jack_midi_get_event_count(buf)):
            err = _lib.jack_midi_event_get(event, buf, i)
            # TODO: proper error handling if this ever happens:
            assert not err, err
            yield event.time, _ffi.buffer(event.buffer, event.size)

I just noticed that if I simply comment out the assert line my script works! I don't know what it does so.... Ill keep this way for now.

midi_file_player.py + multiprocessing

Hi,
I'm trying to modify this example in order to make it compatible with multiprocessing.

Mainly I had to rename some global variables:

#!/usr/bin/env python3

import sys
import threading

import jack
from mido import MidiFile
from multiprocessing import Process

midi_file = '../Musica/Mozart/k265/Zwölf-Variationen.midi'

try:
    mid = iter(MidiFile(midi_file))
except Exception as e:
    sys.exit(type(e).__name__ + ' while loading MIDI: ' + str(e))

client = jack.Client('Luces')
midi_port = client.midi_outports.register('output')
midi_event = threading.Event()
midi_msg = next(mid)
midi_fs = None  # sampling rate
midi_offset = 0

@client.set_process_callback
def process(frames):
    global midi_offset
    global midi_msg
    midi_port.clear_buffer()
    while True:
        if midi_offset >= frames:
            midi_offset -= frames
            return  # We'll take care of this in the next block ...
        # Note: This may raise an exception:
        midi_port.write_midi_event(midi_offset, midi_msg.bytes())
        try:
            midi_msg = next(mid)
        except StopIteration:
            midi_event.set()
            raise jack.CallbackExit
        midi_offset += round(midi_msg.time * midi_fs)

@client.set_samplerate_callback
def samplerate(samplerate):
    global midi_fs
    midi_fs = samplerate

@client.set_shutdown_callback
def shutdown(status, reason):
    print('JACK shutdown:', reason, status)
    midi_event.set()

def run_midi():
    with client:
        print('Playing', repr(midi_file), '... press Ctrl+C to stop')
        try:
            midi_event.wait()
        except KeyboardInterrupt:
            print('\nInterrupted by user')

if __name__ == "__main__":
    processes = [Process(target=run_midi)]
    for p in processes:
        p.start()
    for p in processes:
        p.join()

Now I get this error at the end of the execution:

Playing '../Musica/Mozart/k265/Zwölf-Variationen.midi' ... press Ctrl+C to stop
Cannot read socket fd = 5 err = Success
CheckRes error
JackSocketClientChannel read fail
JACK shutdown: JACK server has been closed <jack.Status 0x21: failure, server_error>

How can I fix it?

Thank you!

Carlo

playing sound in 3 speaker devices

Hi,
i am working on a Yolo program that takes 3 camera inputs, process the live feed and just looking for a way to give 3 different output to 3 different speakers at a same time.

is it possible with this api? all the 3 devices speakers are wired connected via usb port!

Please help me
Thanks

Q: Alsa MIDI Connections

Is it possible to control (make and break) the Alsa MIDI connections in the same way that the Jack MIDI connections can be made?

In QJackCtl these are on the third tab and remain persistent the app is quit - which makes me think that Jackd is handling them.
jackclient_alsa_connection

I could receive the MIDI packets (with python-mido) and relay them, but I'm after a better (less latency) method.

Simple audio record example

It would be great if someone could add an example of recording audio to the examples in the documentation. If I figure it out I will try to add it. Thanks for the great library!

Question: Volume control?

This probably demonstrates my lack of understanding on the inner workings of JACK, but here it goes... Why doesn't come jackclient with any volume controls? This is my No.1 Python need for Jack ;-) Thanks for clarifying.

Sending real time midi event

I'm trying to write a program to send midi events to a soft synth. I can't tell from the docs what the 'time' parameter should represent.

A real simple example which I thought would work:

client = jack.Client('MIDI-Chord-Generator')
inport = client.midi_inports.register('input')
outport = client.midi_outports.register('output')
client.activate()
outport.connect("Helm:events-in")

for x in range(0,10):
  print("Note")

  outport.write_midi_event(0, (0x90, 60, 100))

  time.sleep(5)

  outport.write_midi_event(0, (0x80, 60, 100))

Can you let me know if I'm missing something obvious!

Segfault under some conditions

I saw this error, and I'm not quite sure what's happening. I think jackd may have stopped in the background and restarted, it's a pretty complex environment, and there are also multiple threads.

Thought you guys might want to know about it anyway though.

Thanks for the great library!

Current thread 0x00007f6719361700 (most recent call first):
  File "/usr/lib/python3/dist-packages/jack.py", line 315 in owns
  File "/usr/lib/python3/dist-packages/jack.py", line 1377 in _wrap_port_ptr
  File "/usr/lib/python3/dist-packages/jack.py", line 1265 in get_port_by_name
  File "/usr/lib/python3/dist-packages/jack.py", line 1361 in _port_list_from_pointers
  File "/usr/lib/python3/dist-packages/jack.py", line 1329 in get_ports
  File "/home/daniel/Projects/KaithemAutomation/kaithem/src/jackmanager.py", line 1090 in _get_ports_fix
  File "/home/daniel/Projects/KaithemAutomation/kaithem/src/jackmanager.py", line 1170 in checkJackClient
  File "/home/daniel/Projects/KaithemAutomation/kaithem/src/jackmanager.py", line 1064 in work
  File "/usr/lib/python3.6/threading.py", line 864 in run
  File "/home/daniel/Projects/KaithemAutomation/kaithem/src/tweaks.py", line 42 in run_with_except_hook
  File "/usr/lib/python3.6/threading.py", line 916 in _bootstrap_inner
  File "/usr/lib/python3.6/threading.py", line 884 in _bootstrap

access to transport position (jack_transport_query)

Hello,
I would like to get current transport position from jack server. ffi string in jack.py contain reference to jack_transport_query() function but there is no corresponding python method : client.transport_query(). Did you plan to add this function ? I can help or test if you want...

Best, Vampouille

How to start jackd from the python module?

Creating an instance of jack.Client will spawn an instance of jackd server, if it is not already running.
Is there a way to specify the options to the spawned jackd server from within this python package?

JackOpenError when (re)creating clients with identical name

I have recently noticed some very annoying behavior with the Jack server "clogging up" on client names. The critical application is that a client is created (usually does something) and is destroyed afterwards. This is then repeated for a considerable amount of times with an identical name of the client. Although this seems like a pretty bonkers use case, we actually rely on doing it (in a current implementation at least). Nevertheless, I would expect this to be possible and handled by the server without problems. Right?

I created the a simple script which provokes the behavior.

import jack

i = 0
while True:
    i += 1

    # name = f'Client{i:d}'  # this runs infinitely
    name = f'Client'  # this ALWAYS fails for the 99th instance ???

    print(f'Test {i:d}: creating "{name}" ...')
    client = jack.Client(name=name)
    client.activate()
    client.deactivate()
    client.close()
    del client

Executing the script results in the following trailing output and error:

...
Test 97: creating "Client" ...
Test 98: creating "Client" ...
Test 99: creating "Client" ...
Cannot open Client client
JackShmReadWritePtr1::~JackShmReadWritePtr1 - Init not done for -1, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
Traceback (most recent call last):
  File "jack_test.py", line 11, in <module>
    client = jack.Client(name=name)
  File ".../jack.py", line 213, in __init__
    raise JackOpenError(name, self._status)
jack.JackOpenError: Error initializing "Client": <jack.Status 0x21: failure, server_error>

The surprising thing (to me at least) is that this fails at the 99th client. And this is always reproduced in the exact same way.

On very annoying aspect is that this client name is now blocked indefinitely. An continues to be blocked even after restarting the Jack server. I did not find a possibility to instantiate a client with the given name again. This is indeed a problem when using tools like ecasound which do not let you determine the instantiated Jack client name (this is also how I encountered the problem). The easiest way to reset the behavior is to log out and in of the OS session (or restart), which is still very disruptive. Is there an easier option to get this reset?

negative xrun times

Hello I am running the chatty client demo. the Xrun call back is producing negative values
e.g. xrun; delay -274886000640.0 microseconds

This clearly makes no sense.... There is no audible artifacts in the audio stream

I am running Ubuntu 20.04.2

SegFault on port_registration_callback for existing clients on quit

There is a strange behaviour for clients existing before a new jack.Client is created, once the port registration callback is set.
I made a test using python 2.7, ardour and jack_mixer.

  1. launch the application; it has to have both audio and midi inputs and outputs. For example, this doesn't happen when launching jack_mixer without any channel set.
  2. create a client with a port registration callback; these commands will suffice:
client = jack.Client('xyz', no_start_server=True)
def port_cb(*args):
    print 'port_cb: {}'.format(args)
client.set_port_registration_callback(port_cb)
client.activate()
  1. close the former application

This generates a segfault on my machine (unfortunally I'm not able to make tests on other setups). The strange thing is that this does not happen when the application is started after the jack.Client instance is created and activated.
This problem is not reproducible when using a client created with jackclient-python (I don't exactly know why, maybe they exit in a different way).

How to use write_midi_event ?

Couldn't find any clear example how to use write_midi_event so came up with the following working code (a basic virtual MIDI cable) that you might add to your examples section. Any comments ?

import jack

midiInBuffer = []
midiOutBuffer = []

client = jack.Client('jack')

midi_in = client.midi_inports.register('midi_in')
midi_out = client.midi_outports.register('midi_out')

@client.set_process_callback

def process(frames):
  #MIDI sent
  midi_out.clear_buffer()
  if (len(midiOutBuffer)):
    for msg in midiOutBuffer:
      midi_out.write_midi_event(0, msg)
      print('MIDI sent = ', msg)
    midiOutBuffer.clear()
  #MIDI received
  for offset, data in midi_in.incoming_midi_events():
    msg = struct.unpack('3B', data)
    midiInBuffer.append(msg)
    print('MIDI rcvd = ', msg)

client.activate()

print(client.midi_inports)
print(client.midi_outports)

#forward all incoming messages from midi_in to midi_out
while True:
  for msg in midiInBuffer
    midiOutBuffer.append(msg)
    print('MIDI fwd = ', msg)
  midiInBuffer.clear()

Client objects on multiple servers don't pull correct port lists?

The following code snippet produces the same list of ports, the correct list for the first ('hard', hardware-connected) JACK server, all four times it does the get_ports() print. The .name print comes out correctly though. Any ideas why this is happening?

print('-----------------------------------------------------------------')
print('Create JACK clients, and use them to verify JACK servers...')
print('-----------------------------------------------------------------')

jack_client_hard = jack.Client('jack_client_hard', servername='default')
jack_client_hard.activate()
jack_client_hard.outports.register('dummy_4hard')

print('JACK ports for hard server:')
print(jack_client_hard.name)
print(jack_client_hard.get_ports())
print('')

jack_client_soft1 = jack.Client('jack_client_soft1', servername='SOFT1')
jack_client_soft1.activate()
jack_client_soft1.outports.register('dummy_4soft1')

print('JACK ports for server SOFT1:')
print(jack_client_soft1.name)
print(jack_client_soft1.get_ports())
print('')

jack_client_soft2 = jack.Client('jack_client_soft2', servername='SOFT2')
jack_client_soft2.activate()
jack_client_soft2.outports.register('dummy_4soft2')

print('JACK ports for server SOFT2:')
print(jack_client_soft2.name)
print(jack_client_soft2.get_ports())
print('')

jack_client_soft3 = jack.Client('jack_client_soft3', servername='SOFT3')
jack_client_soft3.activate()
jack_client_soft3.outports.register('dummy_4soft3')

print('JACK ports for server SOFT3:')
print(jack_client_soft3.name)
print(jack_client_soft3.get_ports())
print('')

input("Press Enter to continue...")

exit(0)

MIDI message blast

Hi, when I run the code below, it repeats the MIDI message forever. I can't seem to find the correct way to send a single midi message under my control. The first port connected below is just the GMIDImonitor with JACK support, the second is a midi port on a Echo AF12 connected to a mixer. Both show the message repeated until I hit the keyboard which satisfies the input() at the end of the code.:

#!/usr/bin/env python3
import jack
import struct

client = jack.Client("MyGreatClient")
inport = client.midi_inports.register("input")
outport = client.midi_outports.register("output")

portlist = client.get_ports(is_midi=True, is_physical=True)

for port in portlist:
    print('port: {} is output: {}'.format(port.name, port.is_output))

@client.set_process_callback
def macsend(frames):
    print('frames: {}'.format(frames))
    outport.clear_buffer()
    outport.write_midi_event(0, (0xB2, 0x01, 0x40))

client.activate()
client.connect(outport,"MIDI monitor:midi_in")
client.connect(outport, portlist[1].name)
print("#" * 80)
print("press Return to quit")
print("#" * 80)
input()

"operands could not be broadcast together with shapes" error playing sound

Hello everyone and thanks for this amazing project!

I'm trying to play a wave sound. I'm adding some code in an application which I didn't start from scratch, so it's quite possible I'm not understanding what I have to do!

I want to have a "metronome", so first I load the 2 metronome sounds using soundfile module:

mDataE, mSamplerateE = sf.read("/home/.../click-emphasis.wav", dtype=np.float32)
mData, mSamplerate = sf.read("/home/.../click.wav", dtype=np.float32)

then in Jack callback function, I check if beat has changed and I play the sound, routing it to the dedicated metronome jack out channels. output_buffers is an array of jack client .outports, metronome_left_channel and metronome_right_channel names of the 2 dedicated channels, and also previous_beat is defined out of callback function:

     # METRONOME: when Jack transport gets into new beat, metronome sound is played
     if state == 1 and 'beat' in position: 

         current_beat = position['beat']
         if current_beat != previous_beat:

             if current_beat == 1:  # Emphasis

                 output_buffers[metronome_left_channel][:] += mDataE[:]
                 output_buffers[metronome_right_channel][:] += mDataE[:]

             else:

                 output_buffers[metronome_left_channel][:] += mData[:]
                 output_buffers[metronome_right_channel][:] += mData[:]

             previous_beat = current_beat

when I hit Play, I get this error:

output_buffers[metronome_left_channel][:] += mDataE[:]
ValueError: operands could not be broadcast together with shapes (1024,) (33412,2) (1024,)

it's first time I try to play a sound, so I'm missing something for sure, but I don't urderstand what..

thanks!

Manu

Real-time audio signal processing in python

Hello,

I've been trying to make jackclient work (if possible) for a real-time audio processing application in python. You can see the code below:

import jack
import numpy as np

jclient = jack.Client("jclient")
    
jclient.register_port("in", jack.IsInput)
jclient.register_port("out", jack.IsOutput)
jclient.activate()

jclient.connect("system:capture_1","jclient:in")
for n_playback_port in (1, 2):
    jclient.connect("jclient:out", "system:playback_{}".format(n_playback_port))
#sr = jclient.get_sample_rate()
buffer_size = jclient.get_buffer_size()

jcapture = np.zeros((1,buffer_size), 'f')    
jinput = np.zeros((1,buffer_size), 'f')
joutput = np.zeros((1,buffer_size), 'f')

try:
    while True:
        print("Capturing audio")
        try:
            jclient.process(joutput, jcapture)
        except jack.InputSyncError:
            print("InputSyncError")
        except jack.OutputSyncError:
            print("OutputSyncError")

        #process jcapture here

        print("Playing back\n")
        try:
            jclient.process(jcapture, jinput)
        except jack.InputSyncError:
            print("InputSyncError")
        except jack.OutputSyncError:
            print("OutputSyncError")            
except KeyboardInterrupt:
    pass

The problem is that even if I don't process the signal at all (use the code above) and just playback the input I hear the input but with interrupts between the consecutive frames (buffers). Am I doing something wrong or is there a better way to do this?
I'm using 16000 kHz sample rate and 1024 samples buffer size for the jackd server.

Audio + MIDI

Hi,
I need to create a JACK client that plays an audio file and a MIDI file at the same time.

I'm trying to merge this two examples:

I miss the last step (I hope), i.e. merging the process() functions:

Do you have some suggestions? If I understand correctly, this while loop blocks the script until the end of the MIDI file, but I have to play MIDI and audio in parallel.

Thank you!

Carlo

Jack keeps sending last MIDI messages

I am trying to send MIDI messages using jackclient-python and I am seeing the issue that JACK repeats outgoing messages. I've managed to break this down to this minimal example:

import jack

cl = jack.Client('Test')
mo = cl.midi_outports.register('p2')
sent = False

@cl.set_process_callback
def process(frames):
    global sent
    if not sent:
        mo.write_midi_event(1, b'\x80\x2f\x32')
        mo.write_midi_event(2, b'\x80\x2f\x33')
        print("Sent!")
        sent = True

with cl:
    input()

The write_midi_event code is indeed only called once, but when I attach a MIDI analyzer (midisnoop in my case) I see that the two messages are rapidly repeated:

image

Am I doing something wrong here in the usage of the library?

Segfault during import

Hey, very recently I experience this segmentation fault whenever trying to import the package. I have no idea yet what component caused the change in behavior. The most probable candidate is building more recent versions of jack2 from source. Maybe investigating this can help to solve a bug here or upstream.

This is the most basic case where the segfault happens (empty environment, basically not more than pip install):

$ python3
Python 3.8.5 (default, Sep  4 2020, 02:22:02)
[Clang 10.0.0 ] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import jack
[1]    41999 segmentation fault  python3

Using faulthandler reveals that it happens during the decoding of "JACK_METADATA_" during import:

$ python3 -q -X faulthandler
>>> import jack
Fatal Python error: Segmentation fault

Current thread 0x0000000114f1cdc0 (most recent call first):
  File "/Users/helmholz/miniconda3/envs/test/lib/python3.8/site-packages/jack.py", line 82 in _decode
  File "/Users/helmholz/miniconda3/envs/test/lib/python3.8/site-packages/jack.py", line 89 in <module>
  File "<frozen importlib._bootstrap>", line 219 in _call_with_frames_removed
  File "<frozen importlib._bootstrap_external>", line 783 in exec_module
  File "<frozen importlib._bootstrap>", line 671 in _load_unlocked
  File "<frozen importlib._bootstrap>", line 975 in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 991 in _find_and_load
  File "<stdin>", line 1 in <module>
[1]    43708 segmentation fault  python3 -q -X faulthandler

Question: limit for number of JACK clients

There seems to be a limitation on a maximum number of JACK clients I can instantiate (tested under OSX 10.14, JACK 1.9.11 from old OSX bundle, jackclient-python 0.4.5).

My limit which I get there is 61 (at least plus 1 for the application starting the JACK server before -- JackPilot or such) ... each with 2 input and 2 output ports and connections.

I'm instantiating clients for benchmarking reasons, that's why the massive number (any actual implementation will not use that many of course). Still, do you have any hint where that limitation might come from?

dlopen issue on Windows 10 x64

Not working out of the box on Windows 10 x64, latest JACK and Python binary releases:

Free Win10 VM from Microsoft
JACK2 1.9.1 64 bit
Python 3.7.0 x86-64

Seems to be CFFI related, crash happens at jack.py line 45: _lib = _ffi.dlopen(_libname)

C:\Users\IEUser\Desktop\jackclient-python>python
Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import jack

(after a couple of seconds the Python shells exits with no error messages...)

C:\Users\IEUser\Desktop\jackclient-python>

Windows application log

Faulting application name: python.exe, version: 3.7.150.1013, time stamp: 0x5b331a30
Faulting module name: ntdll.dll, version: 10.0.17134.165, time stamp: 0xf4df6dc2
Exception code: 0xc0000026
Fault offset: 0x0000000000099968
Faulting process id: 0x1624
Faulting application start time: 0x01d434ca6ba235ee
Faulting application path: C:\Users\IEUser\AppData\Local\Programs\Python\Python37\python.exe
Faulting module path: C:\Windows\SYSTEM32\ntdll.dll
Report Id: 5c6d9233-baba-4d47-aa17-64bf56997ebd
Faulting package full name: 
Faulting package-relative application ID: 

How can I contribute to further testing?

Can't import the module

Hello.

Every time I try to import the jack module, Python crashes/exits.

I have installed:

  1. Jack library (via 64-bit Windows installer) I can run jackd.exe.
  2. This Jack client via pip. pip install JACK-Client.

Also can't find any errors/exceptions.

image
image

Am I doing something wrong or is that a bug? I have been trying to resolve this for about 2 hours, by trying different Python versions, this module versions (0.5.1, 0.5.0) etc. - could not find a solution on my own.

Connect to client that run on remote machine

Hi,
is there any way to connect to a client that run on different machine in the local-network?
Or to run JACK-Client in Docker container while manipulating the jack connection on the host?

Thanks

play audio in loop

hi,
i want to play a wav file in a loop.
I tried to modify playfile.py but without luck. My idea was to reset sndfile sf.seek(0) after all blocks put to queue.

any idea what's wrong?

Add Client.transport_reposition_struct()

... and probably a convenience function (Client.transport_reposition()) that's easier to use.

This would be interesting to test the timebase_master.py example (#19) and the "showtime" example (#20).

How to send sysex messages?

I am trying to use jackclient-python to send sysex messages, and it was unclear from the documentation how to do this. Can you give me a simple example?

The sysex message I'm trying to send is F0 7F 7F 06 02 F7 (MMC play)

Thanks! I love this project!

How To Access Multiple Soundcard?

I have 4 different sound devices with total of 20 inputs and 12 outputs. However, client.get_ports() only returns two system:capture and two system:playback ports.
How can I get access to different inputs/outputs in different audio interface?

Metadata example not working

I get an error when running the metadata example, JACK-Client 0.5.0, Python 3.7.3, Ubuntu 19.04:

Traceback (most recent call last):
  File "metadata.py", line 12, in <module>
    client.set_property(client, jack.METADATA_PRETTY_NAME, 'Best Client Ever')
  File "/home/user/.local/lib/python3.7/site-packages/jack.py", line 1520, in set_property
    .format(key, subject))
ValueError: Unable to set property 'http://jackaudio.org/metadata/pretty-name' for subject 0

Add Client.get_memoryview()?

Now we have get_array() for people who want to use NumPy and get_buffer() for those who don't.
get_buffer() provides bytes and users will have to convert the bytes to floats before they can do anything meaningful.

What about providing get_memoryview() that does the conversion for them (but still doesn't depend on an external library)?

memoryview.cast() is only available since Python 3.3, but I think that doesn't matter, users of older versions will simply get an AttributeError if they try to use it.

Any thoughts?

midi_chords.py

Hello, I apologize for adding this as an issue, but I don't see any other way of contact and/or my lack of understanding.

attempting to run midi_chords.py

With the code as provided:

@client.set_process_callback
def process(frames):

I get this at the console:

/usr/bin/python3.4 /home/mac/PycharmProjs/JackMIDITest/midi_chords.py
################################################################################
press Return to quit
################################################################################
From cffi callback <function Client.set_process_callback.<locals>.callback_wrapper at 0x7f28d3c04c80>:
Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/jack.py", line 720, in callback_wrapper
    return callback(frames, userdata)
TypeError: process() takes 1 positional argument but 2 were given

If I change the code to:

@client.set_process_callback
def process(frames, x):

It runs without error, but I see no midi output.
I made the following mod so as to see midi output:

with client:
    client.connect(outport,"MIDI monitor:midi_in")

The client shows up in Jack in both cases...

Can the examples be relicensed under public domain?

Can the examples be relicensed under public domain? They are a good starting point, but the requirement of retaining the copyright notice in the work derived from them doesn't seem appropriate to me.

Or am I missing something?

undefined symbol: Py_InitModule3

Hi *,

I installed with sudo python3 -m pip install JACK-Client --user.

If I try to import the module with import jack, I see the following error:

~ $ python3 midi_ctl.py
Traceback (most recent call last):
File "midi_ctl.py", line 3, in <module>
import jack
ImportError: /usr/local/lib/python3.5/dist-packages/jack.cpython-35m-x86_64-linux-gnu.so: undefined symbol: Py_InitModule3

Any ideas?

BR,
Ck

plot get_array() data in real-time

sorry if this is out of scope 😏, but i'm a python/audio-science noob and am just so happy how easy we can create a jack client with this library, so blamethank you! 😅

so for funsies, i wanted to "plot" the data coming from get_array(), in real-time... my first omg-it-does-something experiment:

screenshot

import jack
import numpy
import threading
import pygame

client  = jack.Client("foovju")
event   = threading.Event()
input_1 = client.inports.register("input_1")

black   = 0, 0, 0
white   = 255, 255, 255
size    = width, height = client.blocksize, int(client.blocksize / 2)
screen  = pygame.display.set_mode(size)

pygame.display.init()

@client.set_process_callback
def process(frames):
	assert frames == client.blocksize
	data = input_1.get_array()
	screen.fill(black)
	x = 0; h = height / 2
	for d in data:
		y = int(h * (d + 1))
		pygame.draw.rect(screen, white, [x, y, 1, 1])
		x += 1
	pygame.display.flip()

with client:
	print('Press Ctrl+C to stop')
	try:
		event.wait()
	except KeyboardInterrupt:
		print('\nInterrupted by user')

it uses ~50% of one ~3GHz cpu, and its "tanking" jack badly...

any tips or tricks on making this use less cpu? (or affect jack less)

pssst, wanna see some cool waves? try this as audio source: https://ultimae.bandcamp.com/track/security or for mind-blow, try: https://www.youtube.com/user/jerobeamfenderson1 ... dammit, now i wanna know how that oscilloscope works! :yet_another_rabbit_hole:

jack client closes itself just after start

hello,

I'm trying to figure how to keep the client running but it just shows up for a little

# coding=utf-8

import io
import logging
import sys

import jack
import soundfile as sf
import queue
import threading


BUFFERSIZE = 1024


class AudioLib:
    def __init__(self):

        self.log = logging.getLogger(__name__)
        self.log.info("INIT AUDIO LIB")

        self.buffersize = BUFFERSIZE

        self.queue = queue.Queue(maxsize=self.buffersize)
        self.event = threading.Event()

        self.jack_client = jack.Client('TEST', session_id='Test')

        self.blocksize = self.jack_client.blocksize
        self.samplerate = self.jack_client.samplerate

        self.jack_client.set_xrun_callback(self.xrun)
        self.jack_client.set_shutdown_callback(self.shutdown)
        self.jack_client.set_process_callback(self.process)

        self.voice_output_0 = self.jack_client.outports.register('voice_0')

        print("ACTIVATE")

        self.jack_client.activate()

        # self.jack_client.connect(self.voice_output_0, 'system:playback_1')

    def play(self, format, audio, fin):

        audio_samplerate, bits, channels = format

        with sf.SoundFile(io.BytesIO(audio),
                          channels=channels,
                          samplerate=audio_samplerate,
                          format='RAW',
                          subtype='FLOAT') as audio_stream:

            block_generator = audio_stream.blocks(blocksize=self.blocksize,
                                                  always_2d=True, fill_value=0)
            for _, data in zip(range(self.buffersize), block_generator):
                self.queue.put_nowait(data)  # Pre-fill queue

            timeout = self.blocksize * self.buffersize / self.samplerate
            for data in block_generator:
                self.queue.put(data, timeout=timeout)

            self.queue.put(None, timeout=timeout)  # Signal end of file
            self.event.wait()  # Wait until playback is

    def print_error(self, *args):
        print(*args, file=sys.stderr)

    def xrun(self, delay):
        self.print_error("An xrun occured, increase JACK's period size?")

    def shutdown(self, status, reason):
        self.print_error('JACK shutdown!')
        self.print_error('status:', status)
        self.print_error('reason:', reason)
        self.event.set()

    def stop_callback(self, msg=''):
        if msg:
            self.print_error(msg)
        for port in self.jack_client.outports:
            port.get_array().fill(0)
        self.event.set()
        raise jack.CallbackExit

    def process(self, frames):
        assert frames == self.jack_client.blocksize

        try:
            data = self.queue.get_nowait()
            for channel, port in zip(data.T, self.jack_client.outports):
                port.get_array()[:] = channel
        except queue.Empty:
            self.stop_callback('Buffer is empty: increase buffersize?')

        if data is None:
            self.stop_callback()  # Playback is finished
        else:
            for channel, port in zip(data.T, self.jack_client.outports):
                port.get_array()[:] = channel

this is mostly a rip off play file example

thanks

question: simple MIDI beeping

Hello,

first of all I'd like to thank you for this nice module. It's great to see it's not a dead project.

I have a problem/question. Let's say I want to create a simple application which writes MIDI beeps on output, Morse code for example. How can I do that? In all examples there is some trigger, like MIDI input, but I want my application to send those signals whenever it wants. Can I do it without callbacks?

I tried this, but it does not work:

import jack

client = jack.Client("MYMIDI")
outport = client.midi_outports.register("output")


@client.set_process_callback
def process(frames):
    outport.clear_buffer()
    i = client.frame_time
    outport.write_midi_event(i, (144, 36, 64))
    i += 1000
    outport.write_midi_event(i, (128, 36, 64))

with client:
    input()

Thanks very much,
Petr

Use RingBuffer in midi_monitor.py example

Printing to the terminal isn't allowed in the process callback.
The data should be transferred to a non-realtime thread for printing.

This could also be a nice usage example for the RingBuffer.

install problems related to lib/jack folder

If you install jackclient using pip without installing jack first, it becomes hard to fix the problem. To reproduce (i use anaconda, so my pip installs are all local by default).

  1. (Without jack installed) pip install JACK-Client
  2. Woops... sudo apt install multimedia-jack
  3. (With jack installed) pip uninstall JACK-Client
  4. (With jack installed) pip install JACK-Client

This install mistake brings up a very strange error where find_library returns a directory instead of a library. The ... dots aren't real, just hiding my file system for no particular reason.

>>> import jack 
OSError: cannot load library '.../miniconda3/envs/py3/lib/jack'
>>> from ctypes.util import find_library
>>> find_library("jack")
'.../miniconda3/envs/py3/lib/jack'

I fixed this eventually by:
step (3)
deleting the .../miniconda3/envs/py3/lib/jack directory
step (4)

Is it possible to delete this directory as a part of the pip uninstall process?

"timeout waiting for client" from jack daemon when using libjack calls from within port_registration_callback

Recently had an issue, where:

  • port_registration_callback (set via set_port_registration_callback() before activate()) function was running a bunch of libjack (through this module, ofc, code link) calls.
  • same-name port was registered twice during app lifetime.

And that caused client (current git master - c5982a3) to reliably crash with:

cannot read result for request type 10 from server (Connection reset by peer)
cannot send event response to engine (Broken pipe)
cannot continue execution of the processing graph (Bad file descriptor)
jack_client_thread: graph error - exiting from JACK

And JACK1 (0.124.1, Debian Jessie) logging something like:

Oct 11 06:43:42 Paging-Test6 jackd1-paging[801]: timeout waiting for client paging.812 to handle a port registered event
Oct 11 06:43:42 Paging-Test6 jackd1-paging[801]: cannot send port registration notification to paging.812 (No such file or directory)

This seem to be 100% reproducible in these kinda-specific conditions - i.e. when it's same port name being registered for the second time during client lifetime - no other calls to that callback seem to trigger it.
Can be easily reproduced with that particular app (before it was fixed not to call stuff from callbacks) by running alsa_out, closing it, then running it again - client drops with above symptoms.

Also, all connect() / disconnect() calls from within that callback seem to raise JackError, while actually creating/removing connections, for any ports.

So I wonder, is it expected (e.g. "calling stuff from callbacks is obviously bad!") or sensible behavior?

And if it is, maybe it should be documented under set_port_registration_callback?
I.e. something like "calling other libjack functions here may lead to unexpected behavior like deadlocks or client timeouts" there.
If so, I can probably create a PR, but given relative lack of JACK/client knowledge, I suspect I might not be best at describing what exactly should be avoided here.

Support for the metadata API?

First of all, thanks for this package! Helps a lot with neatly automating my setup :)

I was wondering if Jack's metadata API can be used through jackclient-python?
I couldn't find any references to it in the the current code, so maybe some work needs to be done to enable it? If so, what would that be? Maybe I can be of help.

example thru_client not working (Python 2.7)

When I try to run your example script thru_client.py with python2.7 (linux, ubuntu 14.10), I get:

$ python thru_client.py 
Press Ctrl+C to stop
From callback <function callback_wrapper at 0xb6f0aa3c>:
Trying to convert the result back to C:
TypeError: an integer is required

Any idea what's wrong?

My versions of dependencies:
JACK-Client==0.3.0
cffi==0.8.2

Detecting xruns in process callback

Hi and thanks for the great library, been using it for years!

What's the best way to detect if the last process callback lead to an xrun? Here's my use case: I'm sending MIDI, which works 99% of the time. But when an xrun occurs, the MIDI events aren't sent to connected inputs and on the next process callback I clear the buffer and they're lost forever. Here's how I'm currently doing it:

jack_midi_event_write = jack._lib.jack_midi_event_write

jack_port_get_buffer = jack._lib.jack_port_get_buffer


class Process:
    __slots__ = ('_before', '_buffer', '_client', '_port', '_xrun')

    def __init__(self, client: jack.Client, port: jack.OwnMidiPort) -> None:
        self._before = 0;
        self._buffer = jack.RingBuffer(2 ** 8)
        self._xrun = threading.Event()
        self._client = client
        self._port = port

    def process(self, frames: int) -> None:
        xrun = self._xrun
        xrun_set = xrun.is_set()
        port = self._port
        client = port._client
        last_frame_time = client.last_frame_time
        blocksize = client.blocksize

        if not xrun_set and last_frame_time - blocksize == self._before:
            port.clear_buffer()
        if xrun_set:
            xrun.clear()

        self._before = last_frame_time
        src_buffer = self._buffer
        space = src_buffer.read_space

        if space != 0:
            data = src_buffer.read(space)
            dst_buffer = jack_port_get_buffer(port._ptr, blocksize)
            i = 0
            while i != space:
                jack_midi_event_write(dst_buffer, 0, data[i : i + 3], 3)
                i += 3

    def handle_xrun(self, delay_usec: float) -> None:
        self._xrun.set()

    def _append(self, event: Tuple[int, int, int]) -> None:
        self._buffer.write(bytes(event))

    def note_on(self, note: int) -> None:
        self._append((0x99, note, 100))

    def note_off(self, note: int) -> None:
        self._append((0x89, note, 0))

I'm doing two things:

  1. I'm comparing last_frame_time - blocksize to the last_frame_time on the previous process callback.

  2. Using the set_xrun_callback to set a threading.Event()

I'm not sure if I'm doing any of this correctly, just experimenting to see what works. I know you're not meant to use Python for realtime, but it's working too well to justify moving to C++.

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.