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

Auto-connect to system output #100

Open
crsaracco opened this issue Nov 10, 2018 · 3 comments
Open

Auto-connect to system output #100

crsaracco opened this issue Nov 10, 2018 · 3 comments

Comments

@crsaracco
Copy link
Member

crsaracco commented Nov 10, 2018

Hi, bit of a Jack development noob here.

Initially I thought this crate was just not working, since I ran sine.rs and heard no output. However, I was messing around with qjackctl and found the "Connections" page, and found that if I manually connected the client's output port to the system:playback_1 and system:playback_2 ports, I could hear the output!

It seems like it doesn't do this by default when I launch the sine example, so I figured I'd try to connect it programmatically at the start of the program. I'm having trouble doing this, though. Here's what I've tried:

let spec = jack::AudioOut::default();
let mut out_port = client.register_port("sine_out_1", spec).unwrap();
let system_out_1 = client.port_by_name("system:playback_1").unwrap();
let connect_result = client.connect_ports(&out_port, &system_out_1);
println!("{:?}", connect_result);

The println just gives me:

Err(PortConnectionError("rust_jack_sine:sine_out_1", "system:playback_1"))

and obviously the program crashes when I try to unwrap it.

Did I do something wrong in setting up the connections? Or is something wrong with my setup somehow, since I assume the sine example just works for most other people?

Bitwig on my system can automatically connect to the jack server and output sound when I start it up, so I think my jack server settings are at least workable.

Not sure what system settings would be useful to debug this... I'm running Arch linux, if it matters. I can provide more details if needed.

@crsaracco
Copy link
Member Author

crsaracco commented Nov 11, 2018

So I looked into the C examples of Jack, and found something that worked for me.

In their example, you have to connect to the system playback ports after you activate the client, so that's what I did in my program:

// Connect the ports to the system output.
// You can't do this before the client is activated,
// because we can't make connections to clients that aren't running.
let client_out_1 = active_client.as_client().port_by_name("rust_jack_sine:sine_out_1").unwrap();
let system_out_1 = active_client.as_client().port_by_name("system:playback_1").unwrap();
let system_out_2 = active_client.as_client().port_by_name("system:playback_2").unwrap();
active_client.as_client().connect_ports(&client_out_1, &system_out_1);
active_client.as_client().connect_ports(&client_out_1, &system_out_2);

(There's probably a more robust way to do that, but I just wanted to get something working for now)

I'd suggest making a note in the documentation somewhere (or is it already there somewhere?) -- or maybe it's obvious to those that have used Jack before?

Either way, you can close this issue if you want :)

@wmedrano
Copy link
Member

You want active_client.as_client().connect_ports_by_name("rust_jack_sine:sine_out_1", "system:playback_1");
I may remove .connect_ports since it doesn't add much value and obfuscates that inactive ports can't be connected and in programs that create ports, it often requires creating an unowned clone or getting a port_by_name since ownership of the port is somewhere else.

Will keep it open as a sign to look into:

  • Autoconnecting, to reduce boilerplate that will be written by most programs.
  • Improve debugabilty of connect_ports

@crsaracco
Copy link
Member Author

crsaracco commented Nov 12, 2018

Oh, yep that's probably what I want. Missed that somehow.

One last thing: is there a more robust way to get the system's playback channels other than just assuming it's going to be "system:playback_1" and "system:playback_2"? (or is it always that in Jack?)

From what I could gather, I might be able to do it with:

let system_out_ports = active_client.as_client().ports(None, None, jack::PortFlags::IS_INPUT | jack::PortFlags::IS_PHYSICAL);

but I just wanted to double-check.

Thanks!

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

2 participants