Implement a nicer version of str() for Python wrapper objects.
[calfbox.git] / usbio.c
bloba2159e4e9e104d7b5bacebd71f3b3cbec06d1199
1 /*
2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2013 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 /*
21 Note: this is a silly experimental driver for a number of USB MIDI devices.
23 It only supports audio output and MIDI input, as those are my immediate
24 needs, to be able to use a machine running CalfBox as a standalone MIDI
25 instrument. Plug-and-play is supported, as long as current user running
26 calfbox has write access to the USB devices involved. This can be done by
27 running calfbox as root, or by setting right permissions in udev scripts
28 - this may be considered a safer method.
30 Devices supported:
31 * Class-compliant audio output devices (tested with Lexicon Omega and some
32 cheap no-brand C-Media USB soundcard dongle)
33 * Alesis Multimix 8 USB 2.0 (audio output only)
34 * Class-compliant MIDI input devices (tested with several devices)
36 Yes, code quality is pretty awful, especially in areas involving clock
37 sync. I'm going to clean it up iteratively later.
41 #include "config.h"
42 #include "config-api.h"
43 #include "errors.h"
44 #include "hwcfg.h"
45 #include "io.h"
46 #include "meter.h"
47 #include "midi.h"
48 #include "recsrc.h"
49 #include "usbio_impl.h"
51 #include <assert.h>
52 #include <errno.h>
53 #include <libusb.h>
54 #include <math.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <syscall.h>
59 #include <unistd.h>
60 #include <sys/mman.h>
62 ///////////////////////////////////////////////////////////////////////////////
64 int cbox_usbio_get_sample_rate(struct cbox_io_impl *impl)
66 struct cbox_usb_io_impl *uii = (struct cbox_usb_io_impl *)impl;
68 return uii->sample_rate;
71 gboolean cbox_usbio_get_status(struct cbox_io_impl *impl, GError **error)
73 // XXXKF: needs a flag that would indicate whether device is present
74 // XXXKF: needs to return that flag with appropriate message
75 return TRUE;
78 static void run_audio_loop(struct cbox_usb_io_impl *uii)
80 while(!uii->stop_engine && !uii->device_removed) {
81 struct cbox_io *io = uii->ioi.pio;
82 struct timeval tv = {
83 .tv_sec = 0,
84 .tv_usec = 1000
86 libusb_handle_events_timeout(uii->usbctx, &tv);
87 for (GSList *p = io->midi_outputs; p; p = p->next)
89 struct cbox_usb_midi_output *umo = p->data;
90 usbio_send_midi_to_output(umo);
95 void usbio_run_idle_loop(struct cbox_usb_io_impl *uii)
97 while(!uii->stop_engine)
99 struct cbox_io *io = uii->ioi.pio;
100 for (int b = 0; b < uii->output_channels; b++)
101 memset(io->output_buffers[b], 0, io->io_env.buffer_size * sizeof(float));
102 io->cb->process(io->cb->user_data, io, io->io_env.buffer_size);
103 for (GList *p = uii->rt_midi_ports; p; p = p->next)
105 struct cbox_usb_midi_interface *umi = p->data;
106 cbox_midi_buffer_clear(&umi->midi_buffer);
108 for (GSList *p = io->midi_outputs; p; p = p->next)
110 struct cbox_usb_midi_output *umo = p->data;
111 usbio_send_midi_to_output(umo);
114 struct timeval tv = {
115 .tv_sec = 0,
116 .tv_usec = 1
118 libusb_handle_events_timeout(uii->usbctx, &tv);
119 usleep((int)(io->io_env.buffer_size * 1000000.0 / uii->sample_rate));
123 static void *engine_thread(void *user_data)
125 struct cbox_usb_io_impl *uii = user_data;
127 usbio_start_midi_capture(uii);
129 if (uii->handle_audiodev)
131 uii->no_resubmit = FALSE;
132 struct sched_param p;
133 memset(&p, 0, sizeof(p));
134 p.sched_priority = cbox_config_get_int("io", "rtpriority", 10);
135 pid_t tid = syscall(SYS_gettid);
136 if (0 != sched_setscheduler(tid, SCHED_FIFO, &p))
137 g_warning("Cannot set realtime priority for the processing thread: %s.", strerror(errno));
139 usbio_start_audio_playback(uii);
140 if (!uii->setup_error)
142 run_audio_loop(uii);
144 uii->no_resubmit = TRUE;
145 memset(&p, 0, sizeof(p));
146 p.sched_priority = 0;
147 if (0 != sched_setscheduler(tid, SCHED_OTHER, &p))
148 g_warning("Cannot unset realtime priority for the processing thread: %s.", strerror(errno));
149 usbio_stop_audio_playback(uii);
151 else
153 uii->no_resubmit = TRUE;
154 g_message("No audio device found - running idle loop.");
155 // notify the UI thread that the (fake) audio loop is running
156 uii->playback_counter = uii->playback_buffers;
157 usbio_run_idle_loop(uii);
160 usbio_stop_midi_capture(uii);
161 return NULL;
164 static void cbox_usbio_destroy_midi_out(struct cbox_io_impl *ioi, struct cbox_midi_output *midiout)
166 g_free(midiout->name);
167 free(midiout);
170 static struct cbox_usb_midi_interface *cur_midi_interface = NULL;
172 struct cbox_midi_output *cbox_usbio_create_midi_out(struct cbox_io_impl *impl, const char *name, GError **error)
174 // struct cbox_usb_io_impl *uii = (struct cbox_usb_io_impl *)impl;
175 struct cbox_usb_midi_output *output = calloc(1, sizeof(struct cbox_usb_midi_output));
176 output->hdr.name = g_strdup(name);
177 output->hdr.removing = FALSE;
178 cbox_uuid_generate(&output->hdr.uuid);
179 cbox_midi_buffer_init(&output->hdr.buffer);
180 cbox_midi_merger_init(&output->hdr.merger, &output->hdr.buffer);
181 output->ifptr = cur_midi_interface;
183 return (struct cbox_midi_output *)output;
186 static void create_midi_outputs(struct cbox_usb_io_impl *uii)
188 uii->ioi.createmidioutfunc = cbox_usbio_create_midi_out;
189 for (GList *p = uii->midi_ports; p; p = p->next)
191 struct cbox_usb_midi_interface *umi = p->data;
192 if (umi->epdesc_out.found)
194 char buf[80];
195 sprintf(buf, "usb:%03d:%03d", umi->devinfo->bus, umi->devinfo->devadr);
197 cur_midi_interface = umi;
198 cbox_io_create_midi_output(uii->ioi.pio, buf, NULL);
201 uii->ioi.createmidioutfunc = NULL;
202 cur_midi_interface = NULL;
205 gboolean cbox_usbio_start(struct cbox_io_impl *impl, struct cbox_command_target *fb, GError **error)
207 struct cbox_usb_io_impl *uii = (struct cbox_usb_io_impl *)impl;
209 // XXXKF: needs to queue the playback and capture transfers
211 uii->stop_engine = FALSE;
212 uii->setup_error = FALSE;
213 uii->playback_counter = 0;
215 if (pthread_create(&uii->thr_engine, NULL, engine_thread, uii))
217 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "cannot create engine thread: %s", strerror(errno));
218 return FALSE;
220 while(!uii->setup_error && uii->playback_counter < uii->playback_buffers)
221 usleep(10000);
223 create_midi_outputs(uii);
225 return TRUE;
228 gboolean cbox_usbio_stop(struct cbox_io_impl *impl, GError **error)
230 struct cbox_usb_io_impl *uii = (struct cbox_usb_io_impl *)impl;
232 // XXXKF: needs to kill the playback and capture transfers, and
233 // wait for them to be killed
235 uii->stop_engine = TRUE;
236 pthread_join(uii->thr_engine, NULL);
237 return TRUE;
240 void cbox_usbio_poll_ports(struct cbox_io_impl *impl, struct cbox_command_target *fb)
242 struct cbox_usb_io_impl *uii = (struct cbox_usb_io_impl *)impl;
244 // Dry run, just to detect if anything changed
245 if (usbio_scan_devices(uii, TRUE))
247 g_debug("Restarting I/O due to device being connected or disconnected");
248 cbox_usbio_stop(&uii->ioi, NULL);
249 // Re-scan, this time actually create the MIDI inputs
250 usbio_scan_devices(uii, FALSE);
251 cbox_usbio_start(&uii->ioi, fb, NULL);
255 gboolean cbox_usbio_cycle(struct cbox_io_impl *impl, struct cbox_command_target *fb, GError **error)
257 // struct cbox_usb_io_impl *uii = (struct cbox_usb_io_impl *)impl;
258 // XXXKF: this is for restarting the thing; not implemented for now,
259 // the implementation will be something like in case of JACK - close and
260 // reopen.
261 return TRUE;
264 int cbox_usbio_get_midi_data(struct cbox_io_impl *impl, struct cbox_midi_buffer *destination)
266 struct cbox_usb_io_impl *uii = (struct cbox_usb_io_impl *)impl;
268 cbox_midi_merger_render_to(&uii->midi_input_merger, destination);
269 return 0;
272 void cbox_usbio_destroy(struct cbox_io_impl *impl)
274 struct cbox_usb_io_impl *uii = (struct cbox_usb_io_impl *)impl;
276 GList *prev_keys = g_hash_table_get_values(uii->device_table);
277 for (GList *p = prev_keys; p; p = p->next)
279 struct cbox_usb_device_info *udi = p->data;
280 if (udi->status == CBOX_DEVICE_STATUS_OPENED)
281 usbio_forget_device(uii, udi);
283 g_list_free(prev_keys);
284 g_hash_table_destroy(uii->device_table);
286 libusb_exit(uii->usbctx_probe);
287 libusb_exit(uii->usbctx);
288 cbox_midi_merger_close(&uii->midi_input_merger);
289 free(uii);
292 ///////////////////////////////////////////////////////////////////////////////
294 struct usbio_transfer *usbio_transfer_new(struct libusb_context *usbctx, const char *transfer_type, int index, int isopackets, void *user_data)
296 struct usbio_transfer *p = malloc(sizeof(struct usbio_transfer));
297 p->usbctx = usbctx;
298 p->transfer = libusb_alloc_transfer(isopackets);
299 p->index = index;
300 p->cancel_confirm = FALSE;
301 p->pending = FALSE;
302 p->transfer_type = transfer_type;
303 p->user_data = user_data;
304 return p;
307 int usbio_transfer_submit(struct usbio_transfer *xfer)
309 int res = libusb_submit_transfer(xfer->transfer);
310 if (res != 0)
312 g_warning("usbio_transfer_submit: cannot submit transfer '%s:%d', error = %s", xfer->transfer_type, xfer->index, libusb_error_name(res));
313 return res;
315 xfer->pending = TRUE;
316 return 0;
319 void usbio_transfer_shutdown(struct usbio_transfer *xfer)
321 if (xfer->pending)
323 int res = libusb_cancel_transfer(xfer->transfer);
324 if (res != LIBUSB_ERROR_NO_DEVICE)
326 int tries = 100;
327 while(!xfer->cancel_confirm && tries > 0 && xfer->pending)
329 struct timeval tv = {
330 .tv_sec = 0,
331 .tv_usec = 1000
333 libusb_handle_events_timeout(xfer->usbctx, &tv);
334 tries--;
336 if (!tries)
337 g_warning("Timed out waiting for transfer '%s:%d' to complete; status = %d", xfer->transfer_type, xfer->index, xfer->transfer->status);
342 void usbio_transfer_destroy(struct usbio_transfer *xfer)
344 libusb_free_transfer(xfer->transfer);
345 free(xfer);
349 ///////////////////////////////////////////////////////////////////////////////
351 static gboolean cbox_usb_io_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error)
353 struct cbox_usb_io_impl *uii = (struct cbox_usb_io_impl *)ct->user_data;
354 struct cbox_io *io = uii->ioi.pio;
355 gboolean handled = FALSE;
356 if (!strcmp(cmd->command, "/status") && !strcmp(cmd->arg_types, ""))
358 if (!cbox_check_fb_channel(fb, cmd->command, error))
359 return FALSE;
361 for (GList *p = uii->midi_ports; p; p = g_list_next(p))
363 struct cbox_usb_midi_interface *midi = p->data;
364 struct cbox_usb_device_info *di = midi->devinfo;
365 if (midi->epdesc_in.found && !cbox_execute_on(fb, NULL, "/usb_midi_input", "iiii", error, di->bus, di->devadr, di->vid, di->pid))
366 return FALSE;
367 if (midi->epdesc_out.found && !cbox_execute_on(fb, NULL, "/usb_midi_output", "iiii", error, di->bus, di->devadr, di->vid, di->pid))
368 return FALSE;
371 return cbox_execute_on(fb, NULL, "/output_resolution", "i", error, 8 * uii->output_resolution) &&
372 cbox_io_process_cmd(io, fb, cmd, error, &handled);
374 else
376 gboolean result = cbox_io_process_cmd(io, fb, cmd, error, &handled);
377 if (!handled)
378 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Unknown combination of target path and argument: '%s', '%s'", cmd->command, cmd->arg_types);
379 return result;
383 ///////////////////////////////////////////////////////////////////////////////
385 gboolean cbox_io_init_usb(struct cbox_io *io, struct cbox_open_params *const params, struct cbox_command_target *fb, GError **error)
387 struct cbox_usb_io_impl *uii = malloc(sizeof(struct cbox_usb_io_impl));
388 if (libusb_init(&uii->usbctx))
390 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot initialise libusb.");
391 return FALSE;
393 if (libusb_init(&uii->usbctx_probe))
395 libusb_exit(uii->usbctx);
396 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot initialise libusb.");
397 return FALSE;
399 libusb_set_debug(uii->usbctx, 3);
400 libusb_set_debug(uii->usbctx_probe, 3);
401 uii->device_table = g_hash_table_new(g_direct_hash, NULL);
403 uii->sample_rate = cbox_config_get_int(cbox_io_section, "sample_rate", 44100);
404 uii->sync_buffers = cbox_config_get_int(cbox_io_section, "sync_buffers", 2);
405 uii->debug_sync = cbox_config_get_int(cbox_io_section, "debug_sync", 0);
406 uii->playback_buffers = cbox_config_get_int(cbox_io_section, "playback_buffers", 2);
407 // shouldn't be more than 4, otherwise it will crackle due to limitations of
408 // the packet length adjustment. It might work better if adjustment
409 // was per-packet and not per-transfer.
410 uii->iso_packets = cbox_config_get_int(cbox_io_section, "iso_packets", 1);
411 // The USB 2.0 device uses a higher packet rate (125us I think), so the
412 // default number of packets per transfer needs to be different, too -
413 // 1ms is a minimum reasonable value
414 uii->iso_packets_multimix = cbox_config_get_int(cbox_io_section, "iso_packets_multimix", 16);
415 uii->output_resolution = cbox_config_get_int(cbox_io_section, "output_resolution", 16) / 8;
416 uii->output_channels = 2;
417 uii->handle_audiodev = NULL;
418 cbox_midi_merger_init(&uii->midi_input_merger, NULL);
420 // fixed processing buffer size, as we have to deal with packetisation anyway
421 io->io_env.srate = uii->sample_rate;
422 io->io_env.buffer_size = 64;
423 io->cb = NULL;
424 // input and output count is hardcoded for simplicity - in future, it may be
425 // necessary to add support for the extra inputs (needs to be figured out)
426 io->input_count = 2; //cbox_config_get_int("io", "inputs", 0);
427 io->input_buffers = malloc(sizeof(float *) * io->input_count);
428 for (int i = 0; i < io->input_count; i++)
429 io->input_buffers[i] = calloc(io->io_env.buffer_size, sizeof(float));
430 io->output_count = 2; // cbox_config_get_int("io", "outputs", 2);
431 io->output_buffers = malloc(sizeof(float *) * io->output_count);
432 for (int i = 0; i < io->output_count; i++)
433 io->output_buffers[i] = calloc(io->io_env.buffer_size, sizeof(float));
434 io->impl = &uii->ioi;
435 cbox_command_target_init(&io->cmd_target, cbox_usb_io_process_cmd, uii);
437 uii->ioi.pio = io;
438 uii->ioi.getsampleratefunc = cbox_usbio_get_sample_rate;
439 uii->ioi.startfunc = cbox_usbio_start;
440 uii->ioi.stopfunc = cbox_usbio_stop;
441 uii->ioi.getstatusfunc = cbox_usbio_get_status;
442 uii->ioi.pollfunc = cbox_usbio_poll_ports;
443 uii->ioi.cyclefunc = cbox_usbio_cycle;
444 uii->ioi.getmidifunc = cbox_usbio_get_midi_data;
445 uii->ioi.destroymidioutfunc = cbox_usbio_destroy_midi_out;
446 uii->ioi.destroyfunc = cbox_usbio_destroy;
447 uii->midi_ports = NULL;
449 usbio_scan_devices(uii, FALSE);
451 if (cbox_config_get_int("io", "lockall", 0))
452 mlockall(MCL_CURRENT|MCL_FUTURE);
454 return TRUE;