Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API for starting and controlling a JACK server? #90

Closed
jsl303 opened this issue Jul 26, 2020 · 21 comments
Closed

API for starting and controlling a JACK server? #90

jsl303 opened this issue Jul 26, 2020 · 21 comments

Comments

@jsl303
Copy link

jsl303 commented Jul 26, 2020

Is there python binding for API to start and control a JACK server?
https://jackaudio.org/api/group__ControlAPI.html
I wasn't able to find them in the documentation.
I'd love to control how it starts the server like setting inputs and outputs, sampling rate, and so on.

@mgeier
Copy link
Member

mgeier commented Jul 26, 2020

No, I wasn't even aware that such an API exists!

Do you want to implement it?

@jsl303
Copy link
Author

jsl303 commented Jul 26, 2020

Unfortunately beyond my head...

@HaHeho
Copy link

HaHeho commented Jul 27, 2020

I found this jack_control in the documentation of the Website Repo. Also never heard about or used it.
https://github.com/jackaudio/jackaudio.github.com/wiki/WalkThrough_User_jack_control

Maybe the tool is long gone and not maintained anymore. However, there might be code left that is worth checking out. Maybe it can be "revived" for the specific features you are interested in.

@jsl303
Copy link
Author

jsl303 commented Jul 27, 2020 via email

@HaHeho
Copy link

HaHeho commented Jul 27, 2020

https://github.com/jackaudio/jack2/blob/develop/example-clients/jack_control

Fount this. So it still seems to exist in the current code base. And apparently even Python 3. However, the file has no .py ending. The implementation of the command line parameter parsing is done by hand ... by manually iterating over the parameters. I mean it looks awful, but maybe it's not better with argparse. I kind of doubt that tho. Probably just a very old implementation that nobody really cares to improve.

However, it might provide exactly the functionality you want. Let is know if you were successful or have problems making it work.

@mgeier
Copy link
Member

mgeier commented Aug 4, 2020

Is jack_control supposed to come with Jack?

On my Debian Linux system it's included with the JACK package.

If I understand correctly, the jack_control script doesn't actually use the "control API" mentioned above, but it uses dbus, right?

I just had a quick look and it looks like in the JACK1 repo there are Python bindings for the "jackctl" API: https://github.com/jackaudio/jack1/blob/master/python/jackctl.py

Be that as it may, we can try to implement the control API in jackclient-python anyway.

@jsl303 Which functions do you actually need?
Which ones do you think are nice to have?
Which are useless in our case?

@jsl303
Copy link
Author

jsl303 commented Aug 4, 2020 via email

@HaHeho
Copy link

HaHeho commented Aug 5, 2020

It is possible to set the buffer size of instantiated JACK clients with this API (see property below). This can be done before actually starting the client, so no adaptation is required. Doing this for a client will update this setting for the entire jackd server and other clients. Is that correct @mgeier ?

def blocksize(self):

However, the option above is only available to the buffer size and not the sampling rate for example. Hence, a proper API to administrate jackd might be desirable. This should also provide to not only set, but also receive information on the parameters and status of the server of course.

Also, one should always keep in mind that it is possible to run multiple jackd servers at a time, right? I have no idea what viable use cases are or if this actually utilized by someone. However, a server API should definitely support that, I guess.

@mgeier
Copy link
Member

mgeier commented Aug 10, 2020

Doing this for a client will update this setting for the entire jackd server and other clients. Is that correct @mgeier ?

I'm not sure, but I think so.

Here's the call to jack_set_buffer_size():

@blocksize.setter
def blocksize(self, blocksize):
_check(_lib.jack_set_buffer_size(self._ptr, blocksize),
'Error setting JACK blocksize')

I've never actually used this, though, so I don't know if that works in practice.

However, the option above is only available to the buffer size and not the sampling rate for example.

Yes, it looks like that. There seems to be only jack_get_sample_rate() but no jack_set_sample_rate(): https://jackaudio.org/api/group__ServerControl.html

The sample rate can change, though, at least theoretically, because there is jack_set_sample_rate_callback(), which is available as Client.set_samplerate_callback().

Also, one should always keep in mind that it is possible to run multiple jackd servers at a time, right?

Yes, I think so. I have never used multiple servers, though.

But there has been an issue with multiple servers: #46.

@mgeier
Copy link
Member

mgeier commented Aug 10, 2020

It looks like jackctl_server_create() has been deprecated in JACK2 (in favor of jackctl_server_create2()):

https://github.com/jackaudio/jack2/blob/34fb7b6963864380cf1ab48fe575faed62afd2f0/common/jack/control.h#L122-L148

@mgeier
Copy link
Member

mgeier commented Aug 10, 2020

Did anyone of you try https://github.com/jackaudio/jack1/blob/master/python/jackctl.py?

I'm unable to create a jackctl.Server object because of many errors similar to this:

Could not open component .so '/usr/lib/x86_64-linux-gnu/jack/jack_alsa.so': /usr/lib/x86_64-linux-gnu/jack/jack_alsa.so: undefined symbol: _ZTIN4Jack15JackAudioDriverE
Could not open component .so '/usr/lib/x86_64-linux-gnu/jack/jack_alsa.so': /usr/lib/x86_64-linux-gnu/jack/jack_alsa.so: undefined symbol: _ZTIN4Jack15JackAudioDriverE
jack_get_descriptor : dll jack_alsa.so is not a driver
jack_get_descriptor returns null for 'jack_alsa.so'

When I try to manually call jackctl_server_create()/jackctl_server_create2() (using CFFI instead of ctypes), I get the same errors.

Apart from these problems, it's a bit strange to include this in the jackclient-python project, because:

  • it's not a "client"
  • it needs a separate library named libjackserver.so (instead of libjack.so)

It would probably be better to create a separate project for this?

@HaHeho
Copy link

HaHeho commented Aug 13, 2020

Did anyone of you try https://github.com/jackaudio/jack1/blob/master/python/jackctl.py?

No.

Apart from these problems, it's a bit strange to include this in the jackclient-python project, because:

* it's not a "client"

* it needs a separate library named `libjackserver.so` (instead of `libjack.so`)

It would probably be better to create a separate project for this?

Totally.

@abarker
Copy link

abarker commented Dec 27, 2020

I wrote this simple wrapper API for the jack_control module to allow it to be imported and run from Python. It may be useful to someone. To the extent that the jack_control script works and is maintained, this gives you the same commands. It's a little ugly (to work around the fact that the main() function in jack_control always looks at sys.argv and writes to sys.stdout), but should be reliable.

"""

Run the jack_control program, with source code linked below, from Python.
   https://github.com/jackaudio/jack2/blob/develop/tools/jack_control

"""

import sys
import io
import jack_control as jc # Must be in `sys.path` list with `.py` extension.

class FakeSys:
    pass

jc.sys = FakeSys # Override the `sys` module that was imported in jc.

def jack_control(*args):
    """Run `jack_control` as if it were called from the command-line with the
    parameter strings as command-line arguments.  Returns the exit code and
    the string that would have been written to stdout."""
    args = [str(a) for a in args] # Convert any ints which were passed in.
    jc.sys.argv = ["jack_control"] + args

    old_sys_stdout = sys.stdout
    sys.stdout = io.StringIO()
    retcode = jc.main() # Call the real `jack_control` function.
    msg = sys.stdout.getvalue()
    sys.stdout = old_sys_stdout

    return retcode, msg

# Test.
if __name__ == "__main__":

    exit_code, msg = jack_control("help") # Get help message.
    print(msg) # Print the help message (redirected from stdout).

    # Toggle start/stop state.
    status_code, msg = jack_control("status")
    if status_code == 0:
        jack_control("stop")
    else:
        jack_control("start")
    print("Status msg is:\n", msg)

    # Get the long description for the engine parameter "driver".
    exit_code, msg = jack_control("epd", "driver")
    print(msg)

    # Set the "rate" parameter.
    exit_code, msg = jack_control("dps", "rate", 44100)
    print("Rate set exit code was:", exit_code)
    print("Rate set msg:\n", msg, sep="")

@takanoha001
Copy link

I agree to @jsl303 it would be so nice if we could control sampling rate, buffer size, and so on from this python layer. : )

@mgeier
Copy link
Member

mgeier commented Jan 14, 2021

I think it would be better to have this functionality in a separate module (in a separate project) because this is done by a different library (see #90 (comment)).

@takanoha001 Do you want to start such a project?

@vrslev
Copy link
Contributor

vrslev commented Feb 1, 2022

Hey there! I created a package to control JACK server with Python. It uses Jack Control API and is kind of modern replacement for jackctl.

@jsl303 @mgeier @abarker @HaHeho @takanoha001
Check it out guys! https://github.com/vrslev/jack_server

@mgeier
Copy link
Member

mgeier commented Feb 1, 2022

Cool @vrslev, I've added a link to the docs: #114.

I guess we can close this issue now?

@vrslev
Copy link
Contributor

vrslev commented Feb 1, 2022

Amazing, thanks! I plan to maintain that package, so probably yes.

@vrslev
Copy link
Contributor

vrslev commented Mar 15, 2022

@mgeier Should the issue be closed?

@mgeier
Copy link
Member

mgeier commented Mar 15, 2022

Yes, I think this can be closed.

If there are further questions or suggestions, everyone should feel free to add a comment here or create a new issue.

@mgeier mgeier closed this as completed Mar 15, 2022
@Hi-Angel
Copy link

Hi-Angel commented Nov 6, 2023

However, the option above is only available to the buffer size and not the sampling rate for example.

Yes, it looks like that. There seems to be only jack_get_sample_rate() but no jack_set_sample_rate(): https://jackaudio.org/api/group__ServerControl.html

FTR, in JACK implementation by Pipewire there is a jack_set_sample_rate function since 0.3.84 release

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants