int jack_process_callback(jack_nframes_t nframes, void* arg) { struct jack_data* data = (struct jack_data*)arg; if (data == 0) return 0; pthread_mutex_lock(&data->jack_mutex); struct obs_source_audio out; out.speakers = jack_channels_to_obs_speakers(data->channels); out.samples_per_sec = jack_get_sample_rate (data->jack_client); /* format is always 32 bit float for jack */ out.format = AUDIO_FORMAT_FLOAT_PLANAR; for (unsigned int i = 0; i < data->channels; ++i) { jack_default_audio_sample_t *jack_buffer = (jack_default_audio_sample_t *)jack_port_get_buffer( data->jack_ports[i], nframes); out.data[i] = (uint8_t *)jack_buffer; } out.frames = nframes; out.timestamp = os_gettime_ns() - jack_frames_to_time(data->jack_client, nframes); obs_source_output_audio(data->source, &out); pthread_mutex_unlock(&data->jack_mutex); return 0; }
static int _frames_to_time(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj* const *objv) { _t *dp = (_t *)clientData; if (argc != 3) return fw_error_str(interp, "jack-client frames-to-time frames"); jack_nframes_t frames; if (Tcl_GetIntFromObj(interp, objv[2], &frames) != TCL_OK) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewIntObj(jack_frames_to_time(dp->fw.client, frames))); return TCL_OK; }
static int handle_process(jack_nframes_t frames, void *arg) { jack_midi_data_t *buffer; jack_midi_event_t event; jack_nframes_t event_count; jack_nframes_t event_time; jack_nframes_t frame; size_t i; jack_nframes_t last_frame_time; jack_midi_data_t *message; jack_time_t microseconds; void *port_buffer; jack_time_t time; jack_midi_clear_buffer(jack_port_get_buffer(out_port, frames)); switch (process_state) { case 0: /* State: initializing */ switch (wait_semaphore(init_semaphore, 0)) { case -1: set_process_error(SOURCE_WAIT_SEMAPHORE, get_semaphore_error()); /* Fallthrough on purpose */ case 0: return 0; } highest_latency = 0; lowest_latency = 0; messages_received = 0; messages_sent = 0; process_state = 1; total_latency = 0; total_latency_time = 0; unexpected_messages = 0; xrun_count = 0; jack_port_get_latency_range(remote_in_port, JackCaptureLatency, &in_latency_range); jack_port_get_latency_range(remote_out_port, JackPlaybackLatency, &out_latency_range); goto send_message; case 1: /* State: processing */ port_buffer = jack_port_get_buffer(in_port, frames); event_count = jack_midi_get_event_count(port_buffer); last_frame_time = jack_last_frame_time(client); for (i = 0; i < event_count; i++) { jack_midi_event_get(&event, port_buffer, i); message = (messages_received % 2) ? message_2 : message_1; if ((event.size == message_size) && (! memcmp(message, event.buffer, message_size * sizeof(jack_midi_data_t)))) { goto found_message; } unexpected_messages++; } microseconds = jack_frames_to_time(client, last_frame_time) - last_activity_time; if ((microseconds / 1000000) >= timeout) { set_process_error(SOURCE_PROCESS, ERROR_MSG_TIMEOUT); } break; found_message: event_time = last_frame_time + event.time; frame = event_time - last_activity; time = jack_frames_to_time(client, event_time) - last_activity_time; if ((! highest_latency) || (frame > highest_latency)) { highest_latency = frame; highest_latency_time = time; } if ((! lowest_latency) || (frame < lowest_latency)) { lowest_latency = frame; lowest_latency_time = time; } latency_time_values[messages_received] = time; latency_values[messages_received] = frame; total_latency += frame; total_latency_time += time; messages_received++; if (messages_received == samples) { process_state = 2; if (! signal_semaphore(process_semaphore)) { /* Sigh ... */ die(SOURCE_SIGNAL_SEMAPHORE, get_semaphore_error()); } break; } send_message: frame = (jack_nframes_t) ((((double) rand()) / RAND_MAX) * frames); if (frame >= frames) { frame = frames - 1; } port_buffer = jack_port_get_buffer(out_port, frames); buffer = jack_midi_event_reserve(port_buffer, frame, message_size); if (buffer == NULL) { set_process_error(SOURCE_EVENT_RESERVE, ERROR_RESERVE); break; } message = (messages_sent % 2) ? message_2 : message_1; memcpy(buffer, message, message_size * sizeof(jack_midi_data_t)); last_activity = jack_last_frame_time(client) + frame; last_activity_time = jack_frames_to_time(client, last_activity); messages_sent++; case 2: /* State: finished - do nothing */ case -1: /* State: error - do nothing */ case -2: /* State: signalled - do nothing */ ; } return 0; }
jack_time_t luajack_frames_to_time(luajack_t *client, jack_nframes_t nframes) { cud_t *cud = get_cud(client); if(!cud) return 0; return jack_frames_to_time(cud->client, nframes); }