From 21c068f1916330e90f814bed461fe0821d1665ec Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sun, 9 Oct 2011 16:36:37 +0000 Subject: checked in pd-0.43-0.src.tar.gz svn path=/trunk/; revision=15557 --- pd/src/s_audio_jack.c | 517 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 328 insertions(+), 189 deletions(-) (limited to 'pd/src/s_audio_jack.c') diff --git a/pd/src/s_audio_jack.c b/pd/src/s_audio_jack.c index 990a7a8c..79d4692e 100644 --- a/pd/src/s_audio_jack.c +++ b/pd/src/s_audio_jack.c @@ -11,25 +11,24 @@ #include #include - #define MAX_CLIENTS 100 -#define NUM_JACK_PORTS 128 /* seems like higher values give bad xrun problems */ +#define MAX_JACK_PORTS 128 /* seems like higher values give bad xrun problems */ #define BUF_JACK 4096 static jack_nframes_t jack_out_max; #define JACK_OUT_MAX 64 static jack_nframes_t jack_filled = 0; -static t_sample jack_outbuf[NUM_JACK_PORTS*BUF_JACK]; -static t_sample jack_inbuf[NUM_JACK_PORTS*BUF_JACK]; +static t_sample *jack_outbuf; +static t_sample *jack_inbuf; static int jack_started = 0; -static jack_port_t *input_port[NUM_JACK_PORTS]; -static jack_port_t *output_port[NUM_JACK_PORTS]; +static jack_port_t *input_port[MAX_JACK_PORTS]; +static jack_port_t *output_port[MAX_JACK_PORTS]; static int outport_count = 0; static jack_client_t *jack_client = NULL; char *jack_client_names[MAX_CLIENTS]; static int jack_dio_error; - +static t_audiocallback jack_callback; pthread_mutex_t jack_mutex; pthread_cond_t jack_sem; @@ -38,56 +37,114 @@ pthread_cond_t jack_sem; static int process (jack_nframes_t nframes, void *arg) { - int j; - jack_default_audio_sample_t *out, *in; - - if (nframes > JACK_OUT_MAX) jack_out_max = nframes; - else jack_out_max = JACK_OUT_MAX; - if (jack_filled >= nframes) { - if (jack_filled != nframes) fprintf(stderr,"Partial read"); - /* hmm, how to find out whether 't_sample' and 'jack_default_audio_sample_t' are actually the same type??? */ - if(sizeof(t_sample)==sizeof(jack_default_audio_sample_t)) + int j; + jack_default_audio_sample_t *out, *in; + + pthread_mutex_lock(&jack_mutex); + if (nframes > JACK_OUT_MAX) jack_out_max = nframes; + else jack_out_max = JACK_OUT_MAX; + if (jack_filled >= nframes) + { + if (jack_filled != nframes) + fprintf(stderr,"Partial read\n"); + /* hmm, how to find out whether 't_sample' and + 'jack_default_audio_sample_t' are actually the same type??? */ + if (sizeof(t_sample)==sizeof(jack_default_audio_sample_t)) + { + for (j = 0; j < sys_outchannels; j++) + { + out = jack_port_get_buffer (output_port[j], nframes); + memcpy(out, jack_outbuf + (j * BUF_JACK), + sizeof (jack_default_audio_sample_t) * nframes); + } + for (j = 0; j < sys_inchannels; j++) + { + in = jack_port_get_buffer( input_port[j], nframes); + memcpy(jack_inbuf + (j * BUF_JACK), in, + sizeof (jack_default_audio_sample_t) * nframes); + } + } + else + { + unsigned int frame=0; + t_sample*data; + for (j = 0; j < sys_outchannels; j++) + { + out = jack_port_get_buffer (output_port[j], nframes); + data = jack_outbuf + (j * BUF_JACK); + for(frame=0; frame=MAX_CLIENTS)break; + + /* extract the client name from the port name, using a regex * that parses the clientname:portname syntax */ regexec( &port_regex, jack_ports[i], 1, &match_info, 0 ); @@ -166,7 +234,6 @@ static char** jack_get_clients(void) strcpy( jack_client_names[ num_clients ], tmp_client_name ); } num_clients++; - } } @@ -196,7 +263,7 @@ static int jack_connect_ports(char* client) if (jack_ports) for (i=0;jack_ports[i] != NULL && i < sys_inchannels;i++) if (jack_connect (jack_client, jack_ports[i], jack_port_name (input_port[i]))) - fprintf (stderr, "cannot connect input ports %s -> %s\n", jack_ports[i],jack_port_name (input_port[i])); + error ("JACK: cannot connect input ports %s -> %s", jack_ports[i],jack_port_name (input_port[i])); @@ -205,7 +272,7 @@ static int jack_connect_ports(char* client) if (jack_ports) for (i=0;jack_ports[i] != NULL && i < sys_outchannels;i++) if (jack_connect (jack_client, jack_port_name (output_port[i]), jack_ports[i])) - fprintf (stderr, "cannot connect output ports %s -> %s\n", jack_port_name (output_port[i]),jack_ports[i]); + error( "JACK: cannot connect output ports %s -> %s", jack_port_name (output_port[i]),jack_ports[i]); @@ -214,172 +281,244 @@ static int jack_connect_ports(char* client) } -void pd_jack_error_callback(const char *desc) { +static void pd_jack_error_callback(const char *desc) { + error("JACKerror: %s", desc); return; } - int -jack_open_audio(int inchans, int outchans, int rate) - +jack_open_audio(int inchans, int outchans, int rate, t_audiocallback callback) { - int j; - char port_name[80] = ""; - int client_iterator = 0; - int new_jack = 0; - int srate; + int j; + char port_name[80] = ""; + char client_name[80] = ""; - jack_dio_error = 0; - - if ((inchans == 0) && (outchans == 0)) return 0; + int client_iterator = 0; + int new_jack = 0; + int srate; + jack_status_t status; - if (outchans > NUM_JACK_PORTS) { - fprintf(stderr,"%d output ports not supported, setting to %d\n",outchans, NUM_JACK_PORTS); - outchans = NUM_JACK_PORTS; - } + if (NULL==jack_client_new) + { + fprintf(stderr,"JACK framework not available\n"); + return 1; + } + + jack_dio_error = 0; + + if ((inchans == 0) && (outchans == 0)) return 0; - if (inchans > NUM_JACK_PORTS) { - fprintf(stderr,"%d input ports not supported, setting to %d\n",inchans, NUM_JACK_PORTS); - inchans = NUM_JACK_PORTS; + if (outchans > MAX_JACK_PORTS) { + error("JACK: %d output ports not supported, setting to %d", + outchans, MAX_JACK_PORTS); + outchans = MAX_JACK_PORTS; + } + + if (inchans > MAX_JACK_PORTS) { + error("JACK: %d input ports not supported, setting to %d", + inchans, MAX_JACK_PORTS); + inchans = MAX_JACK_PORTS; + } + /* try to become a client of the JACK server */ + /* if no JACK server exists, start a default one (jack_client_open() does that for us... */ + if (!jack_client) { + do { + sprintf(client_name,"pure_data_%d",client_iterator); + client_iterator++; + jack_client = jack_client_open (client_name, JackNullOption, &status, NULL); + if (status & JackServerFailed) { + error("JACK: unable to connect to JACK server"); + jack_client=NULL; + break; + } + } while (status & JackNameNotUnique); + + if(status) { + if (status & JackServerStarted) { + verbose(1, "JACK: started server"); + } else { + error("JACK: server returned status %d", status); + } } + verbose(1, "JACK: started server as '%s'", client_name); - /* try to become a client of the JACK server (we allow two pd's)*/ if (!jack_client) { - do { - sprintf(port_name,"pure_data_%d",client_iterator); - client_iterator++; - } while (((jack_client = jack_client_new (port_name)) == 0) && client_iterator < 2); - - - if (!jack_client) { // jack spits out enough messages already, do not warn + /* jack spits out enough messages already, do not warn */ sys_inchannels = sys_outchannels = 0; return 1; - } - - jack_get_clients(); - - /* tell the JACK server to call `process()' whenever - there is work to be done. - */ - - jack_set_process_callback (jack_client, process, 0); - - jack_set_error_function (pd_jack_error_callback); - + } + + sys_inchannels = inchans; + sys_outchannels = outchans; + if (jack_inbuf) + free(jack_inbuf); + if (sys_inchannels) + jack_inbuf = calloc(sizeof(t_sample), sys_inchannels * BUF_JACK); + if (jack_outbuf) + free(jack_outbuf); + if (sys_outchannels) + jack_outbuf = calloc(sizeof(t_sample), sys_outchannels * BUF_JACK); + + jack_get_clients(); + + /* tell the JACK server to call `process()' whenever + there is work to be done. + */ + jack_callback = callback; + jack_set_process_callback (jack_client, + (callback? callbackprocess : process), 0); + + jack_set_error_function (pd_jack_error_callback); + #ifdef JACK_XRUN - jack_set_xrun_callback (jack_client, jack_xrun, NULL); + jack_set_xrun_callback (jack_client, jack_xrun, NULL); #endif - - /* tell the JACK server to call `srate()' whenever - the sample rate of the system changes. - */ - - jack_set_sample_rate_callback (jack_client, jack_srate, 0); - - - /* tell the JACK server to call `jack_shutdown()' if - it ever shuts down, either entirely, or if it - just decides to stop calling us. - */ - - jack_on_shutdown (jack_client, jack_shutdown, 0); - - for (j=0;j= jack_out_max) - pthread_cond_wait(&jack_sem,&jack_mutex); - - jack_started = 1; - - fp = sys_soundout; - for (j = 0; j < sys_outchannels; j++) { - memcpy(jack_outbuf + (j * BUF_JACK) + jack_filled,fp, DEFDACBLKSIZE*sizeof(t_sample)); - fp += DEFDACBLKSIZE; - } - fp = sys_soundin; - for (j = 0; j < sys_inchannels; j++) { - memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled, DEFDACBLKSIZE*sizeof(t_sample)); - fp += DEFDACBLKSIZE; - } + t_sample * fp; + int j; + int rtnval = SENDDACS_YES; + int timenow; + int timeref = sys_getrealtime(); + if (!jack_client) return SENDDACS_NO; + if (!sys_inchannels && !sys_outchannels) return (SENDDACS_NO); + if (jack_dio_error) + { + sys_log_error(ERR_RESYNC); + jack_dio_error = 0; + } + pthread_mutex_lock(&jack_mutex); + if (jack_filled >= jack_out_max) + pthread_cond_wait(&jack_sem,&jack_mutex); - if ((timenow = sys_getrealtime()) - timeref > 0.002) - { - rtnval = SENDDACS_SLEPT; - } + if (!jack_client) + { + pthread_mutex_unlock(&jack_mutex); + return SENDDACS_NO; + } + jack_started = 1; - memset(sys_soundout,0,DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels); - jack_filled += DEFDACBLKSIZE; - return rtnval; + fp = sys_soundout; + for (j = 0; j < sys_outchannels; j++) + { + memcpy(jack_outbuf + (j * BUF_JACK) + jack_filled, fp, + DEFDACBLKSIZE*sizeof(t_sample)); + fp += DEFDACBLKSIZE; + } + fp = sys_soundin; + for (j = 0; j < sys_inchannels; j++) + { + memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled, + DEFDACBLKSIZE*sizeof(t_sample)); + fp += DEFDACBLKSIZE; + } + jack_filled += DEFDACBLKSIZE; + pthread_mutex_unlock(&jack_mutex); + + if ((timenow = sys_getrealtime()) - timeref > 0.002) + { + rtnval = SENDDACS_SLEPT; + } + memset(sys_soundout, 0, DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels); + return rtnval; } void jack_getdevs(char *indevlist, int *nindevs, -- cgit v1.2.1