On Wed, May 27, 2009 at 07:24:02PM -0500, Gabriel M. Beddingfield wrote:
>
> Hi Jorge,
>
> On Wed, May 27, 2009 6:35 pm, Jorge Cardona wrote:
> > I'm trying to understand how works jack, but i'm stuck on the way that
> > the callbacks at the clients are called from the server. Is there a
> > signaling system, like the posix signals? i was reading the code, but
> > i can't find where exactly is stored the client process function
> > pointer, and when is called.
>
> For Jack1, look in engine.c for jack_engine_process(). Whenever it wants
> to call the client callbacks, this is the function that does it. The
> JSList* node holds a linked-list to all the client data (void*
> node->data). For each client, either jack_process_internal() or
> jack_process_external() is called.
>
> Inside jack_process_internal(), you'll find:
>
> jack_client_internal_t *client;
> jack_client_control_t *ctl;
>
> client = (jack_client_internal_t *) node->data;
> ctl = client->control;
>
> And later on:
>
> if (ctl->process_cbset)
> if (client->private_client->process (nframes,
> client->private_client->process_arg)) {
> jack_error ("internal client %s failed", ctl->name);
> engine->process_errors++;
> }
>
> ctl->process_cbset is a flag indicating whether or not the callback has
> been set. If so, client->private_client->process is the pointer to the
> callback.
note that client->private_client->process only exists in the clients
address space.
I also think the question was rather how to implement a similar system,
and how the control is passed around processes.
So internal clients are not really relevant here.
jack is a lot cleverer, than described here.
between the invocation of the process callbacks of two clients, control
will not be transfered to jackd, the external clients transfer control,
by writing a byte into a pipe, where the next process is blocking on.
look at libjack/client.c: jack_client_thread_aux()
this is where it all happens.
------------------------------------------------------------------------------------
static void
jack_client_thread_aux (void *arg)
{
jack_client_t *client = (jack_client_t *) arg;
jack_client_control_t *control = client->control;
pthread_mutex_lock (&client_lock);
client->thread_ok = TRUE;
client->thread_id = pthread_self();
pthread_cond_signal (&client_ready);
pthread_mutex_unlock (&client_lock);
control->pid = getpid();
control->pgrp = getpgrp();
DEBUG ("client thread is now running");
if (control->thread_init_cbset) {
DEBUG ("calling client thread init callback");
client->thread_init (client->thread_init_arg);
}
/* wait for first wakeup from server */
if (jack_thread_first_wait (client) == control->nframes) {
/* now run till we're done */
if (control->process_cbset) {
/* run process callback, then wait... ad-infinitum */
while (1) {
DEBUG("client calls process()");
int status = (client->process (control->nframes,
client->process_arg) ==
control->nframes);
control->state = Finished;
DEBUG("client leaves process(), re-enters wait");
if (!jack_thread_wait (client, status)) {
break;
}
DEBUG("client done with wait");
}
} else {
/* no process handling but still need to process events */
while (jack_thread_wait (client, 0) == control->nframes)
;
}
}
jack_client_thread_suicide (client);
}
-------------------------------------------------------------------------------------
note that these fds are setup during the graphchange step, where
processing is suspended.
--
torben Hohn
http://galan.sourceforge.net -- The graphical Audio language
_______________________________________________
Jack-Devel mailing list
Jack-Devel@...
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org