Related


Links

Am I free?


Social bookmarking

Delicious Bookmark this on Delicious


Tweets
Flickr randomness


Badges and junk

Support The Commons

Valid HTML 4.01 Strict
Valid CSS!













Unless you are using something like qjackconnect, you probably wouldn't have noticed that the simple client already had a connection between a capture port and its input and a playback port and its output. jack_lsp can show you these connections, however, if you use the -c option. It can do more than that, even, use "jack_lsp --help" to see what.

How did the simple client manage such a thing? Take a look in the source and you'll see:

        if ((ports = jack_get_ports (client, NULL, NULL, 
                               JackPortIsPhysical|JackPortIsOutput)) == NULL) {
                fprintf(stderr, "Cannot find any physical capture ports\n");
                exit(1);
        }

        if (jack_connect (client, ports[0], jack_port_name (input_port))) {
                fprintf (stderr, "cannot connect input ports\n");
        }

        free (ports);

        if ((ports = jack_get_ports (client, NULL, NULL, 
                               JackPortIsPhysical|JackPortIsInput)) == NULL) {
                fprintf(stderr, "Cannot find any physical playback ports\n");
                exit(1);
        }

        if (jack_connect (client, jack_port_name (output_port), ports[0])) {
                fprintf (stderr, "cannot connect output ports\n");
        }

        free (ports);

So what's happening here? Let's look at the first piece of code on its own:

        if ((ports = jack_get_ports (client, NULL, NULL, 
                               JackPortIsPhysical|JackPortIsOutput)) == NULL) {
                fprintf(stderr, "Cannot find any physical capture ports\n");
                exit(1);
        }

The first thing to do is take a look at the documentation for jack_get_ports. The important part: "This function returns a NULL-terminated array of ports that match the specified arguments. The caller is responsible for calling free(3) any non-NULL returned value". Fair enough. Notice how this is used:

Thanks to Tommi Uimonen for suggesting that the concept of input and output ports could do with more explaining. Rather than paraphrase, here's what Tommi had to say:

Take a look from JACK's point of view; where it can get the data from and where it can put it to. After all, JACK is a connection kit, think about the wires between the soundcard and your amplifier, you being the JACK in the middle trying to connect them. You see that something is coming from the soundcard to you, it is Input from your point of view. And where do you deliver it to? You see a tiny hole on the back of your amplifier, it's obvious Output for you.

Back to the jack_get_ports function:. if this function returns NULL, there were no physical ports (and the simpleclient terminates), otherwise, we have a NULL terminated array of ports. The first port in the array is then connected to our input port. Here's the relevant section on it's own:

        if (jack_connect (client, ports[0], jack_port_name (input_port))) {
                fprintf (stderr, "cannot connect input ports\n");
        }

        free (ports);

The key function here is jack_connect. It's purpose is clear enough - it connects ports - but lets take a look at the documentation to see how it should be used.

Simple enough. The method returns 0 on success and a non-zero error code otherwise. It's also worth noting that the ports must be given the right way around: the flags of each port are checked to make sure that the source port is an output port and the destination port is an input port.

Also note that in the simple client, we passed "jack_port_name (input_port)". Another new function! This is because the jack_connect function expects character arrays to identify the ports, i.e. the names of the ports, not the structures representing the ports.The jack_port_name function simply finds the name of our input port. Interestingly, the names referred to here are the same as the names we use to refer to ports when we use jack_connect. Put the following line of code somewhere in the simple client, just before the sleep, for example, and see for yourself:

 	printf("%s\n",jack_port_name (input_port));

The output-port-connecting code works in exactly the same way.

The last piece of code we need to look at is the one that simply states "free (ports);". This is fairly obvious, and simply frees up the space used by the array of port names. Don't forget to do it, though - the onus is upon the caller to free the memory, not JACK. This is stressed in the API documentation, and Tommi Uimonen quite rightly suggested that I stress it here, too.

Fed up with mono beeps?

Then lets move into the amazing world of stereo beeps!

Look at the section of code that deals with finding and connecting to the playback ports:

if ((ports = jack_get_ports (client, NULL, NULL, 
                               JackPortIsPhysical|JackPortIsInput)) == NULL) {
                fprintf(stderr, "Cannot find any physical playback ports\n");
                exit(1);
        }

        if (jack_connect (client, jack_port_name (output_port), ports[0])) {
                fprintf (stderr, "cannot connect output ports\n");
        }

        free (ports);

Now, remember that jack_get_ports will return an array of port names (terminated by NULL) based on the flags. In this case, it will return an array of ports that are both physical and output. So, on a standard system with 2 physical output ports (left and right), we will have two ports in the array. To make stereo beeps, all we need to do is connect the simple client output to every port in the returned array. Here's the modified code:

	if ((ports = jack_get_ports (client, NULL, NULL, 
                               JackPortIsPhysical|JackPortIsInput)) == NULL) {
		fprintf(stderr, "Cannot find any physical playback ports\n");
		exit(1);
	}
	
	int i=0;
	while(ports[i]!=NULL){
	  if (jack_connect (client, jack_port_name (output_port), ports[i])) {
	    fprintf (stderr, "cannot connect output ports\n");
	  }
	  i++;
	}

	free (ports);

Simple, eh? Compile this and make sure it works - connect the metronome, or any other noise-maker, and use "jack_connect -c" to see what connections have been made.

Top - Previous - Next