/* ----------------------- Experimental routines for jack -------------- */ #ifdef USEAPI_JACK #include #include #include #include "m_pd.h" #include "s_stuff.h" #include #include #define MAX_CLIENTS 100 #define NUM_JACK_PORTS 32 #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 int jack_started = 0; static jack_port_t *input_port[NUM_JACK_PORTS]; 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; 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)) { 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 0 ) { 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); } else { /* put the new client at the end of the client list */ strcpy( jack_client_names[ num_clients ], tmp_client_name ); } num_clients++; } } /* for (i=0;i 96) return -1; sprintf( regex_pattern, "%s:.*", client ); jack_ports = jack_get_ports( jack_client, regex_pattern, 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])); jack_ports = jack_get_ports( jack_client, regex_pattern, 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]); free(jack_ports); return 0; } void pd_jack_error_callback(const char *desc) { return; } 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; 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) { 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 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); #ifdef JACK_XRUN 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; } if ((timenow = sys_getrealtime()) - timeref > 0.002) { rtnval = SENDDACS_SLEPT; } memset(sys_soundout,0,DEFDACBLKSIZE*sizeof(t_sample)*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 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"); } *nindevs = *noutdevs = ndev; } void jack_listdevs( void) { post("device listing not implemented for jack yet\n"); } #endif /* JACK */