struct cbox_audio_output *cbox_jackio_create_audio_out(struct cbox_io_impl *impl, const char *name, GError **error) { struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl; jack_port_t *port = jack_port_register(jii->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (!port) { g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot create output audio port '%s'", name); return FALSE; } struct cbox_jack_audio_output *output = calloc(1, sizeof(struct cbox_jack_audio_output)); output->hdr.name = g_strdup(name); output->hdr.removing = FALSE; output->port = port; output->jii = jii; cbox_uuid_generate(&output->hdr.uuid); return (struct cbox_audio_output *)output; }
struct cbox_midi_input *cbox_jackio_create_midi_in(struct cbox_io_impl *impl, const char *name, GError **error) { struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl; jack_port_t *port = jack_port_register(jii->client, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); if (!port) { g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot create input MIDI port '%s'", name); return FALSE; } struct cbox_jack_midi_input *input = calloc(1, sizeof(struct cbox_jack_midi_input)); input->hdr.name = g_strdup(name); input->hdr.removing = FALSE; input->port = port; input->jii = jii; cbox_uuid_generate(&input->hdr.uuid); cbox_midi_buffer_init(&input->hdr.buffer); return (struct cbox_midi_input *)input; }
static void run_audio_loop(struct cbox_usb_io_impl *uii) { while(!uii->stop_engine && !uii->device_removed) { struct cbox_io *io = uii->ioi.pio; struct timeval tv = { .tv_sec = 0, .tv_usec = 1000 }; libusb_handle_events_timeout(uii->usbctx, &tv); for (GSList *p = io->midi_outputs; p; p = p->next) { struct cbox_usb_midi_output *umo = p->data; usbio_send_midi_to_output(umo); } } } void usbio_run_idle_loop(struct cbox_usb_io_impl *uii) { while(!uii->stop_engine) { struct cbox_io *io = uii->ioi.pio; for (int b = 0; b < uii->output_channels; b++) memset(io->output_buffers[b], 0, io->io_env.buffer_size * sizeof(float)); io->cb->process(io->cb->user_data, io, io->io_env.buffer_size); for (GList *p = uii->rt_midi_ports; p; p = p->next) { struct cbox_usb_midi_interface *umi = p->data; cbox_midi_buffer_clear(&umi->input_port->hdr.buffer); } for (GSList *p = io->midi_outputs; p; p = p->next) { struct cbox_usb_midi_output *umo = p->data; usbio_send_midi_to_output(umo); } struct timeval tv = { .tv_sec = 0, .tv_usec = 1 }; libusb_handle_events_timeout(uii->usbctx, &tv); usleep((int)(io->io_env.buffer_size * 1000000.0 / uii->sample_rate)); } } static void *engine_thread(void *user_data) { struct cbox_usb_io_impl *uii = user_data; usbio_start_midi_capture(uii); if (uii->handle_audiodev) { uii->no_resubmit = FALSE; struct sched_param p; memset(&p, 0, sizeof(p)); p.sched_priority = cbox_config_get_int("io", "rtpriority", 10); pid_t tid = syscall(SYS_gettid); if (0 != sched_setscheduler(tid, SCHED_FIFO, &p)) g_warning("Cannot set realtime priority for the processing thread: %s.", strerror(errno)); usbio_start_audio_playback(uii); if (!uii->setup_error) { run_audio_loop(uii); } uii->no_resubmit = TRUE; memset(&p, 0, sizeof(p)); p.sched_priority = 0; if (0 != sched_setscheduler(tid, SCHED_OTHER, &p)) g_warning("Cannot unset realtime priority for the processing thread: %s.", strerror(errno)); usbio_stop_audio_playback(uii); } else { uii->no_resubmit = TRUE; g_message("No audio device found - running idle loop."); // notify the UI thread that the (fake) audio loop is running uii->playback_counter = uii->playback_buffers; usbio_run_idle_loop(uii); } usbio_stop_midi_capture(uii); return NULL; } static void cbox_usbio_destroy_midi_out(struct cbox_io_impl *ioi, struct cbox_midi_output *midiout) { g_free(midiout->name); free(midiout); } static struct cbox_usb_midi_interface *cur_midi_interface = NULL; struct cbox_midi_input *cbox_usbio_create_midi_in(struct cbox_io_impl *impl, const char *name, GError **error) { // struct cbox_usb_io_impl *uii = (struct cbox_usb_io_impl *)impl; struct cbox_usb_midi_input *input = calloc(1, sizeof(struct cbox_usb_midi_input)); input->hdr.name = g_strdup(name); input->hdr.removing = FALSE; cbox_uuid_generate(&input->hdr.uuid); cbox_midi_buffer_init(&input->hdr.buffer); input->ifptr = cur_midi_interface; cbox_midi_appsink_init(&input->hdr.appsink, NULL); input->hdr.enable_appsink = FALSE; return (struct cbox_midi_input *)input; } struct cbox_midi_output *cbox_usbio_create_midi_out(struct cbox_io_impl *impl, const char *name, GError **error) { // struct cbox_usb_io_impl *uii = (struct cbox_usb_io_impl *)impl; struct cbox_usb_midi_output *output = calloc(1, sizeof(struct cbox_usb_midi_output)); output->hdr.name = g_strdup(name); output->hdr.removing = FALSE; cbox_uuid_generate(&output->hdr.uuid); cbox_midi_buffer_init(&output->hdr.buffer); cbox_midi_merger_init(&output->hdr.merger, &output->hdr.buffer); output->ifptr = cur_midi_interface; return (struct cbox_midi_output *)output; } static void create_midi_ports(struct cbox_usb_io_impl *uii) { uii->ioi.createmidiinfunc = cbox_usbio_create_midi_in; uii->ioi.createmidioutfunc = cbox_usbio_create_midi_out; for (GList *p = uii->midi_ports; p; p = p->next) { struct cbox_usb_midi_interface *umi = p->data; char buf[80]; sprintf(buf, "usb:%03d:%03d", umi->devinfo->bus, umi->devinfo->devadr); cur_midi_interface = umi; if (umi->epdesc_in.found) umi->input_port = (struct cbox_usb_midi_input *)cbox_io_create_midi_input(uii->ioi.pio, buf, NULL); else umi->input_port = NULL; if (umi->epdesc_out.found) umi->output_port = (struct cbox_usb_midi_output *)cbox_io_create_midi_output(uii->ioi.pio, buf, NULL); else umi->output_port = NULL; } uii->ioi.createmidiinfunc = NULL; uii->ioi.createmidioutfunc = NULL; cur_midi_interface = NULL; }