source: roaraudio/roard/midi.c @ 3517:1a3218a3fc5b

Last change on this file since 3517:1a3218a3fc5b was 3517:1a3218a3fc5b, checked in by phi, 14 years ago

updated license headers, FSF moved office

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