source: roaraudio/roard/midi.c @ 2942:b583009f19b7

Last change on this file since 2942:b583009f19b7 was 2941:e54be79a2eb2, checked in by phi, 15 years ago

added mixer for MIDI subsystem

File size: 17.9 KB
Line 
1//midi.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25#include "roard.h"
26
27#ifndef ROAR_WITHOUT_DCOMP_MIDI
28
29#if defined(ROAR_HAVE_IO_POSIX) && !defined(ROAR_TARGET_WIN32)
30#define _HAVE_CONSOLE
31#endif
32
33int midi_init_config(void) {
34 midi_config.init        = 1;
35 midi_config.inited      = 0;
36
37#ifndef ROAR_WITHOUT_DCOMP_CB
38 midi_config.init_cb     = 0;
39 midi_config.console_dev = NULL;
40#endif
41
42 return 0;
43}
44
45int midi_init (void) {
46
47 midi_config.inited = 0;
48
49 if ( midi_config.init ) {
50#ifndef ROAR_WITHOUT_DCOMP_CB
51  if ( midi_config.init_cb ) {
52   if ( midi_cb_init() == -1 ) {
53    ROAR_WARN("Can not initialize MIDI subsystem component CB");
54   }
55  }
56#endif
57
58  if ( midi_clock_init() == -1 ) {
59   ROAR_WARN("Can not initialize MIDI subsystem component clock");
60  }
61
62 }
63
64 g_midi_mess.buf = NULL;
65
66 if ( (g_midi_mixer.stream = add_mixer(ROAR_SUBSYS_MIDI, _MIXER_NAME("MIDI"), NULL)) == -1 ) {
67  ROAR_WARN("Can not create MIDI mixer");
68 }
69
70 midi_config.inited |= MIDI_INITED_MAIN;
71
72 return 0;
73}
74
75int midi_free (void) {
76 if ( midi_reinit() == -1 )
77  return -1;
78
79#ifndef ROAR_WITHOUT_DCOMP_CB
80 if ( midi_cb_free() == -1 )
81  return -1;
82#endif
83
84 return 0;
85}
86
87int midi_update(void) {
88
89 if ( g_midi_clock.stream != -1 )
90  midi_check_bridge(g_midi_clock.stream);
91
92#ifndef ROAR_WITHOUT_DCOMP_SSYNTH
93 midi_conv_mes2ssynth();
94#endif
95
96#ifndef ROAR_WITHOUT_DCOMP_CB
97 return midi_cb_update();
98#else
99 return 0;
100#endif
101}
102
103int midi_reinit(void) {
104
105 if ( g_midi_mess.buf != NULL )
106  roar_buffer_free(g_midi_mess.buf);
107
108 g_midi_mess.buf = NULL;
109
110 return 0;
111}
112
113// STREAMS:
114
115int midi_check_stream  (int id) {
116 struct roar_stream        *   s;
117 struct roar_stream_server *  ss;
118 struct roar_buffer        *   b;
119 char                      * buf;
120 ssize_t                     len;
121
122 if ( g_streams[id] == NULL )
123  return -1;
124
125 ROAR_DBG("midi_check_stream(id=%i) = ?", id);
126
127 s = ROAR_STREAM(ss = g_streams[id]);
128
129 if ( s->dir == ROAR_DIR_BRIDGE )
130  return midi_check_bridge(id);
131
132 switch (s->info.codec) {
133  case ROAR_CODEC_MIDI:
134   break;
135  default:
136    streams_delete(id);
137    return -1;
138 }
139
140 if ( roar_buffer_new(&b, MIDI_READ_SIZE) == -1 ) {
141  ROAR_ERR("midi_check_stream(*): Can not alloc buffer space!");
142  ROAR_DBG("midi_check_stream(*) = -1");
143  return -1;
144 }
145
146 roar_buffer_get_data(b, (void **)&buf);
147
148 if ( (len = stream_vio_s_read(ss, buf, MIDI_READ_SIZE)) < 1 ) {
149  streams_delete(id);
150  roar_buffer_free(b);
151  return -1;
152 }
153
154 roar_buffer_set_len(b, len);
155
156 if ( stream_add_buffer(id, b) == -1 ) {
157  roar_buffer_free(b);
158  streams_delete(id);
159  return -1;
160 }
161
162 switch (s->info.codec) {
163  case ROAR_CODEC_MIDI:
164    return midi_conv_midi2mes(id);
165   break;
166  default:
167    streams_delete(id);
168    return -1;
169 }
170
171 return 0;
172}
173
174int midi_send_stream   (int id) {
175 struct roar_stream        *   s;
176 struct roar_stream_server *  ss;
177
178 if ( g_streams[id] == NULL )
179  return -1;
180
181 ROAR_DBG("midi_send_stream(id=%i) = ?", id);
182
183 s = ROAR_STREAM(ss = g_streams[id]);
184
185 switch (s->info.codec) {
186  case ROAR_CODEC_MIDI:
187    return midi_conv_mes2midi(id);
188   break;
189  default:
190    streams_delete(id);
191    return -1;
192 }
193
194 return 0;
195}
196
197int midi_conv_midi2mes (int id) {
198 unsigned char * data;
199 struct roar_stream        *   s;
200 struct roar_stream_server *  ss;
201 struct roar_buffer        * buf = NULL;
202 struct midi_message       * mes = NULL;
203 size_t need = 0, have = 0, last_have = 0, old_have = 0;
204 int alive = 1;
205
206 if ( g_streams[id] == NULL )
207  return -1;
208
209 ROAR_DBG("midi_conv_midi2mes(id=%i) = ?", id);
210
211 s = ROAR_STREAM(ss = g_streams[id]);
212
213 while (ss->buffer != NULL && alive) {
214  if ( roar_buffer_get_data(ss->buffer, (void**)&data) == -1 ) {
215   alive = 0;
216   continue;
217  }
218
219  if ( roar_buffer_get_len(ss->buffer, &have) == -1 ) {
220   alive = 0;
221   continue;
222  }
223  old_have = have;
224
225  while (have && alive) {
226   if ( *data & 0x80 ) {
227    if ( buf != NULL ) {
228     midi_add_buf(id, buf);
229     buf = NULL;
230    }
231
232    last_have = have;
233
234    need = 0;
235    if ( midi_new_bufmes(&buf, &mes) == -1 ) {
236     alive = 0;
237     continue;
238    }
239
240    if (*data == MIDI_TYPE_CLOCK_TICK || *data == MIDI_TYPE_CLOCK_START || *data == MIDI_TYPE_CLOCK_STOP ) {
241     mes->type = *data;
242
243     if ( *data == MIDI_TYPE_CLOCK_TICK ) {
244      s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, 1);
245     }
246    } else {
247     mes->type    = *data & 0xF0;
248     mes->channel = *data & 0x0F;
249     switch (*data & 0xF0) {
250      case MIDI_TYPE_NOTE_ON:
251      case MIDI_TYPE_NOTE_OFF:
252        need = 2;
253       break;
254      case MIDI_TYPE_PA:
255        need = 2;
256       break;
257      case MIDI_TYPE_CONTROLER:
258        need = 2;
259       break;
260      case MIDI_TYPE_PROGRAM:
261        need = 1;
262       break;
263      case MIDI_TYPE_MA:
264        need = 1;
265       break;
266      case MIDI_TYPE_PB:
267      case MIDI_TYPE_SYSEX:
268        need = 1;
269       break;
270     }
271    }
272
273   } else {
274
275    if ( mes == NULL ) {
276     ROAR_WARN("midi_conv_midi2mes(id=%i): Lost sync.", id);
277     data++;
278     have--;
279     continue;
280    }
281
282    switch (mes->type) {
283      case MIDI_TYPE_NOTE_ON:
284      case MIDI_TYPE_NOTE_OFF:
285       if ( need == 2 ) {
286        roar_midi_note_from_midiid(&(mes->d.note), *data);
287
288        // if velocity is zero we have a NOTE OFF event
289        if ( data[1] == 0 )
290         mes->type = MIDI_TYPE_NOTE_OFF;
291       }
292      case MIDI_TYPE_PA:
293      case MIDI_TYPE_CONTROLER:
294        if ( need == 2 ) {
295         mes->kk = *data;
296        } else {
297         mes->vv = *data;
298        }
299       break;
300      case MIDI_TYPE_PROGRAM:
301      case MIDI_TYPE_MA:
302        mes->vv = *data;
303       break;
304      case MIDI_TYPE_PB:
305      case MIDI_TYPE_SYSEX:
306        ROAR_WARN("midi_conv_midi2mes(id=%i): Message of Type 0x%.2X (PB or SysEx) not yet supported", id, mes->type);
307       break;
308    }
309
310    if ( need )
311     need--;
312
313    if ( !need ) {
314     switch (mes->type) {
315      case MIDI_TYPE_CONTROLER:
316       switch (mes->kk) {
317        case MIDI_CCE_MAIN_VOL:
318         if ( 516 * mes->vv > 65100 ) { // max volume
319          ss->mixer.mixer[mes->channel] = 65535;
320         } else {
321          ss->mixer.mixer[mes->channel] = 516 * mes->vv;
322         }
323         break;
324       }
325      break;
326     }
327    }
328
329   }
330   data++;
331   have--;
332  }
333
334  if ( need ) {
335   if ( roar_buffer_set_offset(ss->buffer, old_have - last_have) == -1 ) {
336    ROAR_ERR("midi_conv_midi2mes(*): FIXME: BUG!!! Need to restore buffer here with corrected length");
337   }
338  } else if ( !have ) {
339   roar_buffer_next(&(ss->buffer));
340  }
341
342  if ( need && buf != NULL ) {
343   roar_buffer_free(buf);
344   buf = NULL;
345  } else if ( buf != NULL ) {
346   midi_add_buf(id, buf);
347   buf = NULL;
348  }
349 }
350
351 return 0;
352}
353
354#define _nb  len++; *(d++)
355int midi_conv_mes2midi (int id) {
356 struct roar_stream        *   s;
357 struct roar_stream_server *  ss;
358 struct roar_buffer        * buf = g_midi_mess.buf;
359 struct midi_message       * mes = NULL;
360 unsigned char               data[3];
361 unsigned char             * d;
362 int                         len;
363 int                         send_clock;
364
365 if ( g_streams[id] == NULL )
366  return -1;
367
368 ROAR_DBG("midi_conv_mes2midi(id=%i) = ?", id);
369
370 s = ROAR_STREAM(ss = g_streams[id]);
371
372 send_clock = streams_get_flag(id, ROAR_FLAG_SYNC);
373
374 while (buf != NULL) {
375  if ( roar_buffer_get_data(buf, (void**)&mes) == -1 ) {
376   return -1;
377  }
378
379  if (mes->type == MIDI_TYPE_CLOCK_TICK || mes->type == MIDI_TYPE_CLOCK_START || mes->type == MIDI_TYPE_CLOCK_STOP ) {
380   if ( send_clock ) {
381    if ( stream_vio_s_write(ss, &(mes->type), 1) != 1 ) {
382     streams_delete(id);
383     return -1;
384    }
385   }
386
387   if ( mes->type == MIDI_TYPE_CLOCK_TICK ) {
388    s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, 1);
389   }
390  } else {
391   len = 0;
392   d   = data;
393
394   _nb = (mes->type & 0xF0) | (mes->channel & 0x0F);
395
396   switch (mes->type) {
397    case MIDI_TYPE_CONTROLER:
398      switch (mes->kk) {
399       case MIDI_CCE_MAIN_VOL:
400         if ( 516 * mes->vv > 65100 ) { // max volume
401          ss->mixer.mixer[mes->channel] = 65535;
402         } else {
403          ss->mixer.mixer[mes->channel] = 516 * mes->vv;
404         }
405        break;
406      }
407    case MIDI_TYPE_NOTE_ON:
408    case MIDI_TYPE_NOTE_OFF:
409    case MIDI_TYPE_PA:
410      _nb = mes->kk;
411      _nb = mes->vv;
412     break;
413    case MIDI_TYPE_PROGRAM:
414    case MIDI_TYPE_MA:
415      _nb = mes->vv;
416     break;
417    case MIDI_TYPE_PB:
418    case MIDI_TYPE_SYSEX:
419     break;
420   }
421
422   if ( stream_vio_s_write(ss, data, len) != len ) {
423    streams_delete(id);
424    return -1;
425   }
426  }
427
428  if ( roar_buffer_get_next(buf, &buf) == -1 )
429   buf = NULL;
430 }
431
432 return 0;
433}
434#undef _nb
435
436#ifndef ROAR_WITHOUT_DCOMP_SSYNTH
437int midi_conv_mes2ssynth(void) {
438 struct roar_buffer        * buf = g_midi_mess.buf;
439 struct midi_message       * mes = NULL;
440
441 while (buf != NULL) {
442  if ( roar_buffer_get_data(buf, (void**)&mes) == -1 ) {
443   return -1;
444  }
445
446  if ( ssynth_eval_message(mes) == -1 )
447   return -1;
448
449  if ( roar_buffer_get_next(buf, &buf) == -1 )
450   buf = NULL;
451 }
452
453 return 0;
454}
455#endif
456
457int midi_new_bufmes    (struct roar_buffer ** buf, struct midi_message ** mes) {
458 if ( buf == NULL || mes == NULL )
459  return -1;
460
461 *buf = (void*)(*mes = NULL);
462
463 if ( roar_buffer_new(buf, sizeof(struct midi_message)) == -1 )
464  return -1;
465
466 if ( roar_buffer_get_data(*buf, (void**)mes) == -1 ) {
467  roar_buffer_free(*buf);
468  *buf = (void*)(*mes = NULL);
469  return -1;
470 }
471
472 memset((void*)*mes, 0, sizeof(struct midi_message));
473
474 (*mes)->type = MIDI_TYPE_NONE;
475
476 return 0;
477}
478
479int midi_add_buf       (int id, struct roar_buffer * buf) {
480 struct midi_message * mes;
481
482 if ( id == -1 || buf == NULL )
483  return -1;
484
485 if ( roar_buffer_get_data(buf, (void**)&mes) == -1 )
486  return -1;
487
488 ROAR_DBG("midi_add_buf(id=%i, buf=%p) = ?", id, buf);
489 ROAR_DBG("midi_add_buf(*): MIDI Message of Type 0x%.2X", mes->type);
490 ROAR_DBG("midi_add_buf(*): Channel: %i", mes->channel);
491 ROAR_DBG("midi_add_buf(*): flags=0x%.2X", mes->flags);
492 ROAR_DBG("midi_add_buf(*): kk=0x%.2X, vv=0x%.2X", mes->kk, mes->vv);
493
494 if ( g_midi_mess.buf == NULL ) {
495  g_midi_mess.buf = buf;
496 } else {
497  roar_buffer_add(g_midi_mess.buf, buf);
498 }
499
500 return 0;
501}
502
503// bridges:
504int midi_check_bridge  (int id) {
505
506 ROAR_DBG("midi_check_bridge(id=%i) = ?", id);
507
508 if ( id == g_midi_clock.stream ) {
509  midi_clock_tick();
510
511  return 0;
512 }
513
514 return -1;
515}
516
517// clock:
518
519int midi_clock_init (void) {
520 struct roar_stream * s;
521 struct roar_stream_server * ss;
522
523 if ( (g_midi_clock.stream = streams_new()) == -1 ) {
524  ROAR_WARN("Error while initializing MIDI subsystem component clock");
525  return -1;
526 }
527
528 client_stream_add(g_self_client, g_midi_clock.stream);
529
530 midi_vio_set_dummy(g_midi_clock.stream);
531
532 streams_get(g_midi_clock.stream, &ss);
533 s = ROAR_STREAM(ss);
534
535 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
536
537 s->pos_rel_id    =  g_midi_clock.stream;
538
539 s->info.codec    =  ROAR_CODEC_MIDI;
540 ss->codec_orgi   =  ROAR_CODEC_MIDI;
541
542 s->info.channels = 1; // we have only one channel, ticking on channel 0
543 s->info.rate     = ROAR_MIDI_TICKS_PER_BEAT; // one beat per sec
544 s->info.bits     = ROAR_MIDI_BITS;
545
546 if ( streams_set_dir(g_midi_clock.stream, ROAR_DIR_BRIDGE, 1) == -1 ) {
547  ROAR_WARN("Error while initializing MIDI subsystem component clock");
548  return -1;
549 }
550
551 streams_set_name(g_midi_clock.stream, "MIDI Clock");
552
553 streams_set_flag(g_midi_clock.stream, ROAR_FLAG_PRIMARY);
554 streams_set_flag(g_midi_clock.stream, ROAR_FLAG_SYNC);
555
556 midi_clock_set_bph(3600); // one beat per sec
557
558 midi_config.inited |= MIDI_INITED_CLOCK;
559
560 return 0;
561}
562
563int midi_clock_set_bph (uint_least32_t bph) {
564 uint_least32_t sph = g_sa->rate/2 * 75 * g_sa->channels; // samples per houre
565
566 g_midi_clock.bph  = bph;
567
568 g_midi_clock.spt  = sph/bph;
569
570 g_midi_clock.nt   = ROAR_MATH_OVERFLOW_ADD(g_pos, g_midi_clock.spt);
571
572 return 0;
573}
574
575int midi_clock_tick (void) {
576 struct roar_buffer  * buf;
577 struct midi_message * mes;
578 struct roar_stream_server * ss;
579 unsigned int diff;
580
581 if ( streams_get(g_midi_clock.stream, &ss) == -1 ) {
582  ROAR_ERR("midi_clock_tick(void): Something very BAD happend: can not get stream object of my own stream!");
583  g_midi_clock.stream = -1;
584  ROAR_WARN("midi_clock_tick(void): Disabled MIDI Clock");
585  return -1;
586 }
587
588 while ( g_pos >= g_midi_clock.nt ) {
589  diff = g_pos - g_midi_clock.nt;
590  ROAR_DBG("midi_clock_tick(void): g_pos is %u samples (%5.2f%%) after of nt.", diff, (float)diff/g_midi_clock.spt);
591
592  g_midi_clock.nt   = ROAR_MATH_OVERFLOW_ADD(g_midi_clock.nt, g_midi_clock.spt);
593
594  if ( streams_get_flag(g_midi_clock.stream, ROAR_FLAG_SYNC) ) {
595   ROAR_DBG("midi_clock_tick(void): TICK! (nt=%lu)", g_midi_clock.nt);
596   if ( midi_new_bufmes(&buf, &mes) == -1 ) {
597    ROAR_ERR("midi_clock_tick(void): Can not create Clock-Tick-Message");
598   }
599
600   mes->type = MIDI_TYPE_CLOCK_TICK;
601
602   if ( midi_add_buf(g_midi_clock.stream, buf) == -1 ) {
603    ROAR_ERR("midi_clock_tick(void): Can not add Clock-Tick-Message");
604    roar_buffer_free(buf);
605    return -1;
606   }
607
608   ROAR_STREAM(ss)->pos = ROAR_MATH_OVERFLOW_ADD(ROAR_STREAM(ss)->pos, 1);
609  } else {
610   ROAR_DBG("midi_clock_tick(void): silent tick. (nt=%lu)", g_midi_clock.nt);
611  }
612 }
613
614 return 0;
615}
616
617// CB:
618
619#ifndef ROAR_WITHOUT_DCOMP_CB
620int midi_cb_init (void) {
621#ifdef _HAVE_CONSOLE
622 struct roar_stream * s;
623 struct roar_stream_server * ss;
624 int i;
625 char * files[] = {
626                   "/NX",
627                   "/dev/roarconsole",
628                   "/dev/console",
629#ifdef __linux__
630                   "/dev/tty0",
631                   "/dev/vc/0",
632#endif
633                   NULL
634                  };
635
636 g_midi_cb.console  = -1;
637 g_midi_cb.stream   = -1;
638 g_midi_cb.stoptime =  0;
639 g_midi_cb.playing  =  0;
640
641 if ( midi_config.console_dev != NULL ) {
642  files[0] = midi_config.console_dev;
643 }
644
645 for (i = 0; files[i] != NULL; i++) {
646  if ( (g_midi_cb.console = open(files[i], O_WRONLY|O_NOCTTY, 0)) != -1 )
647   break;
648 }
649
650 if ( g_midi_cb.console == -1 )
651  return -1;
652
653 if ( (g_midi_cb.stream = streams_new()) == -1 ) {
654  ROAR_WARN("Error while initializing MIDI subsystem component CB");
655  midi_cb_free();
656  return -1;
657 }
658
659 client_stream_add(g_self_client, g_midi_clock.stream);
660
661 midi_vio_set_dummy(g_midi_cb.stream);
662
663 streams_get(g_midi_cb.stream, &ss);
664 s = ROAR_STREAM(ss);
665
666 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
667
668 s->pos_rel_id    = -1;
669
670 s->info.codec    =  0;
671 ss->codec_orgi   =  0;
672
673 s->info.channels =  1;
674 s->info.rate     = 1193180;
675 s->info.bits     =  8;
676
677 if ( streams_set_dir(g_midi_cb.stream, ROAR_DIR_BRIDGE, 1) == -1 ) {
678  ROAR_WARN("Error while initializing MIDI subsystem component CB");
679  midi_cb_free();
680  return -1;
681 }
682
683 streams_set_name(g_midi_cb.stream, "Console speaker bridge");
684
685 streams_set_flag(g_midi_cb.stream, ROAR_FLAG_OUTPUT);
686 streams_set_flag(g_midi_cb.stream, ROAR_FLAG_PRIMARY);
687 streams_set_flag(g_midi_cb.stream, ROAR_FLAG_HWMIXER);
688 streams_set_flag(g_midi_cb.stream, ROAR_FLAG_MUTE);
689
690 midi_config.inited |= MIDI_INITED_CB;
691
692 return 0;
693#else
694 g_midi_cb.console  = -1;
695 g_midi_cb.stream   = -1;
696
697 return -1;
698#endif
699}
700
701int midi_cb_free (void) {
702#ifdef _HAVE_CONSOLE
703
704 midi_cb_stop();
705
706 if ( g_midi_cb.stream != -1 )
707  streams_delete(g_midi_cb.stream);
708
709 if ( g_midi_cb.console != -1 )
710  close(g_midi_cb.console);
711
712 return 0;
713#else
714 return -1;
715#endif
716}
717
718int midi_cb_play(float t, float freq, int override) {
719 float samples_per_sec /* S/s */ = g_sa->rate * g_sa->channels;
720
721/*
722#define MIDI_CB_NOOVERRIDE 0
723#define MIDI_CB_OVERRIDE   1
724*/
725 if ( g_midi_cb.playing && override != MIDI_CB_OVERRIDE )
726  return -1;
727
728 g_midi_cb.stoptime = ROAR_MATH_OVERFLOW_ADD(g_pos, samples_per_sec*t);
729 midi_cb_start(freq);
730
731 return 0;
732}
733
734int midi_cb_update (void) {
735
736 if ( !streams_get_flag(g_midi_cb.stream, ROAR_FLAG_MUTE) ) {
737  if ( midi_cb_readbuf() == -1 )
738   return -1;
739 } else if ( g_midi_cb.playing ) {
740  midi_cb_stop();
741 }
742
743 if ( !g_midi_cb.playing )
744  return 0;
745
746/*
747 if ( g_midi_cb.stoptime <= g_pos )
748  midi_cb_stop();
749*/
750
751 ROAR_DBG("midi_cb_update(void) = ?");
752
753 return 0;
754}
755
756int midi_cb_start(float freq) {
757// On linux this uses ioctl KIOCSOUND
758#ifdef __linux__
759 if ( g_midi_cb.console == -1 )
760  return -1;
761
762 if ( ioctl(g_midi_cb.console, KIOCSOUND, freq == 0 ? 0 : (int)(1193180.0/freq)) == -1 )
763  return -1;
764
765 g_midi_cb.playing = 1;
766
767 return 0;
768#else
769 return -1;
770#endif
771}
772
773int midi_cb_stop (void) {
774#ifdef __linux__
775 int ret;
776
777 ret = midi_cb_start(0);
778 g_midi_cb.playing = 0;
779
780 return ret;
781#else
782 return -1;
783#endif
784}
785
786int midi_cb_readbuf(void) {
787 struct roar_buffer        * buf = g_midi_mess.buf;
788 struct midi_message       * mes = NULL;
789
790 ROAR_DBG("midi_cb_readbuf(void) = ?");
791
792 while (buf != NULL) {
793  ROAR_DBG("midi_cb_readbuf(void): buf=%p", buf);
794
795  if ( roar_buffer_get_data(buf, (void**)&mes) == -1 ) {
796   return -1;
797  }
798
799  switch (mes->type) {
800   case MIDI_TYPE_NOTE_ON:
801     midi_cb_start(mes->d.note.freq);
802    break;
803   case MIDI_TYPE_NOTE_OFF:
804     midi_cb_stop();
805    break;
806   case MIDI_TYPE_CONTROLER:
807     if ( mes->kk == MIDI_CCE_ALL_NOTE_OFF ) /* all note off */
808      midi_cb_stop();
809    break;
810  }
811
812  if ( roar_buffer_get_next(buf, &buf) == -1 )
813   buf = NULL;
814 }
815
816 return 0;
817}
818#endif
819
820// VIO:
821
822int     midi_vio_set_dummy(int stream) {
823 struct roar_stream_server * ss;
824
825 if ( streams_get(stream, &ss) == -1 )
826  return -1;
827
828 ss->vio.read     = NULL;
829 ss->vio.write    = NULL;
830 ss->vio.lseek    = NULL;
831 ss->vio.nonblock = (int (*)(struct roar_vio_calls * vio, int state))midi_vio_ok;
832 ss->vio.sync     = (int (*)(struct roar_vio_calls * vio))midi_vio_ok;
833 ss->vio.ctl      = NULL;
834 ss->vio.close    = (int (*)(struct roar_vio_calls * vio))midi_vio_ok;
835
836 return 0;
837}
838
839int     midi_vio_ok(struct roar_vio_calls * vio, ...) {
840 return 0;
841}
842
843#endif
844
845//ll
Note: See TracBrowser for help on using the repository browser.