source: roaraudio/roard/midi.c @ 1850:ac565cd518e6

Last change on this file since 1850:ac565cd518e6 was 1850:ac565cd518e6, checked in by phi, 15 years ago

started grouping g_midi_*_* to g_midi_*.* structs

File size: 6.2 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#if defined(ROAR_HAVE_IO_POSIX) && !defined(ROAR_TARGET_WIN32)
28#define _HAVE_CONSOLE
29#endif
30
31int midi_init (void) {
32
33 if ( midi_cb_init() == -1 ) {
34  ROAR_WARN("Can not initialize MIDI subsystem component CB");
35 }
36
37 if ( midi_clock_init() == -1 ) {
38  ROAR_WARN("Can not initialize MIDI subsystem component clock");
39 }
40
41 return 0;
42}
43
44int midi_free (void) {
45 return midi_cb_free();
46}
47
48int midi_update(void) {
49
50 if ( g_midi_clock.stream != -1 )
51  midi_check_bridge(g_midi_clock.stream);
52
53 return midi_cb_update();
54}
55
56// STREAMS:
57
58int midi_check_stream  (int id) {
59 struct roar_stream        *   s;
60 struct roar_stream_server *  ss;
61
62 if ( g_streams[id] == NULL )
63  return -1;
64
65 ROAR_DBG("midi_check_stream(id=%i) = ?", id);
66
67 s = ROAR_STREAM(ss = g_streams[id]);
68
69 if ( s->dir == ROAR_DIR_BRIDGE )
70  return midi_check_bridge(id);
71
72 switch (s->info.codec) {
73  default:
74    streams_delete(id);
75    return -1;
76 }
77
78 return 0;
79}
80
81int midi_send_stream   (int id) {
82 struct roar_stream        *   s;
83 struct roar_stream_server *  ss;
84
85 if ( g_streams[id] == NULL )
86  return -1;
87
88 ROAR_DBG("midi_send_stream(id=%i) = ?", id);
89
90 s = ROAR_STREAM(ss = g_streams[id]);
91
92 switch (s->info.codec) {
93  default:
94    streams_delete(id);
95    return -1;
96 }
97
98 return 0;
99}
100
101// bridges:
102int midi_check_bridge  (int id) {
103 return -1;
104}
105
106// clock:
107
108int midi_clock_init (void) {
109 struct roar_stream * s;
110 struct roar_stream_server * ss;
111
112 if ( (g_midi_clock.stream = streams_new()) == -1 ) {
113  ROAR_WARN("Error while initializing MIDI subsystem component clock");
114  return -1;
115 }
116
117 midi_vio_set_dummy(g_midi_clock.stream);
118
119 streams_get(g_midi_clock.stream, &ss);
120 s = ROAR_STREAM(ss);
121
122 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
123
124 s->pos_rel_id    =  g_midi_clock.stream;
125
126 s->info.codec    =  ROAR_CODEC_MIDI;
127 ss->codec_orgi   =  ROAR_CODEC_MIDI;
128
129 s->info.channels =  0;
130 s->info.rate     = MIDI_RATE;
131 s->info.bits     =  8;
132
133 if ( streams_set_dir(g_midi_clock.stream, ROAR_DIR_BRIDGE, 1) == -1 ) {
134  ROAR_WARN("Error while initializing MIDI subsystem component clock");
135  return -1;
136 }
137
138 streams_set_name(g_midi_clock.stream, "MIDI Clock");
139
140 streams_set_flag(g_midi_clock.stream, ROAR_FLAG_PRIMARY);
141 streams_set_flag(g_midi_clock.stream, ROAR_FLAG_SYNC);
142
143 return 0;
144}
145
146// CB:
147
148int midi_cb_init (void) {
149#ifdef _HAVE_CONSOLE
150 struct roar_stream * s;
151 struct roar_stream_server * ss;
152 int i;
153 char * files[] = {
154                   "/dev/console",
155#ifdef __linux__
156                   "/dev/tty0",
157                   "/dev/vc/0",
158#endif
159                   NULL
160                  };
161
162 g_console          = -1;
163 g_midi_cb_stream   = -1;
164 g_midi_cb_stoptime =  0;
165 g_midi_cb_playing  =  0;
166
167 for (i = 0; files[i] != NULL; i++) {
168  if ( (g_console = open(files[i], O_WRONLY|O_NOCTTY, 0)) != -1 )
169   break;
170 }
171
172 if ( g_console == -1 )
173  return -1;
174
175 if ( (g_midi_cb_stream = streams_new()) == -1 ) {
176  ROAR_WARN("Error while initializing MIDI subsystem component CB");
177  midi_cb_free();
178  return -1;
179 }
180
181 midi_vio_set_dummy(g_midi_cb_stream);
182
183 streams_get(g_midi_cb_stream, &ss);
184 s = ROAR_STREAM(ss);
185
186 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
187
188 s->pos_rel_id    = -1;
189
190 s->info.codec    =  0;
191 ss->codec_orgi   =  0;
192
193 s->info.channels =  1;
194 s->info.rate     = 1193180;
195 s->info.bits     =  8;
196
197 if ( streams_set_dir(g_midi_cb_stream, ROAR_DIR_BRIDGE, 1) == -1 ) {
198  ROAR_WARN("Error while initializing MIDI subsystem component CB");
199  midi_cb_free();
200  return -1;
201 }
202
203 streams_set_name(g_midi_cb_stream, "Console speaker bridge");
204
205 streams_set_flag(g_midi_cb_stream, ROAR_FLAG_OUTPUT);
206 streams_set_flag(g_midi_cb_stream, ROAR_FLAG_PRIMARY);
207 streams_set_flag(g_midi_cb_stream, ROAR_FLAG_HWMIXER);
208
209 return 0;
210#else
211 g_console          = -1;
212 g_midi_cb_stream   = -1;
213
214 return -1;
215#endif
216}
217
218int midi_cb_free (void) {
219#ifdef _HAVE_CONSOLE
220
221 midi_cb_stop();
222
223 if ( g_midi_cb_stream != -1 )
224  streams_delete(g_midi_cb_stream);
225
226 if ( g_console != -1 )
227  close(g_console);
228
229 return 0;
230#else
231 return -1;
232#endif
233}
234
235int midi_cb_play(float t, float freq, int override) {
236 float samples_per_sec /* S/s */ = g_sa->rate * g_sa->channels;
237
238/*
239#define MIDI_CB_NOOVERRIDE 0
240#define MIDI_CB_OVERRIDE   1
241*/
242 if ( g_midi_cb_playing && override != MIDI_CB_OVERRIDE )
243  return -1;
244
245 g_midi_cb_stoptime = ROAR_MATH_OVERFLOW_ADD(g_pos, samples_per_sec*t);
246 midi_cb_start(freq);
247 g_midi_cb_playing = 1;
248
249 return 0;
250}
251
252int midi_cb_update (void) {
253 if ( !g_midi_cb_playing )
254  return 0;
255
256 if ( g_midi_cb_stoptime <= g_pos )
257  midi_cb_stop();
258
259 return 0;
260}
261
262int midi_cb_start(float freq) {
263// On linux this uses ioctl KIOCSOUND
264#ifdef __linux__
265 if ( g_console == -1 )
266  return -1;
267
268 if ( ioctl(g_console, KIOCSOUND, freq == 0 ? 0 : (int)(1193180.0/freq)) == -1 )
269  return -1;
270
271 return 0;
272#else
273 return -1;
274#endif
275}
276
277int midi_cb_stop (void) {
278#ifdef __linux__
279 g_midi_cb_playing = 0;
280 return midi_cb_start(0);
281#else
282 return -1;
283#endif
284}
285
286// VIO:
287
288int     midi_vio_set_dummy(int stream) {
289 struct roar_stream_server * ss;
290
291 if ( streams_get(stream, &ss) == -1 )
292  return -1;
293
294 ss->vio.read     = NULL;
295 ss->vio.write    = NULL;
296 ss->vio.lseek    = NULL;
297 ss->vio.nonblock = (int (*)(struct roar_vio_calls * vio, int state))midi_vio_ok;
298 ss->vio.sync     = (int (*)(struct roar_vio_calls * vio))midi_vio_ok;
299 ss->vio.ctl      = NULL;
300 ss->vio.close    = (int (*)(struct roar_vio_calls * vio))midi_vio_ok;
301
302 return 0;
303}
304
305int     midi_vio_ok(struct roar_vio_calls * vio, ...) {
306 return 0;
307}
308
309//ll
Note: See TracBrowser for help on using the repository browser.