static PyObject* is_realtime(PyObject* self, PyObject* args) { pyjack_client_t * client = self_or_global_client(self); if(client->pjc == NULL) { PyErr_SetString(JackNotConnectedError, "Jack connection has not yet been established."); return NULL; } int realtime = jack_is_realtime(client->pjc); return Py_BuildValue("i", realtime); }
static void *midi_thread(void *arg) { midi_stream_t *str = arg; alsa_rawmidi_t *midi = str->owner; struct pollfd pfds[MAX_PFDS]; int npfds; jack_time_t wait_nsec = 1000*1000*1000; // 1 sec process_midi_t proc; proc.midi = midi; proc.mode = str->mode; pfds[0].fd = str->wake_pipe[0]; pfds[0].events = POLLIN|POLLERR|POLLNVAL; npfds = 1; if (jack_is_realtime(midi->client)) set_threaded_log_function(); //debug_log("midi_thread(%s): enter", str->name); while (midi->keep_walking) { int poll_timeout; int wait_nanosleep; int r=1, w=1; // read,write pos in pfds int rp=0, wp=0; // read, write pos in ports // sleep //if (wait_nsec != 1000*1000*1000) { // debug_log("midi_thread(%s): ", str->name); // assert (wait_nsec == 1000*1000*1000); //} poll_timeout = wait_nsec / (1000*1000); wait_nanosleep = wait_nsec % (1000*1000); if (wait_nanosleep > NANOSLEEP_RESOLUTION) { struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = wait_nanosleep; clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL); } int res = poll((struct pollfd*)&pfds, npfds, poll_timeout); //debug_log("midi_thread(%s): poll exit: %d", str->name, res); if (!midi->keep_walking) break; if (res < 0) { if (errno == EINTR) continue; error_log("midi_thread(%s) poll failed: %s", str->name, strerror(errno)); break; } // check wakeup pipe if (pfds[0].revents & ~POLLIN) break; if (pfds[0].revents & POLLIN) { char c; read(pfds[0].fd, &c, 1); } // add new ports while (jack_ringbuffer_read_space(str->midi.new_ports) >= sizeof(midi_port_t*) && str->midi.nports < MAX_PORTS) { midi_port_t *port; jack_ringbuffer_read(str->midi.new_ports, (char*)&port, sizeof(port)); str->midi.ports[str->midi.nports++] = port; debug_log("midi_thread(%s): added port %s", str->name, port->name); } // if (res == 0) // continue; // process ports proc.cur_time = 0; //jack_frame_time(midi->client); proc.next_time = NFRAMES_INF; for (rp = 0; rp < str->midi.nports; ++rp) { midi_port_t *port = str->midi.ports[rp]; proc.cur_time = jack_frame_time(midi->client); proc.port = port; proc.rpfds = &pfds[r]; proc.wpfds = &pfds[w]; proc.max_pfds = MAX_PFDS - w; r += port->npfds; if (!(str->process_midi)(&proc)) { port->state = PORT_REMOVED_FROM_MIDI; // this signals to jack thread continue; // this effectively removes port from array } w += port->npfds; if (rp != wp) str->midi.ports[wp] = port; ++wp; } if (str->midi.nports != wp) debug_log("midi_%s: nports %d -> %d", str->name, str->midi.nports, wp); str->midi.nports = wp; if (npfds != w) debug_log("midi_%s: npfds %d -> %d", str->name, npfds, w); npfds = w; /* * Input : ports do not set proc.next_time. * Output: port sets proc.next_time ONLY if it does not have queued data. * So, zero timeout will not cause busy-looping. */ if (proc.next_time < proc.cur_time) { debug_log("%s: late: next_time = %d, cur_time = %d", str->name, (int)proc.next_time, (int)proc.cur_time); wait_nsec = 0; // we are late } else if (proc.next_time != NFRAMES_INF) { jack_time_t wait_frames = proc.next_time - proc.cur_time; jack_nframes_t rate = jack_get_sample_rate(midi->client); wait_nsec = (wait_frames * (1000*1000*1000)) / rate; debug_log("midi_%s: timeout = %d", str->name, (int)wait_frames); } else wait_nsec = 1000*1000*1000; //debug_log("midi_thread(%s): wait_nsec = %lld", str->name, wait_nsec); } return NULL; }
static int alsa_rawmidi_start(alsa_midi_t *m) { alsa_rawmidi_t *midi = (alsa_rawmidi_t*)m; int err; char c = 'q'; if (midi->keep_walking == 1) return -EALREADY; midi->keep_walking = 1; if ((err = jack_client_create_thread(midi->client, &midi->in.thread, MIDI_THREAD_PRIO, jack_is_realtime(midi->client), midi_thread, &midi->in))) { midi->keep_walking = 0; return err; } if ((err = jack_client_create_thread(midi->client, &midi->out.thread, MIDI_THREAD_PRIO, jack_is_realtime(midi->client), midi_thread, &midi->out))) { midi->keep_walking = 0; write(midi->in.wake_pipe[1], &c, 1); pthread_join(midi->in.thread, NULL); return err; } if ((err = jack_client_create_thread(midi->client, &midi->scan.thread, 0, 0, scan_thread, midi))) { midi->keep_walking = 0; write(midi->in.wake_pipe[1], &c, 1); write(midi->out.wake_pipe[1], &c, 1); pthread_join(midi->in.thread, NULL); pthread_join(midi->out.thread, NULL); return err; } return 0; }
/***************************************************************************** * * JACK_INIT() * * Setup the jack client. * *****************************************************************************/ int jack_init(void) { const char *server_name = NULL; static char client_name[32]; jack_options_t options = JackNoStartServer | JackUseExactName; jack_status_t status = 0; if (debug) { fprintf (stderr, "Initializing JACK client from thread 0x%lx\n", pthread_self()); } if (client != NULL) { if (debug) { fprintf (stderr, "Warning: closing stale JACK client...\n"); } jack_client_close (client); client = NULL; } /* open a client connection to the JACK server */ for( phasex_instance = 0; phasex_instance != 16; phasex_instance++) { if(!phasex_instance) { snprintf (client_name, 32, "%s", phasex_title); } else { snprintf (client_name, 32, "%s-%02d", phasex_title, phasex_instance); } printf("Using client name %s\n", client_name); if (client = jack_client_open ((const char *)client_name, options, &status, server_name)) break; } /* deal with non-unique client name */ if (status & JackNameNotUnique) { fprintf (stderr, "Unable to start JACK client '%s'!\n", client_name); return 1; } /* deal with jack server problems */ if (status & (JackServerFailed | JackServerError)) { if (debug) { fprintf (stderr, "Unable to connect to JACK server. Status = 0x%2.0x\n", status); } return 1; } /* deal with missing client */ if (client == NULL) { if (debug) { fprintf (stderr, "Unable to open JACK client. Status = 0x%2.0x\n", status); } return 1; } /* callback for when jack shuts down (needs to be set as early as possible) */ jack_on_shutdown (client, jack_shutdown_handler, 0); if (debug) { fprintf (stderr, "Unique JACK client name '%s' assigned.\n", client_name); } /* notify if we started jack server */ if (status & JackServerStarted) { fprintf (stderr, "JACK server started.\n"); } /* report realtime scheduling in JACK */ if (debug) { if (jack_is_realtime (client)) { fprintf (stderr, "JACK is running with realtime scheduling.\n"); } else { fprintf (stderr, "JACK is running without realtime scheduling.\n"); } } /* get sample rate early and notify other threads */ sample_rate = jack_get_sample_rate (client); if (debug) { fprintf (stderr, "JACK sample rate: %d\n", sample_rate); } /* scale sample rate depending on mode */ switch (sample_rate_mode) { case SAMPLE_RATE_UNDERSAMPLE: sample_rate /= 2; break; case SAMPLE_RATE_OVERSAMPLE: sample_rate *= 2; break; } /* set samplerate related vars */ f_sample_rate = (sample_t)sample_rate; nyquist_freq = (sample_t)(sample_rate / 2); wave_period = (sample_t)(F_WAVEFORM_SIZE / (double)sample_rate); if (debug) { fprintf (stderr, "Internal sample rate: %d\n", sample_rate); } /* callback for setting our sample rate when jack tells us to */ jack_set_sample_rate_callback (client, jack_samplerate_handler, 0); /* now that we have the sample rate, signal anyone else who needs to know */ pthread_mutex_lock (&sample_rate_mutex); pthread_cond_broadcast (&sample_rate_cond); pthread_mutex_unlock (&sample_rate_mutex); /* get buffer size */ buffer_size = jack_get_buffer_size (client) * 2; if (buffer_size > (PHASEX_MAX_BUFSIZE / 2)) { fprintf (stderr, "JACK requested buffer size: %d. Max is: %d.\n", buffer_size, (PHASEX_MAX_BUFSIZE / 2)); fprintf (stderr, "JACK buffer size exceeded. Closing client...\n"); jack_client_close (client); client = NULL; jack_running = 0; return 1; } buffer_full = buffer_size; if (debug) { fprintf (stderr, "JACK output buffer size: %d.\n", buffer_size); } /* callback for setting our buffer size when jack tells us to */ jack_set_buffer_size_callback (client, jack_bufsize_handler, 0); /* callback for dealing with xruns */ jack_set_xrun_callback (client, jack_xrun_handler, 0); /* create ports */ input_port1 = jack_port_register (client, "in_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); input_port2 = jack_port_register (client, "in_2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); output_port1 = jack_port_register (client, "out_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); output_port2 = jack_port_register (client, "out_2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if ( (output_port1 == NULL) || (output_port2 == NULL) || (input_port1 == NULL) || (input_port2 == NULL) ) { fprintf (stderr, "JACK has no output ports available.\n"); jack_client_close (client); client = NULL; jack_running = 0; return 0; } /* set callback for jack to grab audio data */ jack_set_process_callback (client, process_buffer, 0); return 0; }
static int _is_realtime(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj* const *objv) { _t *dp = (_t *)clientData; if (argc != 2) return fw_error_str(interp, "jack-client is-realtime"); Tcl_SetObjResult(interp, Tcl_NewIntObj(jack_is_realtime(dp->fw.client))); return TCL_OK; }
int luajack_is_realtime(luajack_t *client) { cud_t *cud = get_cud(client); if(!cud) return 0; return jack_is_realtime(cud->client); }