diff options
Diffstat (limited to 'pd/src/s_audio_jack.c')
-rw-r--r-- | pd/src/s_audio_jack.c | 354 |
1 files changed, 182 insertions, 172 deletions
diff --git a/pd/src/s_audio_jack.c b/pd/src/s_audio_jack.c index 1e79b43b..7ab3a3f6 100644 --- a/pd/src/s_audio_jack.c +++ b/pd/src/s_audio_jack.c @@ -28,6 +28,8 @@ static jack_port_t *output_port[NUM_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; + pthread_mutex_t jack_mutex; pthread_cond_t jack_sem; @@ -36,42 +38,42 @@ pthread_cond_t jack_sem; static int process (jack_nframes_t nframes, void *arg) { - int j; - float *out; - float *in; - - + int j; + float *out; + float *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"); - - for (j = 0; j < sys_outchannels; j++) { - out = jack_port_get_buffer (output_port[j], nframes); - memcpy(out, jack_outbuf + (j * BUF_JACK), sizeof (float) * 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 (float) * nframes); - } - jack_filled -= nframes; - } else { /* PD could not keep up ! */ - if (jack_started) sys_log_error(ERR_RESYNC); - for (j = 0; j < outport_count; j++) { - out = jack_port_get_buffer (output_port[j], nframes); - memset(out, 0, sizeof (float) * nframes); - } - memset(jack_outbuf,0,sizeof(jack_outbuf)); - jack_filled = 0; - } - pthread_cond_broadcast(&jack_sem); - return 0; + else jack_out_max = JACK_OUT_MAX; + if (jack_filled >= nframes) { + if (jack_filled != nframes) fprintf(stderr,"Partial read"); + + for (j = 0; j < sys_outchannels; j++) { + out = jack_port_get_buffer (output_port[j], nframes); + memcpy(out, jack_outbuf + (j * BUF_JACK), sizeof (float) * 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 (float) * nframes); + } + jack_filled -= nframes; + } else { /* PD could not keep up ! */ + if (jack_started) jack_dio_error = 1; + for (j = 0; j < outport_count; j++) { + out = jack_port_get_buffer (output_port[j], nframes); + memset(out, 0, sizeof (float) * nframes); + } + memset(jack_outbuf,0,sizeof(jack_outbuf)); + jack_filled = 0; + } + pthread_cond_broadcast(&jack_sem); + return 0; } static int jack_srate (jack_nframes_t srate, void *arg) { - sys_dacsr = srate; + sys_dacsr = srate; return 0; } @@ -79,11 +81,11 @@ static void jack_shutdown (void *arg) { /* Ignore for now */ - // exit (1); + // exit (1); } static int jack_xrun(void* arg) { - sys_log_error(ERR_DACSLEPT); + jack_dio_error = 1; return 0; } @@ -131,19 +133,19 @@ static char** jack_get_clients(void) if( strcmp( "alsa_pcm", tmp_client_name ) == 0 && num_clients > 0 ) { - char* tmp; + char* tmp; /* alsa_pcm goes in spot 0 */ - tmp = jack_client_names[ num_clients ]; - jack_client_names[ num_clients ] = jack_client_names[0]; - jack_client_names[0] = tmp; - strcpy( jack_client_names[0], tmp_client_name); + tmp = jack_client_names[ num_clients ]; + jack_client_names[ num_clients ] = jack_client_names[0]; + jack_client_names[0] = tmp; + strcpy( jack_client_names[0], tmp_client_name); } else { /* put the new client at the end of the client list */ strcpy( jack_client_names[ num_clients ], tmp_client_name ); } - num_clients++; + num_clients++; } } @@ -170,20 +172,20 @@ static int jack_connect_ports(char* client) sprintf( regex_pattern, "%s:.*", client ); jack_ports = jack_get_ports( jack_client, regex_pattern, - NULL, JackPortIsOutput); + NULL, JackPortIsOutput); 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])); + fprintf (stderr, "cannot connect input ports %s -> %s\n", jack_ports[i],jack_port_name (input_port[i])); jack_ports = jack_get_ports( jack_client, regex_pattern, - NULL, JackPortIsInput); + NULL, JackPortIsInput); 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]); + fprintf (stderr, "cannot connect output ports %s -> %s\n", jack_port_name (output_port[i]),jack_ports[i]); @@ -201,168 +203,176 @@ int jack_open_audio(int inchans, int outchans, int rate) { - int j; - char port_name[80] = ""; - int client_iterator = 0; - int new_jack = 0; - int srate; - - if ((inchans == 0) && (outchans == 0)) return 0; - - if (outchans > NUM_JACK_PORTS) { - fprintf(stderr,"%d output ports not supported, setting to %d\n",outchans, NUM_JACK_PORTS); - outchans = NUM_JACK_PORTS; - } + int j; + char port_name[80] = ""; + int client_iterator = 0; + int new_jack = 0; + int srate; + + jack_dio_error = 0; + + if ((inchans == 0) && (outchans == 0)) return 0; + + 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 (inchans > NUM_JACK_PORTS) { + if (inchans > NUM_JACK_PORTS) { fprintf(stderr,"%d input ports not supported, setting to %d\n",inchans, NUM_JACK_PORTS); inchans = NUM_JACK_PORTS; } - /* 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 - 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 (jack_error); - + /* 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 + 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 (jack_error); + #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<NUM_JACK_PORTS;j++) { - input_port[j]=NULL; - output_port[j] = NULL; - } - - new_jack = 1; - } - - /* display the current sample rate. once the client is activated - (see below), you should rely on your own sample rate - callback (see above) for this value. - */ - - srate = jack_get_sample_rate (jack_client); - sys_dacsr = srate; - - /* create the ports */ - - for (j = 0; j < inchans; j++) { - sprintf(port_name, "input%d", j); - if (!input_port[j]) input_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); - } + + /* 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<NUM_JACK_PORTS;j++) { + input_port[j]=NULL; + output_port[j] = NULL; + } + + new_jack = 1; + } + + /* display the current sample rate. once the client is activated + (see below), you should rely on your own sample rate + callback (see above) for this value. + */ + + srate = jack_get_sample_rate (jack_client); + sys_dacsr = srate; + + /* create the ports */ + + for (j = 0; j < inchans; j++) { + sprintf(port_name, "input%d", j); + if (!input_port[j]) input_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); + } for (j = 0; j < outchans; j++) { - sprintf(port_name, "output%d", j); - if (!output_port[j]) output_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - } - outport_count = outchans; + sprintf(port_name, "output%d", j); + if (!output_port[j]) output_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + } + outport_count = outchans; /* tell the JACK server that we are ready to roll */ - if (new_jack) { - if (jack_activate (jack_client)) { - fprintf (stderr, "cannot activate client"); - return 1; - } - - memset(jack_outbuf,0,sizeof(jack_outbuf)); - - if (jack_client_names[0]) - jack_connect_ports(jack_client_names[0]); - - pthread_mutex_init(&jack_mutex,NULL); - pthread_cond_init(&jack_sem,NULL); - } - return 0; + if (new_jack) { + if (jack_activate (jack_client)) { + fprintf (stderr, "cannot activate client\n"); + sys_inchannels = sys_outchannels = 0; + return 1; + } + + memset(jack_outbuf,0,sizeof(jack_outbuf)); + + if (jack_client_names[0]) + jack_connect_ports(jack_client_names[0]); + + pthread_mutex_init(&jack_mutex,NULL); + pthread_cond_init(&jack_sem,NULL); + } + return 0; } void jack_close_audio(void) { - jack_started = 0; + jack_started = 0; } int jack_send_dacs(void) { - float * 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_filled >= 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(float)); - fp += DEFDACBLKSIZE; - } - fp = sys_soundin; - for (j = 0; j < sys_inchannels; j++) { - memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled, DEFDACBLKSIZE*sizeof(float)); - fp += DEFDACBLKSIZE; - } - - if ((timenow = sys_getrealtime()) - timeref > 0.002) - { - rtnval = SENDDACS_SLEPT; - } - - memset(sys_soundout,0,DEFDACBLKSIZE*sizeof(float)*sys_outchannels); - jack_filled += DEFDACBLKSIZE; - return rtnval; + float * 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; + } + if (jack_filled >= 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(float)); + fp += DEFDACBLKSIZE; + } + fp = sys_soundin; + for (j = 0; j < sys_inchannels; j++) { + memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled, DEFDACBLKSIZE*sizeof(float)); + fp += DEFDACBLKSIZE; + } + + if ((timenow = sys_getrealtime()) - timeref > 0.002) + { + rtnval = SENDDACS_SLEPT; + } + + memset(sys_soundout,0,DEFDACBLKSIZE*sizeof(float)*sys_outchannels); + jack_filled += DEFDACBLKSIZE; + return rtnval; } void jack_getdevs(char *indevlist, int *nindevs, char *outdevlist, int *noutdevs, int *canmulti, - int maxndev, int devdescsize) + int maxndev, int devdescsize) { int i, ndev; *canmulti = 0; /* supports multiple devices */ ndev = 1; for (i = 0; i < ndev; i++) { - sprintf(indevlist + i * devdescsize, "JACK"); - sprintf(outdevlist + i * devdescsize, "JACK"); + sprintf(indevlist + i * devdescsize, "JACK"); + sprintf(outdevlist + i * devdescsize, "JACK"); } *nindevs = *noutdevs = ndev; } |