1 /*-
2 * Copyright (c) 2006-2019 Hans Petter Selasky. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26 #include <sys/uio.h>
27 #include <sys/file.h>
28 #include <sys/time.h>
29
30 #include <stdio.h>
31 #include <time.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <signal.h>
38
39 #ifdef __APPLE__
40 #include <mach/mach_time.h>
41 #include <sched.h>
42 static mach_timebase_info_data_t umidi20_timebase_info;
43 #endif
44
45 #include "umidi20.h"
46
47 #ifdef HAVE_DEBUG
48 #define DPRINTF(fmt, ...) \
49 printf("%s:%d: " fmt, __FUNCTION__, __LINE__,## __VA_ARGS__)
50 #else
51 #define DPRINTF(fmt, ...) do { } while (0)
52 #endif
53
54 #define PTHREAD_NULL ((pthread_t)-1L)
55
56 #define STRLCPY(a,b,c) do { \
57 strncpy(a,b,c); ((char *)(a))[(c)-1] = 0; \
58 } while (0)
59
60 /* prototypes */
61
62 static void *umidi20_watchdog_alloc(void *arg);
63 static void *umidi20_watchdog_play_rec(void *arg);
64 static void umidi20_watchdog_record_sub(struct umidi20_device *dev, struct umidi20_device *play_dev, uint32_t position);
65 static void umidi20_watchdog_play_sub(struct umidi20_device *dev, uint32_t position);
66 static void *umidi20_watchdog_files(void *arg);
67 static void umidi20_stop_thread(pthread_t *p_td, pthread_mutex_t *mtx);
68 static void *umidi20_watchdog_song(void *arg);
69 static void umidi20_exec_timer(uint32_t pos);
70
71 /* structures */
72
73 struct umidi20_root_device root_dev;
74
75 struct umidi20_timer_entry {
76 TAILQ_ENTRY(umidi20_timer_entry) entry;
77 umidi20_timer_callback_t *fn;
78 void *arg;
79 uint32_t ms_interval;
80 uint32_t timeout_pos;
81 uint8_t pending;
82 };
83
84 /* functions */
85
86 uint32_t
umidi20_get_curr_position(void)87 umidi20_get_curr_position(void)
88 {
89 uint32_t position;
90
91 pthread_mutex_lock(&root_dev.mutex);
92 position = root_dev.curr_position;
93 pthread_mutex_unlock(&root_dev.mutex);
94
95 return (position);
96 }
97
98 void
umidi20_set_record_event_callback(uint8_t device_no,umidi20_event_callback_t * func,void * arg)99 umidi20_set_record_event_callback(uint8_t device_no, umidi20_event_callback_t *func, void *arg)
100 {
101 if (device_no >= UMIDI20_N_DEVICES)
102 return;
103
104 root_dev.rec[device_no].event_callback_func = func;
105 root_dev.rec[device_no].event_callback_arg = arg;
106 }
107
108 void
umidi20_set_play_event_callback(uint8_t device_no,umidi20_event_callback_t * func,void * arg)109 umidi20_set_play_event_callback(uint8_t device_no, umidi20_event_callback_t *func, void *arg)
110 {
111 if (device_no >= UMIDI20_N_DEVICES)
112 return;
113
114 root_dev.play[device_no].event_callback_func = func;
115 root_dev.play[device_no].event_callback_arg = arg;
116 }
117
118 void
umidi20_init(void)119 umidi20_init(void)
120 {
121 uint32_t x;
122
123 umidi20_mutex_init(&root_dev.mutex);
124
125 pthread_cond_init(&root_dev.cond, NULL);
126
127 #ifdef __APPLE__
128 mach_timebase_info(&umidi20_timebase_info);
129 #endif
130 umidi20_gettime(&(root_dev.curr_time));
131
132 root_dev.start_time = root_dev.curr_time;
133 root_dev.curr_position = 0;
134
135 TAILQ_INIT(&root_dev.timers);
136
137 for (x = 0; x < UMIDI20_N_DEVICES; x++) {
138 root_dev.rec[x].file_no = -1;
139 root_dev.rec[x].device_no = x;
140 root_dev.rec[x].update = 1;
141 snprintf(root_dev.rec[x].fname,
142 sizeof(root_dev.rec[x].fname),
143 "/dev/umidi0.%x", x);
144
145 root_dev.play[x].file_no = -1;
146 root_dev.play[x].device_no = x;
147 root_dev.play[x].update = 1;
148 snprintf(root_dev.play[x].fname,
149 sizeof(root_dev.play[x].fname),
150 "/dev/umidi0.%x", x);
151 }
152
153 if (pthread_create(&(root_dev.thread_alloc), NULL,
154 &umidi20_watchdog_alloc, NULL)) {
155 root_dev.thread_alloc = PTHREAD_NULL;
156 }
157 if (pthread_create(&(root_dev.thread_play_rec), NULL,
158 &umidi20_watchdog_play_rec, NULL)) {
159 root_dev.thread_play_rec = PTHREAD_NULL;
160 }
161 if (pthread_create(&(root_dev.thread_files), NULL,
162 &umidi20_watchdog_files, NULL)) {
163 root_dev.thread_files = PTHREAD_NULL;
164 }
165 }
166
167 void
umidi20_uninit(void)168 umidi20_uninit(void)
169 {
170 pthread_mutex_lock(&root_dev.mutex);
171
172 umidi20_stop_thread(&(root_dev.thread_alloc),
173 &root_dev.mutex);
174
175 umidi20_stop_thread(&(root_dev.thread_play_rec),
176 &root_dev.mutex);
177
178 pthread_mutex_unlock(&root_dev.mutex);
179 }
180
181 static void
umidi20_stop_thread(pthread_t * p_td,pthread_mutex_t * p_mtx)182 umidi20_stop_thread(pthread_t *p_td, pthread_mutex_t *p_mtx)
183 {
184 pthread_t td;
185 uint8_t recurse = 0;
186
187 pthread_mutex_assert(p_mtx, MA_OWNED);
188
189 td = *p_td;
190 *p_td = PTHREAD_NULL;
191
192 if (td != PTHREAD_NULL) {
193 while (pthread_mutex_unlock(p_mtx) == 0)
194 recurse++;
195
196 pthread_kill(td, SIGURG);
197 pthread_join(td, NULL);
198
199 while (recurse--)
200 pthread_mutex_lock(p_mtx);
201 }
202 }
203
204 static void *
umidi20_watchdog_alloc(void * arg)205 umidi20_watchdog_alloc(void *arg)
206 {
207 struct umidi20_event *event;
208
209 pthread_mutex_lock(&root_dev.mutex);
210
211 while (root_dev.thread_alloc != PTHREAD_NULL) {
212
213 while (UMIDI20_IF_QLEN(&(root_dev.free_queue)) < UMIDI20_BUF_EVENTS) {
214 pthread_mutex_unlock(&root_dev.mutex);
215 event = umidi20_event_alloc(NULL, 0);
216 pthread_mutex_lock(&root_dev.mutex);
217 if (event) {
218 UMIDI20_IF_ENQUEUE_LAST(&(root_dev.free_queue), event);
219 } else {
220 break;
221 }
222 }
223 pthread_mutex_unlock(&root_dev.mutex);
224
225 usleep(100000);
226
227 pthread_mutex_lock(&root_dev.mutex);
228 }
229
230 pthread_mutex_unlock(&root_dev.mutex);
231
232 return NULL;
233 }
234
235 static void *
umidi20_watchdog_play_rec(void * arg)236 umidi20_watchdog_play_rec(void *arg)
237 {
238 struct timespec ts = {0, 0};
239 uint32_t position;
240 uint32_t x;
241
242 pthread_mutex_lock(&root_dev.mutex);
243
244 while (root_dev.thread_play_rec != PTHREAD_NULL) {
245
246 umidi20_gettime(&ts);
247
248 root_dev.curr_time = ts;
249
250 position = umidi20_difftime
251 (&(root_dev.curr_time), &(root_dev.start_time));
252
253 root_dev.curr_position = position;
254
255 for (x = 0; x < UMIDI20_N_DEVICES; x++) {
256 umidi20_watchdog_record_sub(&(root_dev.rec[x]), &(root_dev.play[x]),
257 position);
258 }
259
260 umidi20_exec_timer(position);
261
262 for (x = 0; x < UMIDI20_N_DEVICES; x++) {
263 umidi20_watchdog_play_sub(&(root_dev.play[x]), position);
264 }
265
266 pthread_mutex_unlock(&root_dev.mutex);
267
268 usleep(1000);
269
270 pthread_mutex_lock(&root_dev.mutex);
271 }
272
273 pthread_mutex_unlock(&root_dev.mutex);
274
275 return NULL;
276 }
277
278 static void
umidi20_exec_timer(uint32_t pos)279 umidi20_exec_timer(uint32_t pos)
280 {
281 struct umidi20_timer_entry *entry;
282 int32_t delta;
283
284 restart:
285
286 TAILQ_FOREACH(entry, &root_dev.timers, entry) {
287 delta = entry->timeout_pos - pos;
288 if ((delta < 0) || ((uint32_t)delta > entry->ms_interval)) {
289
290 /* check if next timeout is valid, else reset */
291
292 if (delta < -1000 || (uint32_t)delta > entry->ms_interval) {
293 /* reset */
294 entry->timeout_pos = pos;
295 } else if (delta < 0) {
296 /* try to stay sync */
297 while (delta < 0) {
298 /* try to stay sync */
299 entry->timeout_pos += entry->ms_interval;
300 delta += entry->ms_interval;
301 }
302 entry->timeout_pos -= entry->ms_interval;
303 }
304 entry->pending = 1;
305 pthread_mutex_unlock(&root_dev.mutex);
306 (entry->fn) (entry->arg);
307 pthread_mutex_lock(&root_dev.mutex);
308 entry->pending = 0;
309 pthread_cond_broadcast(&root_dev.cond);
310 /* allow callback to update the interval */
311 entry->timeout_pos += entry->ms_interval;
312 goto restart;
313 }
314 }
315 }
316
317 void
umidi20_update_timer(umidi20_timer_callback_t * fn,void * arg,uint32_t ms_interval,uint8_t do_sync)318 umidi20_update_timer(umidi20_timer_callback_t *fn, void *arg, uint32_t ms_interval, uint8_t do_sync)
319 {
320 struct umidi20_timer_entry *entry;
321
322 /* check for invalid interval */
323 if (ms_interval == 0)
324 return;
325 /* check for too big interval */
326 if (ms_interval > 65535)
327 ms_interval = 65535;
328
329 pthread_mutex_lock(&root_dev.mutex);
330
331 TAILQ_FOREACH(entry, &root_dev.timers, entry) {
332 if ((entry->fn == fn) && (entry->arg == arg)) {
333 break;
334 }
335 }
336 if (entry != NULL) {
337 entry->ms_interval = ms_interval;
338 if (do_sync)
339 entry->timeout_pos = root_dev.curr_position;
340 }
341 pthread_mutex_unlock(&root_dev.mutex);
342 }
343
344 void
umidi20_set_timer(umidi20_timer_callback_t * fn,void * arg,uint32_t ms_interval)345 umidi20_set_timer(umidi20_timer_callback_t *fn, void *arg, uint32_t ms_interval)
346 {
347 struct umidi20_timer_entry *entry;
348 struct umidi20_timer_entry *new_entry;
349
350 if (ms_interval == 0) {
351 umidi20_unset_timer(fn, arg);
352 return;
353 }
354 if (ms_interval > 65535)
355 ms_interval = 65535;
356
357 new_entry = malloc(sizeof(*new_entry));
358 if (new_entry == NULL)
359 return;
360
361 pthread_mutex_lock(&root_dev.mutex);
362
363 TAILQ_FOREACH(entry, &root_dev.timers, entry) {
364 if ((entry->fn == fn) && (entry->arg == arg)) {
365 break;
366 }
367 }
368
369 if (entry != NULL) {
370 /* first timeout ASAP */
371 entry->ms_interval = ms_interval;
372 entry->timeout_pos = root_dev.curr_position;
373
374 pthread_mutex_unlock(&root_dev.mutex);
375 free(new_entry);
376 return;
377 }
378 new_entry->fn = fn;
379 new_entry->arg = arg;
380 new_entry->ms_interval = ms_interval;
381 new_entry->timeout_pos = root_dev.curr_position + ms_interval;
382 new_entry->pending = 0;
383
384 TAILQ_INSERT_TAIL(&root_dev.timers, new_entry, entry);
385
386 pthread_mutex_unlock(&root_dev.mutex);
387 }
388
389 void
umidi20_unset_timer(umidi20_timer_callback_t * fn,void * arg)390 umidi20_unset_timer(umidi20_timer_callback_t *fn, void *arg)
391 {
392 struct umidi20_timer_entry *entry;
393
394 pthread_mutex_lock(&root_dev.mutex);
395 TAILQ_FOREACH(entry, &root_dev.timers, entry) {
396 if ((entry->fn == fn) && (entry->arg == arg)) {
397 TAILQ_REMOVE(&root_dev.timers, entry, entry);
398 while (entry->pending != 0)
399 pthread_cond_wait(&root_dev.cond, &root_dev.mutex);
400 pthread_mutex_unlock(&root_dev.mutex);
401 free(entry);
402 return;
403 }
404 }
405 pthread_mutex_unlock(&root_dev.mutex);
406 }
407
408 static void
umidi20_watchdog_record_sub(struct umidi20_device * dev,struct umidi20_device * play_dev,uint32_t curr_position)409 umidi20_watchdog_record_sub(struct umidi20_device *dev,
410 struct umidi20_device *play_dev,
411 uint32_t curr_position)
412 {
413 struct umidi20_event *event;
414 int len;
415 uint8_t cmd[16];
416 uint8_t drop;
417 uint8_t x;
418
419 curr_position -= dev->start_position;
420
421 if (curr_position >= dev->end_offset) {
422 /* time overflow */
423 if (dev->enabled_usr) {
424 DPRINTF("time overflow\n");
425 dev->enabled_usr = 0;
426 }
427 }
428 /* record */
429
430 if (dev->file_no < 0)
431 return;
432
433 /*
434 * Read data regularly so that the buffer-size is kept
435 * low, even if not recording. A length of zero
436 * usually means end of file.
437 */
438 if ((len = read(dev->file_no, cmd, sizeof(cmd))) <= 0) {
439 if (len == 0)
440 dev->update = 1;
441 else if (errno != EWOULDBLOCK)
442 dev->update = 1;
443 return;
444 }
445 if (dev->enabled_usr == 0)
446 return;
447
448 for (x = 0; x != (uint8_t)len; x++) {
449
450 event = umidi20_convert_to_event(&(dev->conv), cmd[x], 1);
451
452 if (event == NULL)
453 continue;
454
455 DPRINTF("pos = %d\n", curr_position);
456
457 event->device_no = dev->device_no;
458 event->position = curr_position;
459
460 drop = 0;
461
462 if (dev->event_callback_func != NULL) {
463
464 pthread_mutex_unlock(&root_dev.mutex);
465
466 (dev->event_callback_func) (dev->device_no,
467 dev->event_callback_arg, event, &drop);
468
469 pthread_mutex_lock(&root_dev.mutex);
470 }
471 if (drop) {
472 umidi20_event_free(event);
473 } else {
474 umidi20_event_queue_insert
475 (&(dev->queue), event, UMIDI20_CACHE_INPUT);
476 }
477 }
478 }
479
480 static void
umidi20_watchdog_play_sub(struct umidi20_device * dev,uint32_t curr_position)481 umidi20_watchdog_play_sub(struct umidi20_device *dev,
482 uint32_t curr_position)
483 {
484 struct umidi20_event *event;
485 struct umidi20_event *event_root;
486 uint32_t delta_position;
487 int err;
488 uint8_t len;
489 uint8_t drop;
490
491 /* playback */
492
493 curr_position -= dev->start_position;
494
495 if (curr_position >= dev->end_offset) {
496 /* time overflow */
497 if (dev->enabled_usr) {
498 DPRINTF("time overflow\n");
499 dev->enabled_usr = 0;
500 }
501 return;
502 }
503 while (1) {
504
505 UMIDI20_IF_POLL_HEAD(&(dev->queue), event_root);
506 event = event_root;
507
508 if (event == NULL) {
509 break;
510 }
511 delta_position = (event->position - curr_position);
512
513 if (delta_position >= 0x80000000) {
514
515 drop = 0;
516
517 if (dev->event_callback_func != NULL) {
518
519 pthread_mutex_unlock(&root_dev.mutex);
520
521 (dev->event_callback_func) (dev->device_no,
522 dev->event_callback_arg, event, &drop);
523
524 pthread_mutex_lock(&root_dev.mutex);
525 }
526 if ((dev->file_no >= 0) &&
527 (dev->enabled_usr) &&
528 (event->cmd[1] != 0xFF) &&
529 (!drop)) {
530
531 /* only write non-meta/reset commands */
532
533 do {
534 len = umidi20_command_to_len[event->cmd[0] & 0xF];
535
536 if (umidi20_event_is_key_start(event))
537 dev->any_key_start = 1;
538
539 /* try to write data */
540
541 err = write(dev->file_no, event->cmd + 1, len);
542 if ((err <= 0) && (errno != EWOULDBLOCK)) {
543 /* try to re-open the device */
544 dev->update = 1;
545 break;
546 } else if (err != len) {
547 /*
548 * we are done - the queue
549 * is full
550 */
551 break;
552 }
553 } while ((event = event->p_next));
554 }
555 UMIDI20_IF_REMOVE(&(dev->queue), event_root);
556
557 umidi20_event_free(event_root);
558 } else {
559 break;
560 }
561 }
562 }
563
564 static void *
umidi20_watchdog_files(void * arg)565 umidi20_watchdog_files(void *arg)
566 {
567 struct umidi20_device *dev;
568 uint32_t x;
569 int file_no;
570
571 pthread_mutex_lock(&root_dev.mutex);
572
573 while (root_dev.thread_files != PTHREAD_NULL) {
574
575 for (x = 0; x < UMIDI20_N_DEVICES; x++) {
576
577 dev = &(root_dev.play[x]);
578
579 if (dev->update) {
580
581 file_no = dev->file_no;
582 dev->file_no = -1;
583
584 if (file_no > 2) {
585 switch (dev->enabled_cfg_last) {
586 case UMIDI20_ENABLED_CFG_DEV:
587 close(file_no);
588 break;
589 case UMIDI20_ENABLED_CFG_JACK:
590 umidi20_jack_tx_close(x);
591 break;
592 case UMIDI20_ENABLED_CFG_COREMIDI:
593 umidi20_coremidi_tx_close(x);
594 break;
595 case UMIDI20_ENABLED_CFG_ANDROID:
596 umidi20_android_tx_close(x);
597 break;
598 default:
599 break;
600 }
601 }
602 switch (dev->enabled_cfg) {
603 case UMIDI20_ENABLED_CFG_DEV:
604 file_no = open(dev->fname, O_WRONLY | O_NONBLOCK);
605 break;
606 case UMIDI20_ENABLED_CFG_JACK:
607 file_no = umidi20_jack_tx_open(x, dev->fname);
608 break;
609 case UMIDI20_ENABLED_CFG_COREMIDI:
610 file_no = umidi20_coremidi_tx_open(x, dev->fname);
611 break;
612 case UMIDI20_ENABLED_CFG_ANDROID:
613 file_no = umidi20_android_tx_open(x, dev->fname);
614 break;
615 default:
616 file_no = -1;
617 break;
618 }
619 if (file_no >= 0) {
620 dev->enabled_cfg_last = dev->enabled_cfg;
621 dev->update = 0;
622 dev->file_no = file_no;
623 } else {
624 dev->enabled_cfg_last = UMIDI20_DISABLE_CFG;
625 }
626 }
627 dev = &(root_dev.rec[x]);
628
629 if (dev->update) {
630
631 file_no = dev->file_no;
632 dev->file_no = -1;
633
634 if (file_no > 2) {
635 switch (dev->enabled_cfg_last) {
636 case UMIDI20_ENABLED_CFG_DEV:
637 close(file_no);
638 break;
639 case UMIDI20_ENABLED_CFG_JACK:
640 umidi20_jack_rx_close(x);
641 break;
642 case UMIDI20_ENABLED_CFG_COREMIDI:
643 umidi20_coremidi_rx_close(x);
644 break;
645 case UMIDI20_ENABLED_CFG_ANDROID:
646 umidi20_android_rx_close(x);
647 break;
648 default:
649 break;
650 }
651 }
652 switch (dev->enabled_cfg) {
653 case UMIDI20_ENABLED_CFG_DEV:
654 file_no = open(dev->fname, O_RDONLY | O_NONBLOCK);
655 break;
656 case UMIDI20_ENABLED_CFG_JACK:
657 file_no = umidi20_jack_rx_open(x, dev->fname);
658 break;
659 case UMIDI20_ENABLED_CFG_COREMIDI:
660 file_no = umidi20_coremidi_rx_open(x, dev->fname);
661 break;
662 case UMIDI20_ENABLED_CFG_ANDROID:
663 file_no = umidi20_android_rx_open(x, dev->fname);
664 break;
665 default:
666 file_no = -1;
667 break;
668 }
669 if (file_no >= 0) {
670
671 /* set non-blocking I/O */
672 fcntl(file_no, F_SETFL, (int)O_NONBLOCK);
673
674 dev->enabled_cfg_last = dev->enabled_cfg;
675 dev->update = 0;
676 dev->file_no = file_no;
677 } else {
678 dev->enabled_cfg_last = UMIDI20_DISABLE_CFG;
679 }
680 }
681 }
682
683 pthread_mutex_unlock(&root_dev.mutex);
684 usleep(100000);
685 pthread_mutex_lock(&root_dev.mutex);
686 }
687 pthread_mutex_unlock(&root_dev.mutex);
688 return NULL;
689 }
690
691 /*
692 * flag: 0 - default
693 * 1 - use cache
694 */
695 struct umidi20_event *
umidi20_event_alloc(struct umidi20_event *** ppp_next,uint8_t flag)696 umidi20_event_alloc(struct umidi20_event ***ppp_next, uint8_t flag)
697 {
698 struct umidi20_event *event = NULL;
699
700 if (flag == 1) {
701 pthread_mutex_lock(&root_dev.mutex);
702 UMIDI20_IF_DEQUEUE(&(root_dev.free_queue), event);
703 pthread_mutex_unlock(&root_dev.mutex);
704 }
705 if (event == NULL) {
706 event = malloc(sizeof(*event));
707 }
708 if (event) {
709 memset(event, 0, sizeof(*event));
710 if (ppp_next) {
711 **ppp_next = event;
712 *ppp_next = &(event->p_next);
713 }
714 }
715 return event;
716 }
717
718 void
umidi20_event_free(struct umidi20_event * event)719 umidi20_event_free(struct umidi20_event *event)
720 {
721 struct umidi20_event *p_next;
722
723 while (event) {
724 p_next = event->p_next;
725 free(event);
726 event = p_next;
727 }
728 }
729
730 struct umidi20_event *
umidi20_event_copy(struct umidi20_event * event,uint8_t flag)731 umidi20_event_copy(struct umidi20_event *event, uint8_t flag)
732 {
733 struct umidi20_event *p_curr;
734 struct umidi20_event *p_next = NULL;
735 struct umidi20_event **pp_next = &p_next;
736
737 while (event) {
738
739 p_curr = umidi20_event_alloc(&pp_next, flag);
740
741 if (p_curr == NULL) {
742 goto fail;
743 }
744 /* copy data */
745
746 p_curr->position = event->position;
747 p_curr->revision = event->revision;
748 p_curr->tick = event->tick;
749 p_curr->device_no = event->device_no;
750 memcpy(p_curr->cmd, event->cmd, UMIDI20_COMMAND_LEN);
751
752 /* get next event */
753 event = event->p_next;
754 }
755 return p_next;
756
757 fail:
758 umidi20_event_free(p_next);
759 return NULL;
760 }
761
762 struct umidi20_event *
umidi20_event_from_data(const uint8_t * data_ptr,uint32_t data_len,uint8_t flag)763 umidi20_event_from_data(const uint8_t *data_ptr,
764 uint32_t data_len, uint8_t flag)
765 {
766 struct umidi20_event *p_curr = NULL;
767 struct umidi20_event *p_next = NULL;
768 struct umidi20_event **pp_next = &p_next;
769 uint8_t i;
770 uint8_t cont = 0;
771 static const uint8_t p0 = 0;
772 static const uint8_t s0 = 0;
773
774 if (data_len == 0) {
775 goto fail;
776 }
777 p_curr = umidi20_event_alloc(&pp_next, flag);
778 if (p_curr == NULL) {
779 goto fail;
780 }
781 i = 1;
782 while (1) {
783
784 if (data_len == 0) {
785 p_curr->cmd[0] = (p0 | s0 | (i - 1));
786 break;
787 }
788 if (i == 8) {
789 p_curr->cmd[0] = (cont ?
790 (p0 | s0 | 0x8) :
791 (p0 | s0 | 0x0));
792 i = 1;
793 cont = 1;
794
795 p_curr = umidi20_event_alloc(&pp_next, flag);
796 if (p_curr == NULL) {
797 goto fail;
798 }
799 }
800 p_curr->cmd[i] = *data_ptr;
801 i++;
802 data_ptr++;
803 data_len--;
804 }
805 return p_next;
806
807 fail:
808 umidi20_event_free(p_next);
809 return NULL;
810 }
811
812 uint8_t *
umidi20_event_pointer(struct umidi20_event * event,uint32_t offset)813 umidi20_event_pointer(struct umidi20_event *event, uint32_t offset)
814 {
815 while (1) {
816 uint32_t len = umidi20_event_get_length_first(event);
817 if (offset >= len) {
818 offset -= len;
819 event = event->p_next;
820 } else {
821 return (&event->cmd[1 + offset]);
822 }
823 }
824 }
825
826 uint32_t
umidi20_event_get_what(struct umidi20_event * event)827 umidi20_event_get_what(struct umidi20_event *event)
828 {
829 if (event == NULL)
830 return 0;
831
832 switch (event->cmd[1] >> 4) {
833 case 0x8:
834 case 0x9:
835 return (UMIDI20_WHAT_CHANNEL |
836 UMIDI20_WHAT_KEY |
837 UMIDI20_WHAT_VELOCITY);
838 case 0xA:
839 return (UMIDI20_WHAT_CHANNEL |
840 UMIDI20_WHAT_KEY |
841 UMIDI20_WHAT_KEY_PRESSURE);
842 case 0xB:
843 return (UMIDI20_WHAT_CHANNEL |
844 UMIDI20_WHAT_CONTROL_VALUE |
845 UMIDI20_WHAT_CONTROL_ADDRESS);
846 case 0xC:
847 return (UMIDI20_WHAT_CHANNEL |
848 UMIDI20_WHAT_PROGRAM_VALUE);
849 case 0xD:
850 return (UMIDI20_WHAT_CHANNEL |
851 UMIDI20_WHAT_CHANNEL_PRESSURE);
852 case 0xE:
853 return (UMIDI20_WHAT_CHANNEL |
854 UMIDI20_WHAT_PITCH_BEND);
855 case 0xF:
856 switch (event->cmd[1]) {
857 case 0xF8:
858 return (UMIDI20_WHAT_BEAT_EVENT);
859 case 0xF1:
860 case 0xF2:
861 case 0xF3:
862 case 0xFA:
863 case 0xFB:
864 case 0xFC:
865 return (UMIDI20_WHAT_SONG_EVENT);
866 case 0xF0: /* SYSEX */
867 if (umidi20_event_get_length(event) >= 11 &&
868 umidi20_event_pointer(event, 1)[0] == 0x0A &&
869 umidi20_event_pointer(event, 2)[0] == 0x55 &&
870 (umidi20_event_pointer(event, 3)[0] & 0xF0) == 0x00) {
871 return (UMIDI20_WHAT_CHANNEL |
872 UMIDI20_WHAT_KEY |
873 UMIDI20_WHAT_VELOCITY |
874 UMIDI20_WHAT_EXTENDED_KEY);
875 }
876 break;
877 default:
878 break;
879 }
880 break;
881 default:
882 break;
883 }
884 return 0;
885 }
886
887 uint8_t
umidi20_event_is_meta(struct umidi20_event * event)888 umidi20_event_is_meta(struct umidi20_event *event)
889 {
890 return ((umidi20_event_get_length_first(event) > 1) &&
891 (event->cmd[1] == 0xFF));
892 }
893
894 uint8_t
umidi20_event_is_pitch_bend(struct umidi20_event * event)895 umidi20_event_is_pitch_bend(struct umidi20_event *event)
896 {
897 if (event == NULL)
898 return 0;
899 return ((event->cmd[1] & 0xF0) == 0xE0);
900 }
901
902 uint8_t
umidi20_event_is_key_start(struct umidi20_event * event)903 umidi20_event_is_key_start(struct umidi20_event *event)
904 {
905 uint32_t what = umidi20_event_get_what(event);
906
907 if (what & UMIDI20_WHAT_KEY) {
908 if ((event->cmd[1] & 0xF0) == 0x80)
909 return (0);
910 if (what & UMIDI20_WHAT_VELOCITY) {
911 if (umidi20_event_get_velocity(event) != 0)
912 return (1);
913 }
914 }
915 return (0);
916 }
917
918 uint8_t
umidi20_event_is_key_end(struct umidi20_event * event)919 umidi20_event_is_key_end(struct umidi20_event *event)
920 {
921 uint32_t what = umidi20_event_get_what(event);
922
923 if (what & UMIDI20_WHAT_KEY) {
924 if ((event->cmd[1] & 0xF0) == 0x80)
925 return (1);
926 if (what & UMIDI20_WHAT_VELOCITY) {
927 if (umidi20_event_get_velocity(event) == 0)
928 return (1);
929 }
930 }
931 return (0);
932 }
933
934 uint8_t
umidi20_event_is_tempo(struct umidi20_event * event)935 umidi20_event_is_tempo(struct umidi20_event *event)
936 {
937 if (event == NULL)
938 return 0;
939 return ((event->cmd[1] == 0xFF) &&
940 (event->cmd[2] == 0x51));
941 }
942
943 uint8_t
umidi20_event_is_voice(struct umidi20_event * event)944 umidi20_event_is_voice(struct umidi20_event *event)
945 {
946 if (event == NULL)
947 return 0;
948 return ((event->cmd[1] >= 0x80) &&
949 (event->cmd[1] <= 0xEF));
950 }
951
952 uint8_t
umidi20_event_is_sysex(struct umidi20_event * event)953 umidi20_event_is_sysex(struct umidi20_event *event)
954 {
955 if (event == NULL)
956 return 0;
957 return (event->cmd[1] == 0xF0);
958 }
959
960 uint8_t
umidi20_event_get_channel(struct umidi20_event * event)961 umidi20_event_get_channel(struct umidi20_event *event)
962 {
963 uint32_t what = umidi20_event_get_what(event);
964
965 if (what & UMIDI20_WHAT_EXTENDED_KEY)
966 return (umidi20_event_pointer(event, 3)[0] & 0x0F);
967 else if (what & UMIDI20_WHAT_CHANNEL)
968 return (event->cmd[1] & 0x0F);
969 else
970 return (0);
971 }
972
973 void
umidi20_event_set_channel(struct umidi20_event * event,uint8_t c)974 umidi20_event_set_channel(struct umidi20_event *event, uint8_t c)
975 {
976 uint32_t what = umidi20_event_get_what(event);
977
978 if (what & UMIDI20_WHAT_EXTENDED_KEY) {
979 umidi20_event_pointer(event, 3)[0] &= 0xF0;
980 umidi20_event_pointer(event, 3)[0] |= (c & 0x0F);
981 } else if (what & UMIDI20_WHAT_CHANNEL) {
982 event->cmd[1] &= 0xF0;
983 event->cmd[1] |= (c & 0x0F);
984 }
985 }
986
987 uint8_t
umidi20_event_get_key(struct umidi20_event * event)988 umidi20_event_get_key(struct umidi20_event *event)
989 {
990 uint32_t what = umidi20_event_get_what(event);
991
992 if (what & UMIDI20_WHAT_EXTENDED_KEY)
993 return (umidi20_event_pointer(event, 4)[0]);
994 else if (what & UMIDI20_WHAT_KEY)
995 return (event->cmd[2]);
996 else
997 return (0);
998 }
999
1000 void
umidi20_event_set_key(struct umidi20_event * event,uint8_t k)1001 umidi20_event_set_key(struct umidi20_event *event, uint8_t k)
1002 {
1003 uint32_t what = umidi20_event_get_what(event);
1004
1005 if (what & UMIDI20_WHAT_EXTENDED_KEY)
1006 umidi20_event_pointer(event, 4)[0] = k & 0x7F;
1007 else if (what & UMIDI20_WHAT_KEY)
1008 event->cmd[2] = k & 0x7F;
1009 }
1010
1011 uint32_t
umidi20_event_get_extended_key(struct umidi20_event * event)1012 umidi20_event_get_extended_key(struct umidi20_event *event)
1013 {
1014 uint32_t what = umidi20_event_get_what(event);
1015
1016 if (what & UMIDI20_WHAT_EXTENDED_KEY) {
1017 uint32_t retval = 0;
1018 retval |= umidi20_event_pointer(event, 6)[0] & 0x7F;
1019 retval <<= 7;
1020 retval |= umidi20_event_pointer(event, 7)[0] & 0x7F;
1021 retval <<= 7;
1022 retval |= umidi20_event_pointer(event, 8)[0] & 0x7F;
1023 retval <<= 7;
1024 retval |= umidi20_event_pointer(event, 9)[0] & 0x7F;
1025
1026 return (retval);
1027 } else {
1028 return (-1U);
1029 }
1030 }
1031
1032 void
umidi20_event_set_extended_key(struct umidi20_event * event,uint32_t freq)1033 umidi20_event_set_extended_key(struct umidi20_event *event, uint32_t freq)
1034 {
1035 uint32_t what = umidi20_event_get_what(event);
1036
1037 if (what & UMIDI20_WHAT_EXTENDED_KEY) {
1038 umidi20_event_pointer(event, 9)[0] = freq & 0x7F;
1039 freq >>= 7;
1040 umidi20_event_pointer(event, 8)[0] = freq & 0x7F;
1041 freq >>= 7;
1042 umidi20_event_pointer(event, 7)[0] = freq & 0x7F;
1043 freq >>= 7;
1044 umidi20_event_pointer(event, 6)[0] = freq & 0x7F;
1045 }
1046 }
1047
1048 uint8_t
umidi20_event_get_velocity(struct umidi20_event * event)1049 umidi20_event_get_velocity(struct umidi20_event *event)
1050 {
1051 uint32_t what = umidi20_event_get_what(event);
1052
1053 if (what & UMIDI20_WHAT_EXTENDED_KEY)
1054 return (umidi20_event_pointer(event, 5)[0]);
1055 else if (what & UMIDI20_WHAT_VELOCITY)
1056 return (event->cmd[3]);
1057 else
1058 return (0);
1059 }
1060
1061 void
umidi20_event_set_velocity(struct umidi20_event * event,uint8_t k)1062 umidi20_event_set_velocity(struct umidi20_event *event, uint8_t k)
1063 {
1064 uint32_t what = umidi20_event_get_what(event);
1065
1066 if (what & UMIDI20_WHAT_EXTENDED_KEY)
1067 umidi20_event_pointer(event, 5)[0] = k & 0x7F;
1068 else if (what & UMIDI20_WHAT_VELOCITY)
1069 event->cmd[3] = k & 0x7F;
1070 }
1071
1072 uint8_t
umidi20_event_get_pressure(struct umidi20_event * event)1073 umidi20_event_get_pressure(struct umidi20_event *event)
1074 {
1075 uint32_t what = umidi20_event_get_what(event);
1076
1077 if (what & UMIDI20_WHAT_CHANNEL_PRESSURE) {
1078 return event->cmd[2];
1079 }
1080 if (what & UMIDI20_WHAT_KEY_PRESSURE) {
1081 return event->cmd[3];
1082 }
1083 return (0);
1084 }
1085
1086 void
umidi20_event_set_pressure(struct umidi20_event * event,uint8_t p)1087 umidi20_event_set_pressure(struct umidi20_event *event, uint8_t p)
1088 {
1089 uint32_t what = umidi20_event_get_what(event);
1090
1091 if (what & UMIDI20_WHAT_CHANNEL_PRESSURE) {
1092 event->cmd[2] = p & 0x7F;
1093 }
1094 if (what & UMIDI20_WHAT_KEY_PRESSURE) {
1095 event->cmd[3] = p & 0x7F;
1096 }
1097 }
1098
1099 uint8_t
umidi20_event_get_control_address(struct umidi20_event * event)1100 umidi20_event_get_control_address(struct umidi20_event *event)
1101 {
1102 uint32_t what = umidi20_event_get_what(event);
1103
1104 return ((what & UMIDI20_WHAT_CONTROL_ADDRESS) ?
1105 event->cmd[2] : 0);
1106 }
1107
1108 void
umidi20_event_set_control_address(struct umidi20_event * event,uint8_t a)1109 umidi20_event_set_control_address(struct umidi20_event *event, uint8_t a)
1110 {
1111 uint32_t what = umidi20_event_get_what(event);
1112
1113 if (what & UMIDI20_WHAT_CONTROL_ADDRESS) {
1114 event->cmd[2] = a & 0x7F;
1115 }
1116 }
1117
1118 uint8_t
umidi20_event_get_control_value(struct umidi20_event * event)1119 umidi20_event_get_control_value(struct umidi20_event *event)
1120 {
1121 uint32_t what = umidi20_event_get_what(event);
1122
1123 return ((what & UMIDI20_WHAT_CONTROL_VALUE) ?
1124 event->cmd[3] : 0);
1125 }
1126
1127 void
umidi20_event_set_control_value(struct umidi20_event * event,uint8_t a)1128 umidi20_event_set_control_value(struct umidi20_event *event, uint8_t a)
1129 {
1130 uint32_t what = umidi20_event_get_what(event);
1131
1132 if (what & UMIDI20_WHAT_CONTROL_VALUE) {
1133 event->cmd[3] = a & 0x7F;
1134 }
1135 }
1136
1137 uint8_t
umidi20_event_get_program_number(struct umidi20_event * event)1138 umidi20_event_get_program_number(struct umidi20_event *event)
1139 {
1140 uint32_t what = umidi20_event_get_what(event);
1141
1142 return ((what & UMIDI20_WHAT_PROGRAM_VALUE) ?
1143 event->cmd[2] : 0);
1144 }
1145
1146 void
umidi20_event_set_program_number(struct umidi20_event * event,uint8_t n)1147 umidi20_event_set_program_number(struct umidi20_event *event, uint8_t n)
1148 {
1149 uint32_t what = umidi20_event_get_what(event);
1150
1151 if (what & UMIDI20_WHAT_PROGRAM_VALUE) {
1152 event->cmd[2] = n & 0x7F;
1153 }
1154 }
1155
1156 uint16_t
umidi20_event_get_pitch_value(struct umidi20_event * event)1157 umidi20_event_get_pitch_value(struct umidi20_event *event)
1158 {
1159 uint32_t what = umidi20_event_get_what(event);
1160
1161 return ((what & UMIDI20_WHAT_PITCH_BEND) ?
1162 (event->cmd[2] | (event->cmd[3] << 7)) : 0);
1163 }
1164
1165 void
umidi20_event_set_pitch_value(struct umidi20_event * event,uint16_t n)1166 umidi20_event_set_pitch_value(struct umidi20_event *event, uint16_t n)
1167 {
1168 uint32_t what = umidi20_event_get_what(event);
1169
1170 if (what & UMIDI20_WHAT_PITCH_BEND) {
1171 event->cmd[2] = n & 0x7F;
1172 event->cmd[3] = (n >> 7) & 0x7F;
1173 }
1174 }
1175
1176 uint32_t
umidi20_event_get_length_first(struct umidi20_event * event)1177 umidi20_event_get_length_first(struct umidi20_event *event)
1178 {
1179 uint32_t len;
1180
1181 if (event) {
1182 len = umidi20_command_to_len[event->cmd[0] & 0xF];
1183 } else {
1184 len = 0;
1185 }
1186 return len;
1187 }
1188
1189 uint32_t
umidi20_event_get_length(struct umidi20_event * event)1190 umidi20_event_get_length(struct umidi20_event *event)
1191 {
1192 uint32_t len = 0;
1193
1194 while (event) {
1195 len += umidi20_command_to_len[event->cmd[0] & 0xF];
1196 event = event->p_next;
1197 }
1198 return len;
1199 }
1200
1201 void
umidi20_event_copy_out(struct umidi20_event * event,uint8_t * dst,uint32_t offset,uint32_t len)1202 umidi20_event_copy_out(struct umidi20_event *event, uint8_t *dst,
1203 uint32_t offset, uint32_t len)
1204 {
1205 uint32_t part_len;
1206
1207 while (offset > 0) {
1208 part_len = umidi20_command_to_len[event->cmd[0] & 0xF];
1209
1210 if (offset < part_len) {
1211 break;
1212 }
1213 offset -= part_len;
1214 event = event->p_next;
1215 }
1216
1217 while (len > 0) {
1218
1219 part_len = umidi20_command_to_len[event->cmd[0] & 0xF];
1220 part_len -= offset;
1221
1222 if (part_len > len) {
1223 part_len = len;
1224 }
1225 memcpy(dst, event->cmd + 1 + offset, part_len);
1226
1227 dst += part_len;
1228 len -= part_len;
1229 offset = 0;
1230 event = event->p_next;
1231 }
1232 }
1233
1234 uint8_t
umidi20_event_get_meta_number(struct umidi20_event * event)1235 umidi20_event_get_meta_number(struct umidi20_event *event)
1236 {
1237 return (umidi20_event_is_meta(event) ?
1238 event->cmd[2] : 0);
1239 }
1240
1241 void
umidi20_event_set_meta_number(struct umidi20_event * event,uint8_t n)1242 umidi20_event_set_meta_number(struct umidi20_event *event, uint8_t n)
1243 {
1244 if (umidi20_event_is_meta(event)) {
1245 event->cmd[2] = n & 0x7F;
1246 }
1247 }
1248
1249 uint32_t
umidi20_event_get_tempo(struct umidi20_event * event)1250 umidi20_event_get_tempo(struct umidi20_event *event)
1251 {
1252 uint32_t tempo;
1253
1254 if (!umidi20_event_is_tempo(event)) {
1255 tempo = 1;
1256 } else {
1257 tempo = (event->cmd[3] << 16) | (event->cmd[4] << 8) | event->cmd[5];
1258 if (tempo == 0) {
1259 tempo = 1;
1260 }
1261 tempo = 60000000 / tempo;
1262 if (tempo == 0) {
1263 tempo = 1;
1264 }
1265 if (tempo > 65535) {
1266 tempo = 65535;
1267 }
1268 }
1269 return tempo;
1270 }
1271
1272 void
umidi20_event_set_tempo(struct umidi20_event * event,uint32_t tempo)1273 umidi20_event_set_tempo(struct umidi20_event *event,
1274 uint32_t tempo)
1275 {
1276 if (!umidi20_event_is_tempo(event)) {
1277 return;
1278 }
1279 if (tempo < 3) {
1280 tempo = 3;
1281 }
1282 if (tempo > 65535) {
1283 tempo = 65535;
1284 }
1285 tempo = (60000000 + (tempo / 2) - 1) / tempo;
1286
1287 event->cmd[3] = (tempo >> 16) & 0xFF;
1288 event->cmd[4] = (tempo >> 8) & 0xFF;
1289 event->cmd[5] = (tempo & 0xFF);
1290 event->cmd[0] = 6; /* bytes */
1291 }
1292
1293 struct umidi20_event *
umidi20_event_queue_search(struct umidi20_event_queue * queue,uint32_t position,uint8_t cache_no)1294 umidi20_event_queue_search(struct umidi20_event_queue *queue,
1295 uint32_t position, uint8_t cache_no)
1296 {
1297 struct umidi20_event *event = queue->ifq_cache[cache_no];
1298
1299 if (event == NULL) {
1300 UMIDI20_IF_POLL_HEAD(queue, event);
1301 if (event == NULL) {
1302 goto done;
1303 }
1304 }
1305 while (1) {
1306 if (event->position < position) {
1307 break;
1308 }
1309 if (event->p_prevpkt == NULL) {
1310 break;
1311 }
1312 event = event->p_prevpkt;
1313 }
1314
1315 while (1) {
1316 if (event->position >= position) {
1317 queue->ifq_cache[cache_no] = event;
1318 goto done;
1319 }
1320 if (event->p_nextpkt == NULL) {
1321 queue->ifq_cache[cache_no] = event;
1322 event = NULL;
1323 goto done;
1324 }
1325 event = event->p_nextpkt;
1326 }
1327 done:
1328 return event;
1329 }
1330
1331 void
umidi20_event_queue_copy(struct umidi20_event_queue * src,struct umidi20_event_queue * dst,uint32_t pos_a,uint32_t pos_b,uint16_t rev_a,uint16_t rev_b,uint8_t cache_no,uint8_t flag)1332 umidi20_event_queue_copy(struct umidi20_event_queue *src,
1333 struct umidi20_event_queue *dst,
1334 uint32_t pos_a, uint32_t pos_b,
1335 uint16_t rev_a, uint16_t rev_b,
1336 uint8_t cache_no, uint8_t flag)
1337 {
1338 struct umidi20_event *event_a;
1339 struct umidi20_event *event_b;
1340 struct umidi20_event *event_n;
1341
1342 if (pos_b < pos_a) {
1343 pos_b = -1;
1344 }
1345 event_a = umidi20_event_queue_search(src, pos_a, cache_no);
1346 event_b = umidi20_event_queue_search(src, pos_b, cache_no);
1347
1348 while (event_a != event_b) {
1349
1350 if ((event_a->revision >= rev_a) &&
1351 (event_a->revision < rev_b)) {
1352
1353 event_n = umidi20_event_copy(event_a, flag);
1354
1355 if (event_n) {
1356 umidi20_event_queue_insert(dst, event_n, cache_no);
1357 } else {
1358 /* XXX do what */
1359 }
1360 }
1361 event_a = event_a->p_nextpkt;
1362 }
1363 }
1364
1365 void
umidi20_event_queue_move(struct umidi20_event_queue * src,struct umidi20_event_queue * dst,uint32_t pos_a,uint32_t pos_b,uint16_t rev_a,uint16_t rev_b,uint8_t cache_no)1366 umidi20_event_queue_move(struct umidi20_event_queue *src,
1367 struct umidi20_event_queue *dst,
1368 uint32_t pos_a, uint32_t pos_b,
1369 uint16_t rev_a, uint16_t rev_b,
1370 uint8_t cache_no)
1371 {
1372 struct umidi20_event *event_a;
1373 struct umidi20_event *event_b;
1374 struct umidi20_event *event_n;
1375
1376 if (pos_b < pos_a) {
1377 pos_b = -1;
1378 }
1379 event_a = umidi20_event_queue_search(src, pos_a, cache_no);
1380 event_b = umidi20_event_queue_search(src, pos_b, cache_no);
1381
1382 while (event_a != event_b) {
1383
1384 event_n = event_a->p_nextpkt;
1385
1386 if ((event_a->revision >= rev_a) &&
1387 (event_a->revision < rev_b)) {
1388
1389 UMIDI20_IF_REMOVE(src, event_a);
1390
1391 if (dst) {
1392 umidi20_event_queue_insert(dst, event_a, cache_no);
1393 } else {
1394 umidi20_event_free(event_a);
1395 }
1396 }
1397 event_a = event_n;
1398 }
1399 }
1400
1401 void
umidi20_event_queue_insert(struct umidi20_event_queue * dst,struct umidi20_event * event_n,uint8_t cache_no)1402 umidi20_event_queue_insert(struct umidi20_event_queue *dst,
1403 struct umidi20_event *event_n,
1404 uint8_t cache_no)
1405 {
1406 struct umidi20_event *event_a =
1407 umidi20_event_queue_search(dst, event_n->position + 1, cache_no);
1408
1409 if (event_a == NULL) {
1410 /* queue at end */
1411 UMIDI20_IF_ENQUEUE_LAST(dst, event_n);
1412 } else {
1413 /* queue before event */
1414 UMIDI20_IF_ENQUEUE_BEFORE(dst, event_a, event_n);
1415 }
1416 }
1417
1418 void
umidi20_event_queue_drain(struct umidi20_event_queue * src)1419 umidi20_event_queue_drain(struct umidi20_event_queue *src)
1420 {
1421 struct umidi20_event *event;
1422
1423 while (1) {
1424
1425 UMIDI20_IF_DEQUEUE(src, event);
1426
1427 if (event == NULL) {
1428 break;
1429 }
1430 umidi20_event_free(event);
1431 }
1432 }
1433
1434 /*
1435 * the following statemachine, that converts MIDI commands to
1436 * USB MIDI packets, derives from Linux's usbmidi.c, which
1437 * was written by "Clemens Ladisch":
1438 *
1439 * return values:
1440 * 0: No command
1441 * Else: Command is complete
1442 */
1443 uint8_t
umidi20_convert_to_command(struct umidi20_converter * conv,uint8_t b)1444 umidi20_convert_to_command(struct umidi20_converter *conv, uint8_t b)
1445 {
1446 static const uint8_t p0 = 0x0;
1447 static const uint8_t s0 = 0x0;
1448
1449 if (b >= 0xf8) {
1450 conv->temp_0[0] = p0 | 0x01 | 0x8;
1451 conv->temp_0[1] = b;
1452 conv->temp_0[2] = 0;
1453 conv->temp_0[3] = 0;
1454 conv->temp_0[4] = 0;
1455 conv->temp_0[5] = 0;
1456 conv->temp_0[6] = 0;
1457 conv->temp_0[7] = 0;
1458 conv->temp_cmd = conv->temp_0;
1459 return 1;
1460
1461 } else if (b >= 0xf0) {
1462 switch (b) {
1463 case 0xf0: /* system exclusive begin */
1464 conv->temp_1[1] = b;
1465 conv->state = UMIDI20_ST_SYSEX_1;
1466 break;
1467 case 0xf1: /* MIDI time code */
1468 case 0xf3: /* song select */
1469 conv->temp_1[1] = b;
1470 conv->state = UMIDI20_ST_1PARAM;
1471 break;
1472 case 0xf2: /* song position pointer */
1473 conv->temp_1[1] = b;
1474 conv->state = UMIDI20_ST_2PARAM_1;
1475 break;
1476 case 0xf4: /* unknown */
1477 case 0xf5: /* unknown */
1478 conv->state = UMIDI20_ST_UNKNOWN;
1479 break;
1480 case 0xf6: /* tune request */
1481 conv->temp_1[0] = p0 | 0x01 | 0x8;
1482 conv->temp_1[1] = 0xf6;
1483 conv->temp_1[2] = 0;
1484 conv->temp_1[3] = 0;
1485 conv->temp_1[4] = 0;
1486 conv->temp_1[5] = 0;
1487 conv->temp_1[6] = 0;
1488 conv->temp_1[7] = 0;
1489 conv->temp_cmd = conv->temp_1;
1490 conv->state = UMIDI20_ST_UNKNOWN;
1491 return 1;
1492
1493 case 0xf7: /* system exclusive end */
1494 switch (conv->state) {
1495 case UMIDI20_ST_SYSEX_0:
1496 conv->temp_1[0] = p0 | 0x1 | s0;
1497 conv->temp_1[1] = 0xf7;
1498 conv->temp_1[2] = 0;
1499 conv->temp_1[3] = 0;
1500 conv->temp_1[4] = 0;
1501 conv->temp_1[5] = 0;
1502 conv->temp_1[6] = 0;
1503 conv->temp_1[7] = 0;
1504 conv->temp_cmd = conv->temp_1;
1505 conv->state = UMIDI20_ST_UNKNOWN;
1506 return 1;
1507 case UMIDI20_ST_SYSEX_1:
1508 conv->temp_1[0] = p0 | 0x2 | s0;
1509 conv->temp_1[2] = 0xf7;
1510 conv->temp_1[3] = 0;
1511 conv->temp_1[4] = 0;
1512 conv->temp_1[5] = 0;
1513 conv->temp_1[6] = 0;
1514 conv->temp_1[7] = 0;
1515 conv->temp_cmd = conv->temp_1;
1516 conv->state = UMIDI20_ST_UNKNOWN;
1517 return 1;
1518 case UMIDI20_ST_SYSEX_2:
1519 conv->temp_1[0] = p0 | 0x3 | s0;
1520 conv->temp_1[3] = 0xf7;
1521 conv->temp_1[4] = 0;
1522 conv->temp_1[5] = 0;
1523 conv->temp_1[6] = 0;
1524 conv->temp_1[7] = 0;
1525 conv->temp_cmd = conv->temp_1;
1526 conv->state = UMIDI20_ST_UNKNOWN;
1527 return 1;
1528 case UMIDI20_ST_SYSEX_3:
1529 conv->temp_1[0] = p0 | 0x4 | s0;
1530 conv->temp_1[4] = 0xf7;
1531 conv->temp_1[5] = 0;
1532 conv->temp_1[6] = 0;
1533 conv->temp_1[7] = 0;
1534 conv->temp_cmd = conv->temp_1;
1535 conv->state = UMIDI20_ST_UNKNOWN;
1536 return 1;
1537 case UMIDI20_ST_SYSEX_4:
1538 conv->temp_1[0] = p0 | 0x5 | s0;
1539 conv->temp_1[5] = 0xf7;
1540 conv->temp_1[6] = 0;
1541 conv->temp_1[7] = 0;
1542 conv->temp_cmd = conv->temp_1;
1543 conv->state = UMIDI20_ST_UNKNOWN;
1544 return 1;
1545 case UMIDI20_ST_SYSEX_5:
1546 conv->temp_1[0] = p0 | 0x6 | s0;
1547 conv->temp_1[6] = 0xf7;
1548 conv->temp_1[7] = 0;
1549 conv->temp_cmd = conv->temp_1;
1550 conv->state = UMIDI20_ST_UNKNOWN;
1551 return 1;
1552 case UMIDI20_ST_SYSEX_6:
1553 conv->temp_1[0] = p0 | 0x7 | s0;
1554 conv->temp_1[7] = 0xf7;
1555 conv->temp_cmd = conv->temp_1;
1556 conv->state = UMIDI20_ST_UNKNOWN;
1557 return 1;
1558 }
1559 conv->state = UMIDI20_ST_UNKNOWN;
1560 break;
1561 }
1562 } else if (b >= 0x80) {
1563 conv->temp_1[1] = b;
1564 if ((b >= 0xc0) && (b <= 0xdf)) {
1565 conv->state = UMIDI20_ST_1PARAM;
1566 } else {
1567 conv->state = UMIDI20_ST_2PARAM_1;
1568 }
1569 } else { /* b < 0x80 */
1570 switch (conv->state) {
1571 case UMIDI20_ST_1PARAM:
1572 if (conv->temp_1[1] >= 0xf0) {
1573 conv->state = UMIDI20_ST_UNKNOWN;
1574 }
1575 conv->temp_1[0] = p0 | 0x02 | 0x8;
1576 conv->temp_1[2] = b;
1577 conv->temp_1[3] = 0;
1578 conv->temp_1[4] = 0;
1579 conv->temp_1[5] = 0;
1580 conv->temp_1[6] = 0;
1581 conv->temp_1[7] = 0;
1582 conv->temp_cmd = conv->temp_1;
1583 return 1;
1584 case UMIDI20_ST_2PARAM_1:
1585 conv->temp_1[2] = b;
1586 conv->state = UMIDI20_ST_2PARAM_2;
1587 break;
1588 case UMIDI20_ST_2PARAM_2:
1589 if (conv->temp_1[1] < 0xf0) {
1590 conv->state = UMIDI20_ST_2PARAM_1;
1591 } else {
1592 conv->state = UMIDI20_ST_UNKNOWN;
1593 }
1594 conv->temp_1[0] = p0 | 0x03 | 0x8;
1595 conv->temp_1[3] = b;
1596 conv->temp_1[4] = 0;
1597 conv->temp_1[5] = 0;
1598 conv->temp_1[6] = 0;
1599 conv->temp_1[7] = 0;
1600 conv->temp_cmd = conv->temp_1;
1601 return 1;
1602 case UMIDI20_ST_SYSEX_0:
1603 conv->temp_1[1] = b;
1604 conv->state = UMIDI20_ST_SYSEX_1;
1605 break;
1606 case UMIDI20_ST_SYSEX_1:
1607 conv->temp_1[2] = b;
1608 conv->state = UMIDI20_ST_SYSEX_2;
1609 break;
1610 case UMIDI20_ST_SYSEX_2:
1611 conv->temp_1[3] = b;
1612 conv->state = UMIDI20_ST_SYSEX_3;
1613 break;
1614 case UMIDI20_ST_SYSEX_3:
1615 conv->temp_1[4] = b;
1616 conv->state = UMIDI20_ST_SYSEX_4;
1617 break;
1618 case UMIDI20_ST_SYSEX_4:
1619 conv->temp_1[5] = b;
1620 conv->state = UMIDI20_ST_SYSEX_5;
1621 break;
1622 case UMIDI20_ST_SYSEX_5:
1623 conv->temp_1[6] = b;
1624 conv->state = UMIDI20_ST_SYSEX_6;
1625 break;
1626 case UMIDI20_ST_SYSEX_6:
1627 if (conv->temp_1[1] == 0xF0) {
1628 conv->temp_1[0] = p0 | 0x0 | s0;
1629 } else {
1630 conv->temp_1[0] = p0 | 0x8 | s0;
1631 }
1632 conv->temp_1[7] = b;
1633 conv->temp_cmd = conv->temp_1;
1634 conv->state = UMIDI20_ST_SYSEX_0;
1635 return 1;
1636 }
1637 }
1638 return 0;
1639 }
1640
1641 struct umidi20_event *
umidi20_convert_to_event(struct umidi20_converter * conv,uint8_t b,uint8_t flag)1642 umidi20_convert_to_event(struct umidi20_converter *conv,
1643 uint8_t b, uint8_t flag)
1644 {
1645 struct umidi20_event *event = NULL;
1646
1647 if (umidi20_convert_to_command(conv, b)) {
1648
1649 if (conv->temp_cmd[0] == 0x0) {
1650 /* long command begins */
1651 umidi20_event_free(conv->p_next);
1652 conv->p_next = NULL;
1653 conv->pp_next = NULL;
1654 }
1655 if (conv->temp_cmd[0] <= 0x8) {
1656 /* accumulate system exclusive messages */
1657 if (conv->pp_next == NULL)
1658 conv->pp_next = &(conv->p_next);
1659 event = umidi20_event_alloc(&(conv->pp_next), flag);
1660 } else {
1661 event = umidi20_event_alloc(NULL, flag);
1662 }
1663
1664 memcpy(event->cmd, conv->temp_cmd, UMIDI20_COMMAND_LEN);
1665
1666 if ((conv->temp_cmd[0] == 0x8) ||
1667 (conv->temp_cmd[0] == 0x0)) {
1668 event = NULL;
1669 } else if (conv->temp_cmd[0] < 8) {
1670 event = conv->p_next;
1671 conv->p_next = NULL;
1672 conv->pp_next = NULL;
1673 } else {
1674 /* short command */
1675 }
1676 }
1677 return event;
1678 }
1679
1680 void
umidi20_convert_reset(struct umidi20_converter * conv)1681 umidi20_convert_reset(struct umidi20_converter *conv)
1682 {
1683 umidi20_event_free(conv->p_next);
1684 memset(conv, 0, sizeof(*conv));
1685 }
1686
1687 const
1688 uint8_t umidi20_command_to_len[16] = {
1689
1690 /* Long MIDI commands */
1691
1692 [0x0] = 7, /* bytes, long command begins */
1693 [0x1] = 1, /* bytes, long command ends */
1694 [0x2] = 2, /* bytes, long command ends */
1695 [0x3] = 3, /* bytes, long command ends */
1696 [0x4] = 4, /* bytes, long command ends */
1697 [0x5] = 5, /* bytes, long command ends */
1698 [0x6] = 6, /* bytes, long command ends */
1699 [0x7] = 7, /* bytes, long command ends */
1700 [0x8] = 7, /* bytes, long command continues */
1701
1702 /* Short MIDI commands */
1703
1704 [0x9] = 1, /* bytes, short command ends */
1705 [0xA] = 2, /* bytes, short command ends */
1706 [0xB] = 3, /* bytes, short command ends */
1707 [0xC] = 4, /* bytes, short command ends */
1708 [0xD] = 5, /* bytes, short command ends */
1709 [0xE] = 6, /* bytes, short command ends */
1710 [0xF] = 7, /* bytes, short command ends */
1711 };
1712
1713 void
umidi20_gettime(struct timespec * ts)1714 umidi20_gettime(struct timespec *ts)
1715 {
1716 #ifdef __APPLE__
1717 uint64_t value = (mach_absolute_time() *
1718 umidi20_timebase_info.numer) / umidi20_timebase_info.denom;
1719 ts->tv_nsec = value % 1000000000ULL;
1720 ts->tv_sec = value / 1000000000ULL;
1721 #else
1722 if (clock_gettime(CLOCK_MONOTONIC, ts) == -1) {
1723 memset(ts, 0, sizeof(*ts));
1724 }
1725 #endif
1726 }
1727
1728 uint32_t
umidi20_difftime(struct timespec * a,struct timespec * b)1729 umidi20_difftime(struct timespec *a, struct timespec *b)
1730 {
1731 struct timespec c;
1732
1733 c.tv_sec = a->tv_sec - b->tv_sec;
1734 c.tv_nsec = a->tv_nsec - b->tv_nsec;
1735
1736 if (a->tv_nsec < b->tv_nsec) {
1737 c.tv_sec -= 1;
1738 c.tv_nsec += 1000000000;
1739 }
1740 return ((c.tv_sec * 1000) + (c.tv_nsec / 1000000));
1741 }
1742
1743 int
umidi20_mutex_init(pthread_mutex_t * pmutex)1744 umidi20_mutex_init(pthread_mutex_t *pmutex)
1745 {
1746 pthread_mutexattr_t attr;
1747
1748 pthread_mutexattr_init(&attr);
1749 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1750 return pthread_mutex_init(pmutex, &attr);
1751 }
1752
1753 static void
umidi20_device_start(struct umidi20_device * dev,uint32_t start_position,uint32_t end_offset)1754 umidi20_device_start(struct umidi20_device *dev,
1755 uint32_t start_position,
1756 uint32_t end_offset)
1757 {
1758 dev->start_position = start_position;
1759 dev->end_offset = end_offset;
1760 dev->enabled_usr = 1;
1761 }
1762
1763 static void
umidi20_device_stop(struct umidi20_device * dev,int play_fd)1764 umidi20_device_stop(struct umidi20_device *dev, int play_fd)
1765 {
1766 uint32_t y;
1767 uint8_t buf[4];
1768 uint8_t timeout = 16;
1769
1770 dev->enabled_usr = 0;
1771 umidi20_convert_reset(&(dev->conv));
1772 umidi20_event_queue_drain(&(dev->queue));
1773
1774 if (play_fd < 0)
1775 return;
1776
1777 if (dev->any_key_start == 0)
1778 return;
1779
1780 /* clear any key start */
1781 dev->any_key_start = 0;
1782
1783 /* all sound off */
1784 for (y = 0; y != 16; y++) {
1785 buf[0] = 0xB0 | y;
1786 buf[1] = 0x78;
1787 buf[2] = 0;
1788 while (write(play_fd, buf, 3) < 0 &&
1789 errno == EWOULDBLOCK && timeout != 0) {
1790 usleep(10000);
1791 timeout--;
1792 }
1793 }
1794
1795 /* turn pedal off */
1796 for (y = 0; y != 16; y++) {
1797 buf[0] = 0xB0 | y;
1798 buf[1] = 0x40;
1799 buf[2] = 0;
1800 while (write(play_fd, buf, 3) < 0 &&
1801 errno == EWOULDBLOCK && timeout != 0) {
1802 usleep(10000);
1803 timeout--;
1804 }
1805 }
1806 }
1807
1808 static void
umidi20_put_queue(uint8_t device_no,struct umidi20_event * event)1809 umidi20_put_queue(uint8_t device_no,
1810 struct umidi20_event *event)
1811 {
1812 struct umidi20_device *dev;
1813
1814 if (device_no >= UMIDI20_N_DEVICES) {
1815 umidi20_event_free(event);
1816 return;
1817 }
1818 pthread_mutex_lock(&root_dev.mutex);
1819
1820 dev = &(root_dev.play[device_no]);
1821
1822 if (dev->enabled_usr &&
1823 dev->enabled_cfg) {
1824 umidi20_event_queue_insert
1825 (&(dev->queue), event, UMIDI20_CACHE_INPUT);
1826 } else {
1827 umidi20_event_free(event);
1828 }
1829
1830 pthread_mutex_unlock(&root_dev.mutex);
1831 }
1832
1833 static struct umidi20_event *
umidi20_get_queue(uint8_t device_no)1834 umidi20_get_queue(uint8_t device_no)
1835 {
1836 struct umidi20_device *dev;
1837 struct umidi20_event *event;
1838
1839 if (device_no >= UMIDI20_N_DEVICES) {
1840 return NULL;
1841 }
1842 pthread_mutex_lock(&root_dev.mutex);
1843
1844 dev = &(root_dev.rec[device_no]);
1845
1846 if (dev->enabled_usr &&
1847 dev->enabled_cfg) {
1848 UMIDI20_IF_DEQUEUE(&(dev->queue), event);
1849 } else {
1850 event = NULL;
1851 }
1852
1853 pthread_mutex_unlock(&root_dev.mutex);
1854
1855 return event;
1856 }
1857
1858 void
umidi20_start(uint32_t start_offset,uint32_t end_offset,uint8_t flag)1859 umidi20_start(uint32_t start_offset, uint32_t end_offset, uint8_t flag)
1860 {
1861 uint32_t x;
1862 uint32_t start_position;
1863
1864 if (flag == 0) {
1865 return;
1866 }
1867 pthread_mutex_lock(&root_dev.mutex);
1868
1869 umidi20_stop(flag);
1870
1871 /* sanity checking */
1872
1873 if ((end_offset <= start_offset) ||
1874 (start_offset > 0x80000000) ||
1875 (end_offset > 0x80000000)) {
1876 goto done;
1877 }
1878 start_position = (root_dev.curr_position - start_offset);
1879
1880 if (flag & UMIDI20_FLAG_PLAY) {
1881 for (x = 0; x < UMIDI20_N_DEVICES; x++) {
1882 umidi20_device_start
1883 (&(root_dev.play[x]), start_position, end_offset);
1884 }
1885 }
1886 if (flag & UMIDI20_FLAG_RECORD) {
1887 for (x = 0; x < UMIDI20_N_DEVICES; x++) {
1888 umidi20_device_start
1889 (&(root_dev.rec[x]), start_position, end_offset);
1890 }
1891 }
1892 done:
1893 pthread_mutex_unlock(&root_dev.mutex);
1894 }
1895
1896 void
umidi20_stop(uint8_t flag)1897 umidi20_stop(uint8_t flag)
1898 {
1899 uint32_t x;
1900
1901 if (flag == 0)
1902 return;
1903
1904 pthread_mutex_lock(&root_dev.mutex);
1905 if (flag & UMIDI20_FLAG_PLAY) {
1906 for (x = 0; x < UMIDI20_N_DEVICES; x++) {
1907 umidi20_device_stop(&(root_dev.play[x]),
1908 root_dev.play[x].file_no);
1909 }
1910 }
1911 if (flag & UMIDI20_FLAG_RECORD) {
1912 for (x = 0; x < UMIDI20_N_DEVICES; x++) {
1913 umidi20_device_stop(&(root_dev.rec[x]), -1);
1914 }
1915 }
1916 pthread_mutex_unlock(&root_dev.mutex);
1917 }
1918
1919 uint8_t
umidi20_all_dev_off(uint8_t flag)1920 umidi20_all_dev_off(uint8_t flag)
1921 {
1922 uint32_t x;
1923 uint8_t retval = 1;
1924
1925 if (flag == 0)
1926 goto done;
1927
1928 pthread_mutex_lock(&root_dev.mutex);
1929 if (flag & UMIDI20_FLAG_PLAY) {
1930 for (x = 0; x < UMIDI20_N_DEVICES; x++) {
1931 if (root_dev.play[x].enabled_cfg) {
1932 retval = 0;
1933 break;
1934 }
1935 }
1936 }
1937 if (flag & UMIDI20_FLAG_RECORD) {
1938 for (x = 0; x < UMIDI20_N_DEVICES; x++) {
1939 if (root_dev.rec[x].enabled_cfg) {
1940 retval = 0;
1941 break;
1942 }
1943 }
1944 }
1945 pthread_mutex_unlock(&root_dev.mutex);
1946 done:
1947 return retval;
1948 }
1949
1950 struct umidi20_song *
umidi20_song_alloc(pthread_mutex_t * p_mtx,uint16_t file_format,uint16_t resolution,uint8_t div_type)1951 umidi20_song_alloc(pthread_mutex_t *p_mtx, uint16_t file_format,
1952 uint16_t resolution, uint8_t div_type)
1953 {
1954 struct umidi20_song *song = malloc(sizeof(*song));
1955
1956 if (song) {
1957
1958 memset(song, 0, sizeof(*song));
1959
1960 song->p_mtx = p_mtx;
1961
1962 if (pthread_create(&(song->thread_io), NULL,
1963 &umidi20_watchdog_song, song)) {
1964 song->thread_io = PTHREAD_NULL;
1965 }
1966 song->midi_file_format = file_format;
1967
1968 if (resolution == 0) {
1969 /* avoid division by zero */
1970 resolution = 1;
1971 }
1972 song->midi_resolution = resolution;
1973 song->midi_division_type = div_type;
1974 }
1975 return song;
1976 }
1977
1978 void
umidi20_song_free(struct umidi20_song * song)1979 umidi20_song_free(struct umidi20_song *song)
1980 {
1981 struct umidi20_track *track;
1982
1983 if (song == NULL) {
1984 return;
1985 }
1986 pthread_mutex_assert(song->p_mtx, MA_OWNED);
1987
1988 umidi20_stop_thread(&(song->thread_io), song->p_mtx);
1989
1990 umidi20_song_stop(song, UMIDI20_FLAG_PLAY | UMIDI20_FLAG_RECORD);
1991
1992 while (1) {
1993
1994 UMIDI20_IF_DEQUEUE(&(song->queue), track);
1995
1996 if (track == NULL) {
1997 break;
1998 }
1999 umidi20_track_free(track);
2000 }
2001
2002 free(song);
2003 }
2004
2005 static void
umidi20_watchdog_song_sub(struct umidi20_song * song)2006 umidi20_watchdog_song_sub(struct umidi20_song *song)
2007 {
2008 struct umidi20_track *track;
2009 struct umidi20_event *event;
2010 struct umidi20_event_queue queue;
2011 uint32_t curr_position;
2012 uint32_t position;
2013 uint32_t x;
2014
2015 pthread_mutex_assert(song->p_mtx, MA_OWNED);
2016
2017 memset(&queue, 0, sizeof(queue));
2018
2019 pthread_mutex_lock(&root_dev.mutex);
2020 curr_position = root_dev.curr_position;
2021 pthread_mutex_unlock(&root_dev.mutex);
2022
2023 track = song->queue.ifq_cache[UMIDI20_CACHE_INPUT];
2024
2025 if (song->rec_enabled && track) {
2026
2027 for (x = 0; x < UMIDI20_N_DEVICES; x++) {
2028
2029 while (1) {
2030
2031 event = umidi20_get_queue(x);
2032
2033 if (event == NULL) {
2034 break;
2035 }
2036 umidi20_event_queue_insert
2037 (&(track->queue), event,
2038 UMIDI20_CACHE_INPUT);
2039 }
2040 }
2041 }
2042 if (song->play_enabled) {
2043
2044 position = (curr_position - song->play_start_position);
2045
2046 position += (song->play_start_offset + 1500);
2047
2048 if (position >= song->play_end_offset) {
2049 song->play_enabled = 0;
2050 position = song->play_end_offset;
2051 }
2052 UMIDI20_QUEUE_FOREACH(track, &(song->queue)) {
2053 if (!(track->mute_flag)) {
2054 umidi20_event_queue_copy(&(track->queue), &queue,
2055 song->play_last_offset,
2056 position, 0, -1,
2057 UMIDI20_CACHE_OUTPUT, 0);
2058 }
2059 }
2060
2061 song->play_last_offset = position;
2062
2063 while (1) {
2064
2065 UMIDI20_IF_DEQUEUE(&queue, event);
2066
2067 if (event == NULL) {
2068 break;
2069 }
2070 umidi20_put_queue(event->device_no, event);
2071 }
2072 }
2073 }
2074
2075
2076 static void *
umidi20_watchdog_song(void * arg)2077 umidi20_watchdog_song(void *arg)
2078 {
2079 struct umidi20_song *song = arg;
2080
2081 pthread_mutex_lock(song->p_mtx);
2082
2083 while (song->thread_io != PTHREAD_NULL) {
2084
2085 umidi20_watchdog_song_sub(song);
2086
2087 pthread_mutex_unlock(song->p_mtx);
2088
2089 usleep(250000);
2090
2091 pthread_mutex_lock(song->p_mtx);
2092 }
2093
2094 pthread_mutex_unlock(song->p_mtx);
2095
2096 return NULL;
2097 }
2098
2099 struct umidi20_track *
umidi20_song_track_by_unit(struct umidi20_song * song,uint16_t unit)2100 umidi20_song_track_by_unit(struct umidi20_song *song, uint16_t unit)
2101 {
2102 struct umidi20_track *track;
2103
2104 if (song == NULL) {
2105 return NULL;
2106 }
2107 pthread_mutex_assert(song->p_mtx, MA_OWNED);
2108
2109 UMIDI20_IF_POLL_HEAD(&(song->queue), track);
2110
2111 while (track) {
2112 if (!unit--) {
2113 break;
2114 }
2115 track = track->p_nextpkt;
2116 }
2117 return track;
2118 }
2119
2120 /*
2121 * if "track == NULL" then
2122 * recording is disabled
2123 */
2124 void
umidi20_song_set_record_track(struct umidi20_song * song,struct umidi20_track * track)2125 umidi20_song_set_record_track(struct umidi20_song *song,
2126 struct umidi20_track *track)
2127 {
2128 if (song == NULL) {
2129 return;
2130 }
2131 pthread_mutex_assert(song->p_mtx, MA_OWNED);
2132 song->queue.ifq_cache[UMIDI20_CACHE_INPUT] = track;
2133 }
2134
2135 /*
2136 * this function can be called
2137 * multiple times in a row:
2138 */
2139 void
umidi20_song_start(struct umidi20_song * song,uint32_t start_offset,uint32_t end_offset,uint8_t flags)2140 umidi20_song_start(struct umidi20_song *song, uint32_t start_offset,
2141 uint32_t end_offset,
2142 uint8_t flags)
2143 {
2144 uint32_t curr_position;
2145
2146 if (song == NULL) {
2147 goto done;
2148 }
2149 if (flags == 0) {
2150 goto done;
2151 }
2152 pthread_mutex_assert(song->p_mtx, MA_OWNED);
2153
2154 umidi20_song_stop(song, flags);
2155
2156 /* sanity checking */
2157
2158 if ((end_offset <= start_offset) ||
2159 (start_offset > 0x80000000) ||
2160 (end_offset > 0x80000000)) {
2161 goto done;
2162 }
2163 umidi20_start(start_offset, end_offset, flags);
2164
2165 pthread_mutex_lock(&root_dev.mutex);
2166 curr_position = root_dev.curr_position;
2167 pthread_mutex_unlock(&root_dev.mutex);
2168
2169 if (flags & UMIDI20_FLAG_PLAY) {
2170 song->play_enabled = 1;
2171 song->play_start_position = curr_position;
2172 song->play_start_offset = start_offset;
2173 song->play_last_offset = start_offset;
2174 song->play_end_offset = end_offset;
2175 }
2176 if (flags & UMIDI20_FLAG_RECORD) {
2177 song->rec_enabled = 1;
2178 }
2179 /* update buffering */
2180
2181 umidi20_watchdog_song_sub(song);
2182
2183 song->pc_flags |= flags;
2184
2185 done: ;
2186 }
2187
2188 void
umidi20_song_stop(struct umidi20_song * song,uint8_t flags)2189 umidi20_song_stop(struct umidi20_song *song, uint8_t flags)
2190 {
2191 if (song == NULL) {
2192 goto done;
2193 }
2194 if (flags == 0) {
2195 goto done;
2196 }
2197 pthread_mutex_assert(song->p_mtx, MA_OWNED);
2198
2199 flags &= song->pc_flags;
2200
2201 if (flags & UMIDI20_FLAG_PLAY) {
2202 song->play_enabled = 0;
2203 }
2204 if (flags & UMIDI20_FLAG_RECORD) {
2205 song->rec_enabled = 0;
2206 }
2207 umidi20_stop(flags);
2208
2209 song->pc_flags &= ~flags;
2210
2211 done: ;
2212 }
2213
2214 void
umidi20_song_track_add(struct umidi20_song * song,struct umidi20_track * track_ref,struct umidi20_track * track_new,uint8_t is_before_ref)2215 umidi20_song_track_add(struct umidi20_song *song,
2216 struct umidi20_track *track_ref,
2217 struct umidi20_track *track_new,
2218 uint8_t is_before_ref)
2219 {
2220 pthread_mutex_assert(song->p_mtx, MA_OWNED);
2221
2222 if (song == NULL) {
2223 umidi20_track_free(track_new);
2224 return;
2225 }
2226 if (track_ref == NULL) {
2227 UMIDI20_IF_ENQUEUE_LAST(&(song->queue), track_new);
2228 } else {
2229 if (is_before_ref) {
2230 UMIDI20_IF_ENQUEUE_BEFORE(&(song->queue), track_ref, track_new);
2231 } else {
2232 UMIDI20_IF_ENQUEUE_AFTER(&(song->queue), track_ref, track_new);
2233 }
2234 }
2235 }
2236
2237 void
umidi20_song_track_remove(struct umidi20_song * song,struct umidi20_track * track)2238 umidi20_song_track_remove(struct umidi20_song *song,
2239 struct umidi20_track *track)
2240 {
2241 pthread_mutex_assert(song->p_mtx, MA_OWNED);
2242
2243 if (song == NULL) {
2244 return; /* XXX should not happen */
2245 }
2246 if (track == NULL) {
2247 return;
2248 }
2249 UMIDI20_IF_REMOVE(&(song->queue), track);
2250
2251 umidi20_track_free(track);
2252 }
2253
2254 void
umidi20_song_recompute_position(struct umidi20_song * song)2255 umidi20_song_recompute_position(struct umidi20_song *song)
2256 {
2257 struct umidi20_track *conductor_track;
2258 struct umidi20_track *track;
2259 struct umidi20_event *event;
2260 struct umidi20_event *event_copy;
2261
2262 uint32_t tempo;
2263 uint32_t last_tick;
2264 uint32_t delta_tick;
2265 uint32_t factor;
2266 uint32_t position_curr;
2267 uint32_t position_rem;
2268 uint32_t divisor;
2269
2270 if (song == NULL) {
2271 return;
2272 }
2273 pthread_mutex_assert(song->p_mtx, MA_OWNED);
2274
2275 UMIDI20_IF_POLL_HEAD(&(song->queue), conductor_track);
2276
2277 if (conductor_track == NULL) {
2278 goto done;
2279 }
2280 /*
2281 * First copy the conductor track to
2282 * all the other tracks:
2283 */
2284
2285 UMIDI20_QUEUE_FOREACH(event, &(conductor_track->queue)) {
2286
2287 if (umidi20_event_is_tempo(event)) {
2288
2289 UMIDI20_QUEUE_FOREACH(track, &(song->queue)) {
2290
2291 if (track != conductor_track) {
2292
2293 event_copy = umidi20_event_copy(event, 0);
2294 if (event_copy == NULL) {
2295 goto fail;
2296 }
2297 umidi20_event_queue_insert(&(track->queue),
2298 event_copy,
2299 UMIDI20_CACHE_INPUT);
2300 }
2301 }
2302 }
2303 }
2304
2305 /*
2306 * Compute new position information:
2307 */
2308 UMIDI20_QUEUE_FOREACH(track, &(song->queue)) {
2309
2310 tempo = 120; /* BPM */
2311 last_tick = 0;
2312 position_curr = 0;
2313 position_rem = 0;
2314
2315 switch (song->midi_division_type) {
2316 case UMIDI20_FILE_DIVISION_TYPE_PPQ:
2317 divisor = (tempo * song->midi_resolution);
2318 break;
2319 case UMIDI20_FILE_DIVISION_TYPE_SMPTE24:
2320 divisor = (24 * song->midi_resolution);
2321 break;
2322 case UMIDI20_FILE_DIVISION_TYPE_SMPTE25:
2323 divisor = (25 * song->midi_resolution);
2324 break;
2325 case UMIDI20_FILE_DIVISION_TYPE_SMPTE30DROP:
2326 divisor = (29.97 * song->midi_resolution);
2327 break;
2328 case UMIDI20_FILE_DIVISION_TYPE_SMPTE30:
2329 divisor = (30 * song->midi_resolution);
2330 break;
2331 default:
2332 divisor = 120;
2333 break;
2334 }
2335
2336 if (song->midi_division_type == UMIDI20_FILE_DIVISION_TYPE_PPQ) {
2337 factor = UMIDI20_BPM;
2338 } else {
2339 factor = (UMIDI20_BPM / 60);
2340 }
2341
2342 DPRINTF("divisor=%d\n", divisor);
2343
2344 UMIDI20_QUEUE_FOREACH(event, &(track->queue)) {
2345
2346 delta_tick = (event->tick - last_tick);
2347 last_tick = event->tick;
2348
2349 position_curr += (delta_tick / divisor) * factor;
2350 position_rem += (delta_tick % divisor) * factor;
2351
2352 position_curr += (position_rem / divisor);
2353 position_rem %= divisor;
2354
2355 DPRINTF("%d / %d, pos = %d, tick = %d\n", delta_tick,
2356 divisor, position_curr, event->tick);
2357
2358 /* update position */
2359 event->position = position_curr;
2360
2361 if (umidi20_event_is_tempo(event) &&
2362 (song->midi_division_type == UMIDI20_FILE_DIVISION_TYPE_PPQ)) {
2363 tempo = umidi20_event_get_tempo(event);
2364 divisor = (tempo * song->midi_resolution);
2365 position_rem = 0;
2366 }
2367 }
2368 }
2369
2370 fail:
2371 /*
2372 * Remove all tempo information from
2373 * non-conductor tracks:
2374 */
2375 UMIDI20_QUEUE_FOREACH(track, &(song->queue)) {
2376
2377 if (track != conductor_track) {
2378
2379 UMIDI20_QUEUE_FOREACH_SAFE(event, &(track->queue), event_copy) {
2380
2381 if (umidi20_event_is_tempo(event)) {
2382
2383 UMIDI20_IF_REMOVE(&(track->queue), event);
2384
2385 umidi20_event_free(event);
2386 }
2387 }
2388 }
2389 }
2390 done: ;
2391 }
2392
2393 void
umidi20_song_recompute_tick(struct umidi20_song * song)2394 umidi20_song_recompute_tick(struct umidi20_song *song)
2395 {
2396 struct umidi20_track *track;
2397 struct umidi20_event *event;
2398 struct umidi20_event *event_next;
2399
2400 if (song == NULL) {
2401 return;
2402 }
2403 pthread_mutex_assert(song->p_mtx, MA_OWNED);
2404
2405 song->midi_division_type = UMIDI20_FILE_DIVISION_TYPE_PPQ;
2406 song->midi_resolution = 500;
2407
2408 /*
2409 * First remove all tempo
2410 * information:
2411 */
2412 UMIDI20_QUEUE_FOREACH(track, &(song->queue)) {
2413
2414 UMIDI20_QUEUE_FOREACH_SAFE(event, &(track->queue), event_next) {
2415
2416 event->tick = event->position;
2417
2418 if (umidi20_event_is_tempo(event)) {
2419 UMIDI20_IF_REMOVE(&(track->queue), event);
2420 umidi20_event_free(event);
2421 }
2422 }
2423 }
2424 }
2425
2426 void
umidi20_song_compute_max_min(struct umidi20_song * song)2427 umidi20_song_compute_max_min(struct umidi20_song *song)
2428 {
2429 struct umidi20_track *track;
2430
2431 pthread_mutex_assert(song->p_mtx, MA_OWNED);
2432
2433 song->position_max = 0;
2434 song->track_max = 0;
2435 song->band_max = 0;
2436
2437 UMIDI20_QUEUE_FOREACH(track, &(song->queue)) {
2438 umidi20_track_compute_max_min(track);
2439
2440 if (track->position_max > song->position_max) {
2441 song->position_max = track->position_max;
2442 }
2443 song->band_max +=
2444 (track->band_max - track->band_min);
2445 }
2446
2447 song->track_max = UMIDI20_IF_QLEN(&(song->queue));
2448 }
2449
2450 void
umidi20_config_export(struct umidi20_config * cfg)2451 umidi20_config_export(struct umidi20_config *cfg)
2452 {
2453 uint32_t x;
2454
2455 memset(cfg, 0, sizeof(*cfg));
2456
2457 pthread_mutex_lock(&root_dev.mutex);
2458
2459 for (x = 0; x < UMIDI20_N_DEVICES; x++) {
2460
2461 STRLCPY(cfg->cfg_dev[x].rec_fname,
2462 root_dev.rec[x].fname,
2463 sizeof(cfg->cfg_dev[x].rec_fname));
2464
2465 cfg->cfg_dev[x].rec_enabled_cfg =
2466 root_dev.rec[x].enabled_cfg;
2467
2468 STRLCPY(cfg->cfg_dev[x].play_fname,
2469 root_dev.play[x].fname,
2470 sizeof(cfg->cfg_dev[x].play_fname));
2471
2472 cfg->cfg_dev[x].play_enabled_cfg =
2473 root_dev.play[x].enabled_cfg;
2474 }
2475
2476 pthread_mutex_unlock(&root_dev.mutex);
2477 }
2478
2479 void
umidi20_config_import(struct umidi20_config * cfg)2480 umidi20_config_import(struct umidi20_config *cfg)
2481 {
2482 uint32_t x;
2483
2484 pthread_mutex_lock(&root_dev.mutex);
2485
2486 for (x = 0; x < UMIDI20_N_DEVICES; x++) {
2487
2488 if (strcmp(root_dev.rec[x].fname,
2489 cfg->cfg_dev[x].rec_fname)) {
2490 root_dev.rec[x].update = 1;
2491 STRLCPY(root_dev.rec[x].fname,
2492 cfg->cfg_dev[x].rec_fname,
2493 sizeof(root_dev.rec[x].fname));
2494 }
2495 if (root_dev.rec[x].enabled_cfg !=
2496 cfg->cfg_dev[x].rec_enabled_cfg) {
2497
2498 root_dev.rec[x].update = 1;
2499 root_dev.rec[x].enabled_cfg =
2500 cfg->cfg_dev[x].rec_enabled_cfg;
2501 }
2502 if (strcmp(root_dev.play[x].fname,
2503 cfg->cfg_dev[x].play_fname)) {
2504
2505 root_dev.play[x].update = 1;
2506 STRLCPY(root_dev.play[x].fname,
2507 cfg->cfg_dev[x].play_fname,
2508 sizeof(root_dev.play[x].fname));
2509 }
2510 if (root_dev.play[x].enabled_cfg !=
2511 cfg->cfg_dev[x].play_enabled_cfg) {
2512
2513 root_dev.play[x].update = 1;
2514 root_dev.play[x].enabled_cfg =
2515 cfg->cfg_dev[x].play_enabled_cfg;
2516 }
2517 }
2518 pthread_mutex_unlock(&root_dev.mutex);
2519 }
2520
2521 struct umidi20_track *
umidi20_track_alloc(void)2522 umidi20_track_alloc(void)
2523 {
2524 struct umidi20_track *track;
2525
2526 track = malloc(sizeof(*track));
2527 if (track)
2528 memset(track, 0, sizeof(*track));
2529 return (track);
2530 }
2531
2532 void
umidi20_track_free(struct umidi20_track * track)2533 umidi20_track_free(struct umidi20_track *track)
2534 {
2535 if (track == NULL)
2536 return;
2537
2538 umidi20_event_queue_drain(&(track->queue));
2539
2540 free(track);
2541 }
2542
2543 void
umidi20_track_compute_max_min(struct umidi20_track * track)2544 umidi20_track_compute_max_min(struct umidi20_track *track)
2545 {
2546 struct umidi20_event *event;
2547 struct umidi20_event *event_last;
2548 struct umidi20_event *last_key_press[128];
2549 uint32_t what;
2550 uint8_t key;
2551 uint8_t is_on;
2552 uint8_t is_off;
2553 uint8_t meta_num;
2554
2555 memset(&last_key_press, 0, sizeof(last_key_press));
2556
2557 track->key_max = 0x00;
2558 track->key_min = 0xFF;
2559
2560 track->position_max = 0;
2561
2562 UMIDI20_QUEUE_FOREACH(event, &(track->queue)) {
2563
2564 what = umidi20_event_get_what(event);
2565
2566 if (what & UMIDI20_WHAT_KEY) {
2567
2568 is_on = umidi20_event_is_key_start(event);
2569 is_off = umidi20_event_is_key_end(event);
2570 key = umidi20_event_get_key(event) & 0x7F;
2571
2572 if (is_on || is_off) {
2573
2574 event_last = last_key_press[key];
2575 last_key_press[key] = NULL;
2576
2577 /* update duration */
2578
2579 if (event_last) {
2580 event_last->duration =
2581 (event->position - event_last->position);
2582 }
2583 if (is_on) {
2584 last_key_press[key] = event;
2585 }
2586 }
2587 if (key > track->key_max) {
2588 track->key_max = key;
2589 }
2590 if (key < track->key_min) {
2591 track->key_min = key;
2592 }
2593 }
2594 if (umidi20_event_is_meta(event)) {
2595 meta_num = umidi20_event_get_meta_number(event);
2596 what = umidi20_event_get_length(event);
2597
2598 if (meta_num == 0x03) {
2599 what -= 2;
2600 if (what > (sizeof(track->name) - 1)) {
2601 what = (sizeof(track->name) - 1);
2602 }
2603 umidi20_event_copy_out(event, track->name, 2, what);
2604 track->name[what] = 0;
2605 }
2606 if (meta_num == 0x04) {
2607 what -= 2;
2608 if (what > (sizeof(track->instrument) - 1)) {
2609 what = (sizeof(track->instrument) - 1);
2610 }
2611 umidi20_event_copy_out(event, track->instrument, 2, what);
2612 track->instrument[what] = 0;
2613 }
2614 }
2615 }
2616 if ((track->key_max == 0x00) &&
2617 (track->key_min == 0xFF)) {
2618 track->key_max = 0x3C;
2619 track->key_min = 0x3C;
2620 }
2621 track->band_min =
2622 UMIDI20_KEY_TO_BAND_NUMBER(track->key_min);
2623
2624 track->band_max =
2625 UMIDI20_KEY_TO_BAND_NUMBER(track->key_max + UMIDI20_BAND_SIZE);
2626
2627 UMIDI20_IF_POLL_TAIL(&(track->queue), event);
2628 if (event) {
2629 track->position_max = event->position;
2630 }
2631 for (key = 0; key < 0x80; key++) {
2632 event_last = last_key_press[key];
2633 if (event_last) {
2634 event_last->duration =
2635 (event->position - event_last->position);
2636 }
2637 }
2638 }
2639
2640 int
umidi20_pipe(int fd[2])2641 umidi20_pipe(int fd[2])
2642 {
2643 int retval = pipe(fd);
2644
2645 if (retval != 0) {
2646 fd[0] = -1;
2647 fd[1] = -1;
2648 }
2649 return (retval);
2650 }
2651