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 #ifndef _UMIDI20_H_
27 #define	_UMIDI20_H_
28 
29 #include <sys/cdefs.h>
30 #include <sys/param.h>
31 #include <sys/queue.h>
32 
33 #include <pthread.h>
34 #include <signal.h>
35 #include <stdint.h>
36 
37 __BEGIN_DECLS
38 
39 #define	UMIDI20_BPM 60000		/* Beats Per Minute */
40 
41 #define	UMIDI20_COMMAND_LEN 8		/* bytes, max */
42 #define	UMIDI20_BUF_EVENTS 1024		/* units */
43 
44 #define	UMIDI20_N_DEVICES 16		/* units */
45 
46 #define	UMIDI20_FLAG_PLAY 0x01
47 #define	UMIDI20_FLAG_RECORD 0x02
48 
49 #define	UMIDI20_MAX_OFFSET 0x80000000
50 
51 #define	UMIDI20_BAND_SIZE 24
52 #define	UMIDI20_KEY_TO_BAND_OFFSET(n) (((n) + 12) % UMIDI20_BAND_SIZE)
53 #define	UMIDI20_KEY_TO_BAND_NUMBER(n) (((n) + 12) / UMIDI20_BAND_SIZE)
54 
55 #define	UMIDI20_KEY_INVALID	255
56 
57 enum {
58 	UMIDI20_FILE_DIVISION_TYPE_PPQ,
59 	UMIDI20_FILE_DIVISION_TYPE_SMPTE24,
60 	UMIDI20_FILE_DIVISION_TYPE_SMPTE25,
61 	UMIDI20_FILE_DIVISION_TYPE_SMPTE30DROP,
62 	UMIDI20_FILE_DIVISION_TYPE_SMPTE30
63 };
64 
65 enum {
66 	UMIDI20_FILE_FORMAT_TYPE_0,
67 	UMIDI20_FILE_FORMAT_TYPE_1,
68 	UMIDI20_FILE_FORMAT_TYPE_2,
69 };
70 
71 #define	UMIDI20_WHAT_CHANNEL          0x0001
72 #define	UMIDI20_WHAT_KEY              0x0002
73 #define	UMIDI20_WHAT_VELOCITY         0x0004
74 #define	UMIDI20_WHAT_KEY_PRESSURE     0x0008
75 #define	UMIDI20_WHAT_CONTROL_VALUE    0x0010
76 #define	UMIDI20_WHAT_CONTROL_ADDRESS  0x0020
77 #define	UMIDI20_WHAT_PROGRAM_VALUE    0x0040
78 #define	UMIDI20_WHAT_CHANNEL_PRESSURE 0x0080
79 #define	UMIDI20_WHAT_PITCH_BEND       0x0100
80 #define	UMIDI20_WHAT_BEAT_EVENT	      0x0200
81 #define	UMIDI20_WHAT_SONG_EVENT	      0x0400
82 #define	UMIDI20_WHAT_EXTENDED_KEY     0x0800
83 
84 struct timespec;
85 struct umidi20_event;
86 struct umidi20_track;
87 struct umidi20_song;
88 struct umidi20_timer_entry;
89 
90 typedef void (umidi20_event_callback_t)(uint8_t unit, void *arg, struct umidi20_event *event, uint8_t *drop_event);
91 typedef void (umidi20_timer_callback_t)(void *arg);
92 
93 /*--------------------------------------------------------------------------*
94  * queue structures and macros
95  *--------------------------------------------------------------------------*/
96 
97 #define	UMIDI20_CACHE_INPUT  0
98 #define	UMIDI20_CACHE_OUTPUT 1
99 #define	UMIDI20_CACHE_EDIT   2
100 #define	UMIDI20_CACHE_OTHER  3
101 #define	UMIDI20_CACHE_MAX    4
102 
103 struct umidi20_event_queue {
104 	struct umidi20_event *ifq_head;
105 	struct umidi20_event *ifq_tail;
106 	struct umidi20_event *ifq_cache[UMIDI20_CACHE_MAX];
107 
108 	int32_t	ifq_len;
109 	int32_t	ifq_maxlen;
110 };
111 
112 struct umidi20_track_queue {
113 	struct umidi20_track *ifq_head;
114 	struct umidi20_track *ifq_tail;
115 	struct umidi20_track *ifq_cache[UMIDI20_CACHE_MAX];
116 
117 	int32_t	ifq_len;
118 	int32_t	ifq_maxlen;
119 };
120 
121 struct umidi20_song_queue {
122 	struct umidi20_song *ifq_head;
123 	struct umidi20_song *ifq_tail;
124 	struct umidi20_song *ifq_cache[UMIDI20_CACHE_MAX];
125 
126 	int32_t	ifq_len;
127 	int32_t	ifq_maxlen;
128 };
129 
130 #define	UMIDI20_IF_CHECK_CACHE_ONE(ifq,m,n)		\
131     if ((ifq)->ifq_cache[n] == (m)) {			\
132         (ifq)->ifq_cache[n] = (m)->p_nextpkt;		\
133 	if ((ifq)->ifq_cache[n] == NULL) {		\
134 	    (ifq)->ifq_cache[n] = (m)->p_prevpkt;	\
135 	}						\
136     }
137 
138 #define	UMIDI20_IF_CHECK_CACHE(ifq, m) do {	\
139     UMIDI20_IF_CHECK_CACHE_ONE(ifq,m,0);	\
140     UMIDI20_IF_CHECK_CACHE_ONE(ifq,m,1);	\
141     UMIDI20_IF_CHECK_CACHE_ONE(ifq,m,2);	\
142     UMIDI20_IF_CHECK_CACHE_ONE(ifq,m,3);	\
143 } while (0)
144 
145 #define	UMIDI20_IF_REMOVE(ifq, m) do {			\
146     UMIDI20_IF_CHECK_CACHE(ifq, m);			\
147     if ((m)->p_nextpkt) {				\
148         (m)->p_nextpkt->p_prevpkt = (m)->p_prevpkt;	\
149     } else {						\
150         (ifq)->ifq_tail = (m)->p_prevpkt;		\
151     }							\
152     if ((m)->p_prevpkt) {				\
153         (m)->p_prevpkt->p_nextpkt = (m)->p_nextpkt;	\
154     } else {						\
155         (ifq)->ifq_head = (m)->p_nextpkt;		\
156     }							\
157     (m)->p_nextpkt = NULL;				\
158     (m)->p_prevpkt = NULL;				\
159     (ifq)->ifq_len--;					\
160   } while (0)
161 
162 #define	UMIDI20_IF_DEQUEUE(ifq, m) do {                         \
163     (m) = (ifq)->ifq_head;                                      \
164     if (m) {                                                    \
165         UMIDI20_IF_CHECK_CACHE(ifq, m);				\
166         if (((ifq)->ifq_head = (m)->p_nextpkt) == NULL) {	\
167 	    (ifq)->ifq_tail = NULL;				\
168         } else {						\
169 	    (ifq)->ifq_head->p_prevpkt = NULL;			\
170 	}							\
171         (m)->p_nextpkt = NULL;					\
172 	(m)->p_prevpkt = NULL;					\
173         (ifq)->ifq_len--;                                       \
174     }                                                           \
175   } while (0)
176 
177 #define	UMIDI20_IF_ENQUEUE_AFTER(ifq, m1, m2) do {	\
178     (m2)->p_nextpkt = (m1)->p_nextpkt;			\
179     (m2)->p_prevpkt = (m1);				\
180     if ((m1) == (ifq)->ifq_tail) {			\
181 	(ifq)->ifq_tail = (m2);				\
182     } else {						\
183 	(m1)->p_nextpkt->p_prevpkt = (m2);		\
184     }							\
185     (m1)->p_nextpkt = (m2);				\
186     (ifq)->ifq_len++;					\
187   } while (0)
188 
189 #define	UMIDI20_IF_ENQUEUE_BEFORE(ifq, m1, m2) do {	\
190     (m2)->p_nextpkt = (m1);				\
191     (m2)->p_prevpkt = (m1)->p_prevpkt;			\
192     if ((m1) == (ifq)->ifq_head) {			\
193 	(ifq)->ifq_head = (m2);				\
194     } else {						\
195 	(m1)->p_prevpkt->p_nextpkt = (m2);		\
196     }							\
197     (m1)->p_prevpkt = (m2);				\
198     (ifq)->ifq_len++;					\
199   } while (0)
200 
201 #define	UMIDI20_IF_ENQUEUE_LAST(ifq, m) do {	\
202     (m)->p_nextpkt = NULL;			\
203     (m)->p_prevpkt = (ifq)->ifq_tail;		\
204     if ((ifq)->ifq_tail == NULL) {		\
205         (ifq)->ifq_head = (m);                  \
206     } else {					\
207         (ifq)->ifq_tail->p_nextpkt = (m);	\
208     }						\
209     (ifq)->ifq_tail = (m);                      \
210     (ifq)->ifq_len++;                           \
211   } while (0)
212 
213 #define	UMIDI20_IF_ENQUEUE_FIRST(ifq, m) do {	\
214     (m)->p_nextpkt = (ifq)->ifq_head;		\
215     (m)->p_prevpkt = NULL;			\
216     if ((ifq)->ifq_tail == NULL) {		\
217         (ifq)->ifq_tail = (m);			\
218     } else {					\
219         (ifq)->ifq_head->p_prevkt = (m);	\
220     }						\
221     (ifq)->ifq_head = (m);			\
222     (ifq)->ifq_len++;				\
223   } while (0)
224 
225 #define	UMIDI20_IF_QFULL(ifq)   ((ifq)->ifq_len >= (ifq)->ifq_maxlen)
226 #define	UMIDI20_IF_QLEN(ifq)    ((ifq)->ifq_len)
227 #define	UMIDI20_IF_POLL_HEAD(ifq, m) ((m) = (ifq)->ifq_head)
228 #define	UMIDI20_IF_POLL_TAIL(ifq, m) ((m) = (ifq)->ifq_tail)
229 
230 #define	UMIDI20_QUEUE_FOREACH(m, ifq)		\
231   for ((m) = (ifq)->ifq_head;			\
232        (m);					\
233        (m) = (m)->p_nextpkt)
234 
235 #define	UMIDI20_QUEUE_FOREACH_SAFE(m, ifq, m_next)	\
236   for ((m) = (ifq)->ifq_head;				\
237        (m) && ((m_next) = (m)->p_nextpkt, 1);		\
238        (m) = (m_next))
239 
240 
241 /*--------------------------------------------------------------------------*
242  * MIDI command converter
243  *--------------------------------------------------------------------------*/
244 struct umidi20_converter {
245 	struct umidi20_event **pp_next;
246 	struct umidi20_event *p_next;
247 
248 	uint8_t *temp_cmd;
249 	uint8_t	temp_0[UMIDI20_COMMAND_LEN];
250 	uint8_t	temp_1[UMIDI20_COMMAND_LEN];
251 	uint8_t	state;
252 #define	UMIDI20_ST_UNKNOWN   0		/* scan for command */
253 #define	UMIDI20_ST_1PARAM    1
254 #define	UMIDI20_ST_2PARAM_1  2
255 #define	UMIDI20_ST_2PARAM_2  3
256 #define	UMIDI20_ST_SYSEX_0   4
257 #define	UMIDI20_ST_SYSEX_1   5
258 #define	UMIDI20_ST_SYSEX_2   6
259 #define	UMIDI20_ST_SYSEX_3   7
260 #define	UMIDI20_ST_SYSEX_4   8
261 #define	UMIDI20_ST_SYSEX_5   9
262 #define	UMIDI20_ST_SYSEX_6  10
263 };
264 
265 /*--------------------------------------------------------------------------*
266  * MIDI event structure
267  *--------------------------------------------------------------------------*/
268 struct umidi20_event {
269 	struct umidi20_event *p_nextpkt;
270 	struct umidi20_event *p_prevpkt;
271 	struct umidi20_event *p_next;
272 	uint32_t position;		/* milliseconds */
273 	uint32_t tick;			/* units */
274 	uint32_t duration;		/* milliseconds */
275 	uint16_t revision;		/* unit */
276 	uint8_t	device_no;		/* device number */
277 	uint8_t	unused;
278 	uint8_t	cmd[UMIDI20_COMMAND_LEN];
279 };
280 
281 /*--------------------------------------------------------------------------*
282  * MIDI config structures
283  *--------------------------------------------------------------------------*/
284 struct umidi20_config_dev {
285 	char	rec_fname[128];
286 	char	play_fname[128];
287 	uint8_t	rec_enabled_cfg;
288 	uint8_t	play_enabled_cfg;
289 #define	UMIDI20_DISABLE_CFG 0
290 #define	UMIDI20_ENABLED_CFG_DEV 1
291 #define	UMIDI20_ENABLED_CFG_JACK 2
292 #define	UMIDI20_ENABLED_CFG_COREMIDI 3
293 #define	UMIDI20_ENABLED_CFG_ANDROID 4
294 };
295 
296 struct umidi20_config {
297 	struct umidi20_config_dev cfg_dev[UMIDI20_N_DEVICES];
298 };
299 
300 /*--------------------------------------------------------------------------*
301  * MIDI device structure
302  *--------------------------------------------------------------------------*/
303 struct umidi20_device {
304 
305 	struct umidi20_event_queue queue;
306 	struct umidi20_converter conv;
307 
308 	umidi20_event_callback_t *event_callback_func;
309 	void   *event_callback_arg;
310 
311 	uint32_t start_position;
312 	uint32_t end_offset;
313 
314 	int	file_no;		/* file number */
315 
316 	uint8_t	device_no;		/* device number */
317 
318 	uint8_t	any_key_start;		/* a key start was transmitted */
319 	uint8_t	enabled_usr;		/* enabled by user */
320 	uint8_t	enabled_cfg;		/* enabled by config */
321 	uint8_t	enabled_cfg_last;	/* last enabled by config */
322 	uint8_t	update;
323 	char	fname[128];
324 };
325 
326 /*--------------------------------------------------------------------------*
327  * MIDI root-device structure
328  *--------------------------------------------------------------------------*/
329 struct umidi20_root_device {
330 	struct umidi20_device rec[UMIDI20_N_DEVICES];
331 	struct umidi20_device play[UMIDI20_N_DEVICES];
332 	struct umidi20_event_queue free_queue;
333 	struct timespec curr_time;
334 	struct timespec start_time;
335 	pthread_mutex_t mutex;
336 	pthread_cond_t cond;
337 
338 	TAILQ_HEAD(, umidi20_timer_entry) timers;
339 
340 	pthread_t thread_alloc;
341 	pthread_t thread_play_rec;
342 	pthread_t thread_files;
343 
344 	uint32_t curr_position;
345 };
346 
347 extern struct umidi20_root_device root_dev;
348 
349 /*--------------------------------------------------------------------------*
350  * MIDI track structure
351  *--------------------------------------------------------------------------*/
352 struct umidi20_track {
353 	struct umidi20_event_queue queue;
354 
355 	struct umidi20_track *p_nextpkt;
356 	struct umidi20_track *p_prevpkt;
357 
358 	uint32_t position_max;
359 
360 	uint8_t	mute_flag;
361 	uint8_t	selected_flag;
362 	uint8_t	draw_flag;
363 	uint8_t	temp_flag;
364 
365 	uint8_t	key_min;
366 	uint8_t	key_max;
367 
368 	uint8_t	band_min;
369 	uint8_t	band_max;
370 
371 	uint8_t	name[256];
372 	uint8_t	instrument[256];
373 };
374 
375 /*--------------------------------------------------------------------------*
376  * MIDI song structure
377  *--------------------------------------------------------------------------*/
378 struct umidi20_song {
379 	struct umidi20_track_queue queue;
380 	struct timespec play_start_time;
381 
382 	struct umidi20_song *p_nextpkt;
383 	struct umidi20_song *p_prevpkt;
384 	struct umidi20_track *rec_track;
385 
386 	pthread_mutex_t *p_mtx;
387 	pthread_t thread_io;
388 
389 	uint32_t play_start_position;
390 	uint32_t play_end_offset;
391 	uint32_t play_start_offset;
392 	uint32_t play_last_offset;
393 	uint32_t position_max;
394 	uint32_t track_max;
395 	uint32_t band_max;
396 
397 	uint16_t midi_file_format;
398 	uint16_t midi_resolution;
399 	uint16_t record_track;
400 
401 	uint8_t	midi_division_type;
402 
403 	uint8_t	play_enabled;
404 	uint8_t	rec_enabled;
405 
406 	uint8_t	pc_flags;		/* play and record flags */
407 };
408 
409 /*--------------------------------------------------------------------------*
410  * prototypes from "umidi20.c"
411  *--------------------------------------------------------------------------*/
412 
413 extern uint32_t umidi20_get_curr_position(void);
414 extern void umidi20_set_record_event_callback(uint8_t device_no, umidi20_event_callback_t *func, void *arg);
415 extern void umidi20_set_play_event_callback(uint8_t device_no, umidi20_event_callback_t *func, void *arg);
416 extern void umidi20_init(void);
417 extern void umidi20_uninit(void);
418 extern struct umidi20_event *umidi20_event_alloc(struct umidi20_event ***ppp_next, uint8_t flag);
419 extern void umidi20_event_free(struct umidi20_event *event);
420 extern struct umidi20_event *umidi20_event_copy(struct umidi20_event *event, uint8_t flag);
421 extern struct umidi20_event *umidi20_event_from_data(const uint8_t *data_ptr, uint32_t data_len, uint8_t flag);
422 extern uint8_t *umidi20_event_pointer(struct umidi20_event *event, uint32_t offset);
423 extern uint32_t umidi20_event_get_what(struct umidi20_event *event);
424 extern uint8_t umidi20_event_is_meta(struct umidi20_event *event);
425 extern uint8_t umidi20_event_is_pitch_bend(struct umidi20_event *event);
426 extern uint8_t umidi20_event_is_key_start(struct umidi20_event *event);
427 extern uint8_t umidi20_event_is_key_end(struct umidi20_event *event);
428 extern uint8_t umidi20_event_is_tempo(struct umidi20_event *event);
429 extern uint8_t umidi20_event_is_voice(struct umidi20_event *event);
430 extern uint8_t umidi20_event_is_sysex(struct umidi20_event *event);
431 extern uint8_t umidi20_event_get_channel(struct umidi20_event *event);
432 extern void umidi20_event_set_channel(struct umidi20_event *event, uint8_t c);
433 extern uint8_t umidi20_event_get_key(struct umidi20_event *event);
434 extern void umidi20_event_set_key(struct umidi20_event *event, uint8_t k);
435 extern uint32_t umidi20_event_get_extended_key(struct umidi20_event *event);
436 extern void umidi20_event_set_extended_key(struct umidi20_event *event, uint32_t k);
437 extern uint8_t umidi20_event_get_velocity(struct umidi20_event *event);
438 extern void umidi20_event_set_velocity(struct umidi20_event *event, uint8_t v);
439 extern uint8_t umidi20_event_get_pressure(struct umidi20_event *event);
440 extern void umidi20_event_set_pressure(struct umidi20_event *event, uint8_t p);
441 extern uint8_t umidi20_event_get_control_address(struct umidi20_event *event);
442 extern void umidi20_event_set_control_address(struct umidi20_event *event, uint8_t a);
443 extern uint8_t umidi20_event_get_control_value(struct umidi20_event *event);
444 extern void umidi20_event_set_control_value(struct umidi20_event *event, uint8_t a);
445 extern uint8_t umidi20_event_get_program_number(struct umidi20_event *event);
446 extern void umidi20_event_set_program_number(struct umidi20_event *event, uint8_t n);
447 extern uint16_t umidi20_event_get_pitch_value(struct umidi20_event *event);
448 extern void umidi20_event_set_pitch_value(struct umidi20_event *event, uint16_t n);
449 extern uint32_t umidi20_event_get_length_first(struct umidi20_event *event);
450 extern uint32_t umidi20_event_get_length(struct umidi20_event *event);
451 extern void umidi20_event_copy_out(struct umidi20_event *event, uint8_t *dst, uint32_t offset, uint32_t len);
452 extern uint8_t umidi20_event_get_meta_number(struct umidi20_event *event);
453 extern void umidi20_event_set_meta_number(struct umidi20_event *event, uint8_t n);
454 extern uint32_t umidi20_event_get_tempo(struct umidi20_event *event);
455 extern void umidi20_event_set_tempo(struct umidi20_event *event, uint32_t tempo);
456 extern struct umidi20_event *umidi20_event_queue_search(struct umidi20_event_queue *queue, uint32_t position, uint8_t cache_no);
457 extern 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);
458 extern 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);
459 extern void umidi20_event_queue_insert(struct umidi20_event_queue *dst, struct umidi20_event *event_n, uint8_t cache_no);
460 extern void umidi20_event_queue_drain(struct umidi20_event_queue *src);
461 extern uint8_t umidi20_convert_to_command(struct umidi20_converter *conv, uint8_t b);
462 struct umidi20_event *umidi20_convert_to_event(struct umidi20_converter *conv, uint8_t b, uint8_t flag);
463 void	umidi20_convert_reset(struct umidi20_converter *conv);
464 extern const uint8_t umidi20_command_to_len[16];
465 extern void umidi20_gettime(struct timespec *ts);
466 extern uint32_t umidi20_difftime(struct timespec *a, struct timespec *b);
467 extern int umidi20_mutex_init(pthread_mutex_t *pmutex);
468 extern void umidi20_start(uint32_t start_position, uint32_t end_position, uint8_t flag);
469 extern void umidi20_stop(uint8_t flag);
470 struct umidi20_song *umidi20_song_alloc(pthread_mutex_t *p_mtx, uint16_t file_format, uint16_t resolution, uint8_t div_type);
471 extern void umidi20_song_free(struct umidi20_song *song);
472 extern struct umidi20_track *umidi20_song_track_by_unit(struct umidi20_song *song, uint16_t unit);
473 extern void umidi20_song_set_record_track(struct umidi20_song *song, struct umidi20_track *track);
474 extern void umidi20_song_start(struct umidi20_song *song, uint32_t start_offset, uint32_t end_offset, uint8_t flags);
475 extern void umidi20_song_stop(struct umidi20_song *song, uint8_t flags);
476 extern uint8_t umidi20_all_dev_off(uint8_t flag);
477 extern void umidi20_song_track_add(struct umidi20_song *song, struct umidi20_track *track_ref, struct umidi20_track *track_new, uint8_t is_before_ref);
478 extern void umidi20_song_track_remove(struct umidi20_song *song, struct umidi20_track *track);
479 extern void umidi20_song_recompute_position(struct umidi20_song *song);
480 extern void umidi20_song_recompute_tick(struct umidi20_song *song);
481 extern void umidi20_song_compute_max_min(struct umidi20_song *song);
482 extern void umidi20_config_export(struct umidi20_config *cfg);
483 extern void umidi20_config_import(struct umidi20_config *cfg);
484 extern struct umidi20_track *umidi20_track_alloc(void);
485 extern void umidi20_track_free(struct umidi20_track *track);
486 extern void umidi20_track_compute_max_min(struct umidi20_track *track);
487 extern void umidi20_set_timer(umidi20_timer_callback_t *fn, void *arg, uint32_t ms_interval);
488 extern void umidi20_update_timer(umidi20_timer_callback_t *fn, void *arg, uint32_t ms_interval, uint8_t do_sync);
489 extern void umidi20_unset_timer(umidi20_timer_callback_t *fn, void *arg);
490 extern int umidi20_pipe(int [2]);
491 
492 /*--------------------------------------------------------------------------*
493  * prototypes from "umidi20_file.c"
494  *--------------------------------------------------------------------------*/
495 extern struct umidi20_song *umidi20_load_file(pthread_mutex_t *p_mtx, const uint8_t *ptr, uint32_t len);
496 extern uint8_t umidi20_save_file(struct umidi20_song *song, uint8_t **pptr, uint32_t *plen);
497 
498 /*--------------------------------------------------------------------------*
499  * prototypes from "umidi20_assert.c"
500  *--------------------------------------------------------------------------*/
501 #define	pthread_mutex_assert(mtx, flags) do { } while (0)
502 
503 /*--------------------------------------------------------------------------*
504  * prototypes from "umidi20_jack.c"
505  *--------------------------------------------------------------------------*/
506 const char **umidi20_jack_alloc_inputs(void);
507 const char **umidi20_jack_alloc_outputs(void);
508 void umidi20_jack_free_inputs(const char **);
509 void umidi20_jack_free_outputs(const char **);
510 
511 int	umidi20_jack_rx_open(uint8_t n, const char *name);
512 int	umidi20_jack_tx_open(uint8_t n, const char *name);
513 int	umidi20_jack_rx_close(uint8_t n);
514 int	umidi20_jack_tx_close(uint8_t n);
515 int	umidi20_jack_init(const char *name);
516 
517 /*--------------------------------------------------------------------------*
518  * prototypes from "umidi20_coremidi.c"
519  *--------------------------------------------------------------------------*/
520 const char **umidi20_coremidi_alloc_inputs(void);
521 const char **umidi20_coremidi_alloc_outputs(void);
522 void umidi20_coremidi_free_inputs(const char **);
523 void umidi20_coremidi_free_outputs(const char **);
524 
525 int	umidi20_coremidi_rx_open(uint8_t n, const char *name);
526 int	umidi20_coremidi_tx_open(uint8_t n, const char *name);
527 int	umidi20_coremidi_rx_close(uint8_t n);
528 int	umidi20_coremidi_tx_close(uint8_t n);
529 int	umidi20_coremidi_init(const char *name);
530 
531 /*--------------------------------------------------------------------------*
532  * prototypes from "umidi20_android.c"
533  *--------------------------------------------------------------------------*/
534 const char **umidi20_android_alloc_inputs(void);
535 const char **umidi20_android_alloc_outputs(void);
536 void umidi20_android_free_inputs(const char **);
537 void umidi20_android_free_outputs(const char **);
538 
539 int	umidi20_android_rx_open(uint8_t n, const char *name);
540 int	umidi20_android_tx_open(uint8_t n, const char *name);
541 int	umidi20_android_rx_close(uint8_t n);
542 int	umidi20_android_tx_close(uint8_t n);
543 int	umidi20_android_init(const char *name, void *context);
544 
545 /*--------------------------------------------------------------------------*
546  * MIDI generator code
547  *--------------------------------------------------------------------------*/
548 #define	C0 0
549 #define	D0B 1
550 #define	D0 2
551 #define	E0B 3
552 #define	E0 4
553 #define	F0 5
554 #define	G0B 6
555 #define	G0 7
556 #define	A0B 8
557 #define	A0 9
558 #define	H0B 10
559 #define	H0 11
560 
561 #define	C1 12
562 #define	D1B 13
563 #define	D1 14
564 #define	E1B 15
565 #define	E1 16
566 #define	F1 17
567 #define	G1B 18
568 #define	G1 19
569 #define	A1B 20
570 #define	A1 21
571 #define	H1B 22
572 #define	H1 23
573 
574 #define	C2 24
575 #define	D2B 25
576 #define	D2 26
577 #define	E2B 27
578 #define	E2 28
579 #define	F2 29
580 #define	G2B 30
581 #define	G2 31
582 #define	A2B 32
583 #define	A2 33
584 #define	H2B 34
585 #define	H2 35
586 
587 #define	C3 36
588 #define	D3B 37
589 #define	D3 38
590 #define	E3B 39
591 #define	E3 40
592 #define	F3 41
593 #define	G3B 42
594 #define	G3 43
595 #define	A3B 44
596 #define	A3 45
597 #define	H3B 46
598 #define	H3 47
599 
600 #define	C4 48
601 #define	D4B 49
602 #define	D4 50
603 #define	E4B 51
604 #define	E4 52
605 #define	F4 53
606 #define	G4B 54
607 #define	G4 55
608 #define	A4B 56
609 #define	A4 57
610 #define	H4B 58
611 #define	H4 59
612 
613 #define	C5 60
614 #define	D5B 61
615 #define	D5 62
616 #define	E5B 63
617 #define	E5 64
618 #define	F5 65
619 #define	G5B 66
620 #define	G5 67
621 #define	A5B 68
622 #define	A5 69
623 #define	H5B 70
624 #define	H5 71
625 
626 #define	C6 72
627 #define	D6B 73
628 #define	D6 74
629 #define	E6B 75
630 #define	E6 76
631 #define	F6 77
632 #define	G6B 78
633 #define	G6 79
634 #define	A6B 80
635 #define	A6 81
636 #define	H6B 82
637 #define	H6 83
638 
639 #define	C7 84
640 #define	D7B 85
641 #define	D7 86
642 #define	E7B 87
643 #define	E7 88
644 #define	F7 89
645 #define	G7B 90
646 #define	G7 91
647 #define	A7B 92
648 #define	A7 93
649 #define	H7B 94
650 #define	H7 95
651 
652 #define	C8 96
653 #define	D8B 97
654 #define	D8 98
655 #define	E8B 99
656 #define	E8 100
657 #define	F8 101
658 #define	G8B 102
659 #define	G8 103
660 #define	A8B 104
661 #define	A8 105
662 #define	H8B 106
663 #define	H8 107
664 
665 #define	C9 108
666 #define	D9B 109
667 #define	D9 110
668 #define	E9B 111
669 #define	E9 112
670 #define	F9 113
671 #define	G9B 114
672 #define	G9 115
673 #define	A9B 116
674 #define	A9 117
675 #define	H9B 118
676 #define	H9 119
677 
678 #define	C10 120
679 #define	D10B 121
680 #define	D10 122
681 #define	E10B 123
682 #define	E10 124
683 #define	F10 125
684 #define	G10B 126
685 #define	G10 127
686 
687 /* Definition of channel numbers */
688 
689 #define	TRACK_R 0			/* recording track */
690 #define	TRACK_A 1
691 #define	TRACK_B 2
692 #define	TRACK_C 3
693 #define	TRACK_D 4
694 #define	TRACK_E 5
695 #define	TRACK_F 6
696 #define	TRACK_G 7
697 #define	TRACK_H 8
698 #define	TRACK_P 9			/* percussion */
699 
700 struct mid_data {
701 	struct umidi20_track *track;	/* track we are generating */
702 	uint32_t position[16];		/* track position */
703 	uint32_t priv[16];		/* client counters */
704 	uint8_t	channel;		/* currently selected MIDI channel */
705 	uint8_t	cc_enabled;		/* carbon copy enabled */
706 	uint8_t	cc_device_no;		/* carbon copy device number */
707 };
708 
709 extern const char *mid_key_str[128];
710 void	mid_set_device_no(struct mid_data *d, uint8_t device_no);
711 void	mid_sort(uint8_t *pk, uint8_t nk);
712 void	mid_trans(uint8_t *pk, uint8_t nk, int8_t nt);
713 uint8_t	mid_add(uint8_t a, uint8_t b);
714 uint8_t	mid_sub(uint8_t a, uint8_t b);
715 uint8_t	mid_next_key(uint8_t a, int8_t n);
716 void	mid_dump(struct mid_data *d);
717 void	mid_add_raw(struct mid_data *d, const uint8_t *buf, uint32_t len, uint32_t offset);
718 uint32_t mid_get_position(struct mid_data *d);
719 void	mid_set_position(struct mid_data *d, uint32_t pos);
720 uint32_t mid_delay(struct mid_data *d, int32_t off);
721 void	mid_position_ceil(struct mid_data *d, uint16_t channel_mask);
722 void	mid_position_floor(struct mid_data *d, uint16_t channel_mask);
723 void	mid_delay_all(struct mid_data *d, int32_t off);
724 void	mid_key_press(struct mid_data *d, uint8_t key, int8_t vel, uint32_t duration);
725 void	mid_extended_key_press(struct mid_data *d, uint8_t key, uint32_t freq, int8_t vel, uint32_t duration);
726 void	mid_extended_key_pitch(struct mid_data *d, uint8_t key, uint32_t freq);
727 void	mid_extended_key_control(struct mid_data *d, uint8_t key, uint8_t control, uint32_t value);
728 void	mid_key_press_n(struct mid_data *d, const uint8_t *pkey, uint8_t nkey, int8_t vel, uint32_t duration);
729 void	mid_set_channel(struct mid_data *d, uint8_t channel);
730 uint8_t	mid_get_channel(struct mid_data *d);
731 void	mid_control(struct mid_data *d, uint8_t ctrl, uint8_t val);
732 void	mid_pitch_bend(struct mid_data *d, uint16_t val);
733 void	mid_pedal(struct mid_data *d, uint8_t on);
734 void	mid_s_pedal(struct mid_data *d, int32_t db, int32_t dm, int32_t da, uint8_t on);
735 void	mid_init(struct mid_data *d, struct umidi20_track *track);
736 void	mid_set_bank_program(struct mid_data *d, uint8_t channel, uint16_t bank, uint8_t prog);
737 
738 __END_DECLS
739 
740 #endif					/* _UMIDI20_H_ */
741