source: roaraudio/roard/midi.c @ 3547:4ca7b9d5d93f

Last change on this file since 3547:4ca7b9d5d93f was 3547:4ca7b9d5d93f, checked in by phi, 14 years ago

let mixer set there mapping

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