Fix more warnings. Use -Wall flag to enable those warnings to show up in first place.
[calfbox.git] / usbmidi.c
blob8dfe6d617ff065f2ea3673eb2cd79ee3a08c23d0
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 #include "config.h"
20 #include "config-api.h"
21 #include "errors.h"
22 #include "hwcfg.h"
23 #include "io.h"
24 #include "meter.h"
25 #include "midi.h"
26 #include "recsrc.h"
27 #include "usbio_impl.h"
29 #include <unistd.h>
31 static void midi_transfer_cb(struct libusb_transfer *transfer)
33 struct usbio_transfer *xf = transfer->user_data;
34 struct cbox_usb_midi_input *umi = xf->user_data;
35 xf->pending = FALSE;
37 if (transfer->status == LIBUSB_TRANSFER_CANCELLED)
39 xf->cancel_confirm = 1;
40 return;
42 if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT || transfer->status == LIBUSB_TRANSFER_ERROR || transfer->status == LIBUSB_TRANSFER_STALL)
44 if (transfer->status != LIBUSB_TRANSFER_TIMED_OUT)
45 g_warning("USB error on device %03d:%03d: transfer status %d", umi->busdevadr >> 8, umi->busdevadr & 255, transfer->status);
46 if (umi->uii->no_resubmit)
47 return;
48 int res = usbio_transfer_submit(xf);
49 if (res != 0)
50 g_warning("Error submitting URB to MIDI endpoint: error code %d", res);
51 return;
53 if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE)
55 g_debug("No device %03d:%03d, unlinking", umi->busdevadr >> 8, umi->busdevadr & 255);
56 umi->uii->rt_midi_input_ports = g_list_remove(umi->uii->rt_midi_input_ports, umi);
57 return;
60 const struct cbox_usb_device_info *udi = umi->devinfo;
61 if (udi->vid == 0x09e8 && udi->pid == 0x0062)
63 for (int i = 0; i < transfer->actual_length;)
65 uint8_t *data = &transfer->buffer[i];
66 uint8_t len = data[0] & 15;
67 if (!len || i + len >= transfer->actual_length)
68 break;
69 cbox_midi_buffer_write_inline(&umi->midi_buffer, 0, data[1], len > 1 ? data[2] : 0, len > 2 ? data[3] : 0);
70 i += len + 1;
73 else
75 for (int i = 0; i + 3 < transfer->actual_length; i += 4)
77 uint8_t *data = &transfer->buffer[i];
78 if ((data[0] & 15) >= 0x08)
80 // normalise: note on with vel 0 -> note off
81 if ((data[1] & 0xF0) == 0x90 && data[3] == 0)
82 cbox_midi_buffer_write_inline(&umi->midi_buffer, 0, data[1] - 0x10, data[2], data[3]);
83 else
84 cbox_midi_buffer_write_event(&umi->midi_buffer, 0, data + 1, midi_cmd_size(data[1]));
88 if (umi->uii->no_resubmit)
89 return;
90 usbio_transfer_submit(xf);
93 void usbio_start_midi_capture(struct cbox_usb_io_impl *uii)
95 uii->rt_midi_input_ports = g_list_copy(uii->midi_input_ports);
96 uii->midi_input_port_count = 0;
98 for(GList *p = uii->rt_midi_input_ports; p; p = p->next)
99 uii->midi_input_port_count++;
100 uii->midi_input_port_buffers = calloc(uii->midi_input_port_count, sizeof(struct cbox_midi_buffer *));
101 uii->midi_input_port_pos = calloc(uii->midi_input_port_count, sizeof(int));
102 int pn = 0;
103 for(GList *p = uii->rt_midi_input_ports; p; p = p->next)
105 struct cbox_usb_midi_input *umi = p->data;
106 cbox_midi_buffer_clear(&umi->midi_buffer);
107 umi->transfer = usbio_transfer_new(uii->usbctx, "MIDI In", 0, 0, umi);
108 libusb_fill_bulk_transfer(umi->transfer->transfer, umi->handle, umi->endpoint, umi->midi_recv_data, umi->max_packet_size, midi_transfer_cb, umi->transfer, 0);
109 uii->midi_input_port_buffers[pn++] = &umi->midi_buffer;
111 for(GList *p = uii->rt_midi_input_ports; p; p = p->next)
113 struct cbox_usb_midi_input *umi = p->data;
114 int res = usbio_transfer_submit(umi->transfer);
115 if (res != 0)
117 usbio_transfer_destroy(umi->transfer);
118 umi->transfer = NULL;
123 void usbio_stop_midi_capture(struct cbox_usb_io_impl *uii)
125 for(GList *p = uii->rt_midi_input_ports; p; p = p->next)
127 struct cbox_usb_midi_input *umi = p->data;
129 if (!umi->transfer)
130 continue;
132 usbio_transfer_shutdown(umi->transfer);
133 usbio_transfer_destroy(umi->transfer);
134 umi->transfer = NULL;
135 cbox_midi_buffer_clear(&umi->midi_buffer);
137 free(uii->midi_input_port_buffers);
138 free(uii->midi_input_port_pos);
139 g_list_free(uii->rt_midi_input_ports);
142 void cbox_usb_midi_info_init(struct cbox_usb_midi_info *umi, struct cbox_usb_device_info *udi)
144 umi->udi = udi;
145 umi->intf = -1;
146 umi->alt_setting = -1;
147 umi->epdesc.found = FALSE;
150 struct cbox_usb_midi_input *usbio_open_midi_interface(struct cbox_usb_io_impl *uii, const struct cbox_usb_midi_info *uminf, struct libusb_device_handle *handle)
152 struct cbox_usb_device_info *devinfo = uminf->udi;
153 int bus = devinfo->bus;
154 int devadr = devinfo->devadr;
155 GError *error = NULL;
156 // printf("Has MIDI port\n");
157 // printf("Output endpoint address = %02x\n", ep->bEndpointAddress);
158 if (!configure_usb_interface(handle, bus, devadr, uminf->intf, uminf->alt_setting, &error))
160 g_warning("%s", error->message);
161 g_error_free(error);
162 return NULL;
165 struct cbox_usb_midi_input *umi = malloc(sizeof(struct cbox_usb_midi_input));
166 umi->uii = uii;
167 umi->devinfo = devinfo;
168 umi->handle = handle;
169 umi->busdevadr = devinfo->busdevadr;
170 umi->endpoint = uminf->epdesc.bEndpointAddress;
171 cbox_midi_buffer_init(&umi->midi_buffer);
172 uii->midi_input_ports = g_list_prepend(uii->midi_input_ports, umi);
173 int len = uminf->epdesc.wMaxPacketSize;
174 if (len > 256)
175 len = 256;
176 umi->max_packet_size = len;
178 // Drain the output buffer of the device - otherwise playing a few notes and running the program will cause
179 // those notes to play.
180 unsigned char flushbuf[256];
181 int transferred = 0;
182 while(0 == libusb_bulk_transfer(handle, umi->endpoint, flushbuf, umi->max_packet_size, &transferred, 10) && transferred > 0)
183 usleep(1000);
184 devinfo->status = CBOX_DEVICE_STATUS_OPENED;
186 return umi;