1 /*
2 * audiointerface.h
3 * Interface definition for audio and MIDI backends.
4 *
5 * for Denemo, a gtk+ frontend to GNU Lilypond
6 * Copyright (C) 2011 Dominic Sacré
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 */
13
14 #include "audio/audiointerface.h"
15 #include "audio/eventqueue.h"
16 #include "audio/dummybackend.h"
17 #include "source/sourceaudio.h"
18 #ifdef _HAVE_JACK_
19 #include "audio/jackbackend.h"
20 #endif
21 #ifdef _HAVE_PORTAUDIO_
22 #include "audio/portaudiobackend.h"
23 #endif
24 #ifdef _HAVE_PORTMIDI_
25 #include "audio/portmidibackend.h"
26 #endif
27 #ifdef _HAVE_ALSA_
28 #include "audio/alsabackend.h"
29 #endif
30
31 #include "audio/midi.h"
32 #include "audio/audio.h"
33 #include "command/commandfuncs.h"
34 #include "display/draw.h"
35
36 #include <glib.h>
37 #include <string.h>
38 #include <stdint.h>
39
40 static backend_t *backends[NUM_BACKENDS] = { NULL };
41
42 #define PLAYBACK_QUEUE_SIZE 1024
43 #define IMMEDIATE_QUEUE_SIZE 32
44 #define INPUT_QUEUE_SIZE 256
45 #define MIXER_QUEUE_SIZE 50000
46 #define RUBBERBAND_QUEUE_SIZE 50000
47
48
49 // the time in µs after which the queue thread wakes up, whether it has been
50 // signalled or not
51 #define QUEUE_TIMEOUT 100000
52
53 static event_queue_t *event_queues[NUM_BACKENDS] = { NULL };
54
55
56 static GThread *queue_thread;
57 static GCond *queue_cond;
58 static GMutex *queue_mutex;
59
60 static double playback_start_time;
61 // FIXME: synchronize access from multiple threads
62 static volatile double playback_time;
63
64 static gboolean quit_thread;
65 static gboolean signalled = FALSE;
66 static gboolean must_redraw_all = FALSE;
67 static gboolean must_redraw_playhead = FALSE;
68
69 static smf_event_t *redraw_event;
70
71 #ifndef _HAVE_RUBBERBAND_
get_playback_speed(void)72 gdouble get_playback_speed (void)
73 {
74 return 1.0; //Rubberband can do slowdown, backend should define its own version of this
75 }
76 #endif
77
78 static gpointer queue_thread_func (gpointer data);
79 static void signal_queue ();
80
81
82
83 static backend_t *
get_backend(backend_type_t backend)84 get_backend (backend_type_t backend)
85 {
86 if (backend == DEFAULT_BACKEND)
87 {
88 // FIXME: this should be configurable
89 //return backends[MIDI_BACKEND];
90 return backends[AUDIO_BACKEND];
91 }
92 else
93 {
94 return backends[backend];
95 }
96 }
97
98 static event_queue_t *
get_event_queue(backend_type_t backend)99 get_event_queue (backend_type_t backend)
100 {
101 if (backend == DEFAULT_BACKEND)
102 {
103 // FIXME
104 // return event_queues[MIDI_BACKEND];
105 return event_queues[AUDIO_BACKEND];
106 }
107 else
108 {
109 return event_queues[backend];
110 }
111 }
112
113 static int
initialize_audio(DenemoPrefs * config)114 initialize_audio (DenemoPrefs * config)
115 {
116 char const *driver = config->audio_driver->str;
117
118 g_message ("Audio driver is '%s'", driver);
119
120 if (strcmp (driver, "jack") == 0)
121 {
122 #ifdef _HAVE_JACK_
123 backends[AUDIO_BACKEND] = &jack_audio_backend;
124 #else
125 g_warning ("JACK backend is not enabled");
126 #endif
127 }
128 else if (strcmp (driver, "portaudio") == 0)
129 {
130 #ifdef _HAVE_PORTAUDIO_
131 backends[AUDIO_BACKEND] = &portaudio_backend;
132 #else
133 g_warning ("PortAudio backend is not enabled");
134 #endif
135 }
136 else if (strcmp (driver, "dummy") == 0)
137 {
138 // do nothing
139 }
140 else
141 {
142 g_warning ("Unknown audio backend '%s'", driver);
143 }
144
145 if (backends[AUDIO_BACKEND] == NULL)
146 {
147 backends[AUDIO_BACKEND] = &dummy_audio_backend;
148 }
149
150 //event_queues[AUDIO_BACKEND] = event_queue_new(PLAYBACK_QUEUE_SIZE, IMMEDIATE_QUEUE_SIZE, 0);
151
152 int ret = get_backend (AUDIO_BACKEND)->initialize (config);
153
154 if (ret)
155 {
156 g_warning ("Initializing audio backend '%s' failed, falling back to dummy", driver);
157 backends[AUDIO_BACKEND] = &dummy_audio_backend;
158 ret = get_backend (AUDIO_BACKEND)->initialize (config);
159 }
160
161 return ret;
162 }
163
164
165 static int
initialize_midi(DenemoPrefs * config)166 initialize_midi (DenemoPrefs * config)
167 {
168 char const *driver = config->midi_driver->str;
169
170 g_message ("MIDI driver is '%s'", driver);
171
172 if (strcmp (driver, "jack") == 0)
173 {
174 #ifdef _HAVE_JACK_
175 backends[MIDI_BACKEND] = &jack_midi_backend;
176 #else
177 g_warning ("JACK backend is not enabled");
178 #endif
179 }
180 else if (strcmp (driver, "portmidi") == 0)
181 {
182 #ifdef _HAVE_PORTMIDI_
183 backends[MIDI_BACKEND] = &portmidi_backend;
184 #else
185 g_warning ("PortMidi backend is not enabled");
186 #endif
187 }
188 else if (strcmp (driver, "alsa") == 0)
189 {
190 #ifdef _HAVE_ALSA_
191 backends[MIDI_BACKEND] = &alsa_seq_midi_backend;
192 #else
193 g_warning ("ALSA backend is not enabled");
194 #endif
195 }
196 else if (strcmp (driver, "dummy") == 0)
197 {
198 // do nothing
199 }
200 else
201 {
202 g_warning ("Unknown MIDI backend '%s'", driver);
203 }
204
205 if (backends[MIDI_BACKEND] == NULL)
206 {
207 backends[MIDI_BACKEND] = &dummy_midi_backend;
208 }
209
210 //event_queues[MIDI_BACKEND] = event_queue_new(PLAYBACK_QUEUE_SIZE, IMMEDIATE_QUEUE_SIZE, INPUT_QUEUE_SIZE);
211
212 int ret = get_backend (MIDI_BACKEND)->initialize (config);
213
214 if (ret)
215 {
216 g_warning ("Initializing MIDI backend '%s' failed, falling back to dummy", driver);
217 backends[MIDI_BACKEND] = &dummy_midi_backend;
218 ret = get_backend (MIDI_BACKEND)->initialize (config);
219 }
220
221 return ret;
222 }
223
224 gboolean
have_midi(void)225 have_midi (void)
226 {
227 return strcmp (Denemo.prefs.portmidi_input_device->str, "default") && (backends[MIDI_BACKEND] != &dummy_midi_backend);
228 }
229
230 int
audio_initialize(DenemoPrefs * config)231 audio_initialize (DenemoPrefs * config)
232 {
233 queue_thread = NULL;
234 quit_thread = FALSE;
235 redraw_event = NULL;
236
237 queue_cond = g_cond_new ();
238 queue_mutex = g_mutex_new ();
239 event_queues[AUDIO_BACKEND] = event_queue_new (PLAYBACK_QUEUE_SIZE, IMMEDIATE_QUEUE_SIZE, 0, MIXER_QUEUE_SIZE
240 #ifdef _HAVE_RUBBERBAND_
241 , RUBBERBAND_QUEUE_SIZE
242 #endif
243 );
244 event_queues[MIDI_BACKEND] = event_queue_new (PLAYBACK_QUEUE_SIZE, IMMEDIATE_QUEUE_SIZE, INPUT_QUEUE_SIZE, 0
245 #ifdef _HAVE_RUBBERBAND_
246 , 0
247 #endif
248 );
249 if (initialize_audio (config) || initialize_midi(config))
250 {
251 audio_shutdown ();
252 return -1;
253 }
254
255 queue_thread = g_thread_try_new ("Queue Thread", queue_thread_func, NULL, NULL);
256
257 if (queue_thread == NULL)
258 {
259 audio_shutdown();
260 return -1;
261 }
262
263 return 0;
264 }
265
266 static int
destroy(backend_type_t backend)267 destroy (backend_type_t backend)
268 {
269 get_backend (backend)->destroy ();
270 backends[backend] = NULL;
271
272 event_queue_free (event_queues[backend]);
273
274 return 0;
275 }
276
277
278 int
audio_shutdown()279 audio_shutdown ()
280 {
281 g_atomic_int_set (&quit_thread, TRUE);
282
283 if (queue_thread)
284 {
285 signal_queue ();
286
287 g_thread_join (queue_thread);
288 }
289
290 if (get_backend (AUDIO_BACKEND))
291 {
292 destroy (AUDIO_BACKEND);
293 }
294
295 if (get_backend (MIDI_BACKEND))
296 {
297 destroy (MIDI_BACKEND);
298 }
299
300 g_cond_free (queue_cond);
301 g_mutex_free (queue_mutex);
302
303 return 0;
304 }
305
do_queue_draw(void)306 static gboolean do_queue_draw (void) {
307 draw_score_area();
308 return FALSE;
309 }
310 static gboolean
redraw_all_callback(gpointer data)311 redraw_all_callback (gpointer data)
312 {
313
314 g_main_context_invoke (NULL, (GSourceFunc)do_queue_draw, NULL);
315
316 return FALSE;
317 }
318
319 static gboolean
redraw_playhead_callback(gpointer data)320 redraw_playhead_callback (gpointer data)
321 {
322 DenemoMovement *si = Denemo.project->movement;
323
324 smf_event_t *event = (smf_event_t *) data;
325
326 si->playingnow = event->user_pointer;
327 si->playhead = event->time_seconds;
328
329 g_main_context_invoke (NULL, (GSourceFunc)do_queue_draw, NULL);
330
331 return FALSE;
332 }
333
do_handle_midi_event(gchar * data)334 static gboolean do_handle_midi_event (gchar *data) {
335 handle_midi_event (data);
336 g_free(data);
337 return FALSE;
338 }
339 static gboolean
handle_midi_event_callback(gpointer data)340 handle_midi_event_callback (gpointer data)
341 {
342
343 midi_event_t *ev = (midi_event_t *) data;
344
345 // TODO: handle backend type and port
346 gchar *evdata = g_malloc (sizeof (ev->data));
347 memcpy (evdata, ev->data, sizeof (ev->data));
348 g_main_context_invoke (NULL, (GSourceFunc)do_handle_midi_event, evdata);
349
350 g_free (ev);
351
352 return FALSE;
353 }
354
355
356 static void
reset_playback_queue(backend_type_t backend)357 reset_playback_queue (backend_type_t backend)
358 {
359 if (get_event_queue (backend))
360 {
361 event_queue_reset_playback (get_event_queue (backend));
362 }
363 }
364
365 static void
reset_mixer_queue(backend_type_t backend)366 reset_mixer_queue (backend_type_t backend)
367 {
368 if (get_event_queue (backend))
369 {
370 event_queue_reset_mixer (get_event_queue (backend));
371 }
372 }
373 #ifdef _HAVE_RUBBERBAND_
374 static void
reset_rubberband_queue(backend_type_t backend)375 reset_rubberband_queue (backend_type_t backend)
376 {
377 if (get_event_queue (backend))
378 {
379 event_queue_reset_rubberband (get_event_queue (backend));
380 }
381 }
382 #endif
383
384 static gboolean
write_event_to_queue(backend_type_t backend,smf_event_t * event)385 write_event_to_queue (backend_type_t backend, smf_event_t * event)
386 {
387 return event_queue_write_playback (get_event_queue (backend), event);
388 }
389
390 static gboolean
write_sample_to_mixer_queue(backend_type_t backend,float * sample)391 write_sample_to_mixer_queue (backend_type_t backend, float *sample)
392 {
393 return event_queue_write_mixer (get_event_queue (backend), sample);
394 }
395 #ifdef _HAVE_RUBBERBAND_
396 gboolean
write_samples_to_rubberband_queue(backend_type_t backend,float * sample,gint num)397 write_samples_to_rubberband_queue (backend_type_t backend, float *sample, gint num)
398 {gint i;
399 for(i=0;i<num;i++) {
400 if(!event_queue_write_rubberband (get_event_queue (backend), sample+i))
401 return FALSE;
402 }
403 return TRUE;
404 }
405 #endif
406 gboolean
read_event_from_queue(backend_type_t backend,unsigned char * event_buffer,size_t * event_length,double * event_time,double until_time)407 read_event_from_queue (backend_type_t backend, unsigned char *event_buffer, size_t * event_length, double *event_time, double until_time)
408 {
409 double thetime = get_playback_time (); // this is the value of the global playback_time which is volatile
410
411 if (thetime > get_end_time ())
412 {
413 if (is_playing () && thetime > 0.0) // this is the same value rather than the global, but what the check is for I do not know
414 {
415 midi_stop ();
416 }
417 }
418
419 return event_queue_read_output (get_event_queue (backend), event_buffer, event_length, event_time, until_time);
420 }
421
422 gboolean
read_event_from_mixer_queue(backend_type_t backend,unsigned char * event_buffer,size_t * event_length)423 read_event_from_mixer_queue (backend_type_t backend, unsigned char *event_buffer, size_t * event_length)
424 {
425 return mixer_queue_read_output (get_event_queue (backend), event_buffer, event_length);
426 }
427 #ifdef _HAVE_RUBBERBAND_
428
429 gboolean
read_event_from_rubberband_queue(backend_type_t backend,unsigned char * event_buffer,size_t * event_length)430 read_event_from_rubberband_queue (backend_type_t backend, unsigned char *event_buffer, size_t * event_length)
431 {
432 return rubberband_queue_read_output (get_event_queue (backend), event_buffer, event_length);
433 }
434 #endif
435 GStaticMutex smfmutex = G_STATIC_MUTEX_INIT;
436 static gpointer
queue_thread_func(gpointer data)437 queue_thread_func (gpointer data)
438 {
439 g_mutex_lock (queue_mutex);
440
441 for (;;)
442 {
443 if (!g_atomic_int_get (&signalled))
444 {
445 gint64 end_time = g_get_monotonic_time () + (QUEUE_TIMEOUT * G_TIME_SPAN_SECOND)/1000000;
446 g_cond_wait_until (queue_cond, queue_mutex, end_time);
447 signalled = FALSE;
448 }
449
450 if (g_atomic_int_get (&quit_thread))
451 {
452 g_message ("That's it, I quit!");
453 break;
454 }
455
456
457 // TODO: audio capture
458
459 midi_event_t *ev;
460
461 while ((ev = event_queue_read_input (get_event_queue (MIDI_BACKEND))) != NULL)
462 {
463 g_idle_add_full (G_PRIORITY_HIGH_IDLE, handle_midi_event_callback, (gpointer) ev, NULL);
464 }
465
466
467 if (is_playing ())
468 {
469 smf_event_t *event;
470 double until_time = playback_time + 5.0;
471
472
473 //printf("playback_time=%f, until_time=%f\n", playback_time, until_time);
474 g_static_mutex_lock (&smfmutex);
475 while ((event = get_smf_event (until_time)))
476 {
477 write_event_to_queue (AUDIO_BACKEND, event);//g_print ("queue gets 0x%hhX 0x%hhX 0x%hhX\n", *(event->midi_buffer+0), *(event->midi_buffer+1), *(event->midi_buffer+2));
478
479 write_event_to_queue (MIDI_BACKEND, event);
480 }
481 g_static_mutex_unlock (&smfmutex);
482 }
483
484 if (audio_is_playing ())
485 {
486 float sample[2]; //two channels assumed FIXME
487 //FIXME I think this will drop samples if they can't be put in the queue, should find if there is space for a sample before getting it.
488 while (get_audio_sample (sample) && write_sample_to_mixer_queue (AUDIO_BACKEND, sample))
489 ;
490 }
491
492
493 if (g_atomic_int_get (&must_redraw_all))
494 {
495 g_atomic_int_set (&must_redraw_all, FALSE);
496 g_atomic_int_set (&must_redraw_playhead, FALSE);
497
498 g_idle_add_full (G_PRIORITY_HIGH_IDLE, redraw_all_callback, NULL, NULL);
499 }
500
501 if (g_atomic_int_get (&must_redraw_playhead))
502 {
503 g_atomic_int_set (&must_redraw_playhead, FALSE);
504
505 g_idle_add_full (G_PRIORITY_HIGH_IDLE, redraw_playhead_callback, (gpointer) redraw_event, NULL);
506 }
507 }
508
509 g_mutex_unlock (queue_mutex);
510
511 return NULL;
512 }
513
514
515 static void
signal_queue()516 signal_queue ()
517 {
518 g_mutex_lock (queue_mutex);
519 g_atomic_int_set (&signalled, TRUE);
520 g_cond_signal (queue_cond);
521 g_mutex_unlock (queue_mutex);
522 }
523
524
525 static gboolean
try_signal_queue()526 try_signal_queue ()
527 {
528 if (g_mutex_trylock (queue_mutex))
529 {
530 g_atomic_int_set (&signalled, TRUE);
531 g_cond_signal (queue_cond);
532 g_mutex_unlock (queue_mutex);
533 return TRUE;
534 }
535 else
536 {
537 return FALSE;
538 }
539 }
540 static gboolean time_reset = FALSE;
541
542 void
update_playback_time(backend_timebase_prio_t prio,double new_time)543 update_playback_time (backend_timebase_prio_t prio, double new_time)
544 {
545 if (!((prio == TIMEBASE_PRIO_AUDIO) || (prio == TIMEBASE_PRIO_MIDI && get_backend (AUDIO_BACKEND) == &dummy_audio_backend) || (get_backend (AUDIO_BACKEND) == &dummy_audio_backend && get_backend (MIDI_BACKEND) == &dummy_midi_backend)))
546 {
547 // ignore new playback time if another backend has higher priority
548 return;
549 }
550 if(time_reset)
551 {
552 time_reset = FALSE;
553 return;
554 }
555 if (new_time != playback_time)
556 {
557 playback_time = new_time;
558 // midi_play tries to set playback_time, which then gets overriden by the call in the portaudio callback.
559 // if the lock fails, the playback time update will be delayed until the
560 // queue thread wakes up on its own
561 if (!try_signal_queue ())
562 {
563 ;//this is continuously emitted by windows which has debug on. g_debug ("Couldn't signal playback time update to queue");
564 }
565 }
566 }
567
568 double
get_playback_time(void)569 get_playback_time (void)
570 {
571 return playback_time;
572 }
573
574
575 void
midi_play(gchar * callback)576 midi_play (gchar * callback)
577 {
578 generate_midi ();
579
580 reset_playback_queue (AUDIO_BACKEND);
581 reset_playback_queue (MIDI_BACKEND);
582
583 g_message ("Starting playback");
584 start_playing (callback);
585 do {//FIXME, this is a crude attempt to get the playback_time set without the callback from portaudio re-writing it.
586 playback_time = playback_start_time;
587 time_reset = TRUE;
588 playback_time = playback_start_time;
589 get_backend (AUDIO_BACKEND)->start_playing ();// this must pick up the playback_start_time, which won't happen if an interrrupt has occurred meanwhile.
590 } while(playback_time != playback_start_time);
591 g_message ("Starting playback at %f", playback_start_time);
592 get_backend (MIDI_BACKEND)->start_playing ();
593 }
594
595 void
audio_play(void)596 audio_play (void)
597 {
598 reset_mixer_queue (AUDIO_BACKEND);
599 #ifdef _HAVE_RUBBERBAND_
600 reset_rubberband_queue (AUDIO_BACKEND);
601 #endif
602 playback_start_time = get_start_time ();
603 //g_debug ("starting audio playback at %f\n", playback_start_time);
604 playback_time = playback_start_time;
605
606 }
607
608 void
midi_stop(void)609 midi_stop (void)
610 {
611 g_message ("Stopping playback");
612
613 get_backend (AUDIO_BACKEND)->stop_playing ();
614 get_backend (MIDI_BACKEND)->stop_playing ();
615
616 stop_playing ();
617 stop_audio_playing ();
618 reset_playback_queue (AUDIO_BACKEND);
619 reset_playback_queue (MIDI_BACKEND);
620 reset_mixer_queue (AUDIO_BACKEND);
621 #ifdef _HAVE_RUBBERBAND_
622 reset_rubberband_queue (AUDIO_BACKEND);
623 #endif
624 gtk_widget_queue_draw (Denemo.playbackview);
625 }
626
627
628 #define MIDI_EOX (0xF7)
629
630 int
play_midi_event(backend_type_t backend,int port,unsigned char * buffer)631 play_midi_event (backend_type_t backend, int port, unsigned char *buffer)
632 {
633 if(Denemo.non_interactive)
634 return TRUE;
635 guchar ev[1 + 255]; /* 1 length byte plus up to 255 data bytes */
636 gint i = 3;
637 #ifndef _HAVE_JACK_
638 if (buffer[0] == SYS_EXCLUSIVE_MESSAGE1)
639 {
640 for (i = 0; i < 255; i++)
641 if (buffer[i] == MIDI_EOX)
642 break;
643 if (i == 255)
644 return FALSE;
645 }
646 #endif
647 *ev = i;
648 memcpy (ev + 1, buffer, i);//g_print (" midibytes 0x%hhX 0x%hhX 0x%hhX\n", *(buffer+0), *(buffer+1), *(buffer+2));
649
650 return event_queue_write_immediate (get_event_queue (backend), ev, i + 1);
651 }
652
653
654 static gboolean
play_note_noteoff_callback(gpointer data)655 play_note_noteoff_callback (gpointer data)
656 {
657 backend_type_t backend = (((intptr_t) data) >> 24);
658 int port = (((intptr_t) data) >> 16) & 0xff;
659 int channel = (((intptr_t) data) >> 8) & 0xff;
660 int key = ((intptr_t) data) & 0xff;
661
662 unsigned char buffer[] = {
663 MIDI_NOTE_OFF | channel,
664 key,
665 0
666 };
667
668 play_midi_event (backend, port, buffer);
669
670 return FALSE;
671 }
672
673 int
play_note(backend_type_t backend,int port,int channel,int key,int duration,int volume)674 play_note (backend_type_t backend, int port, int channel, int key, int duration, int volume)
675 {
676 if(Denemo.non_interactive)
677 return -1;
678
679 unsigned char buffer[] = {
680 MIDI_NOTE_ON | channel,
681 key,
682 (volume ? volume : 127) * Denemo.project->movement->master_volume
683 };
684
685 int r = play_midi_event (backend, port, buffer);
686
687 // XXX this limits the number of ports to 256...
688 gpointer data = (gpointer) (intptr_t) (backend << 24 | port << 16 | channel << 8 | key);
689 g_timeout_add (duration, play_note_noteoff_callback, data);
690
691 return r;
692 }
693
694 int
play_notes(backend_type_t backend,int port,int channel,chord * chord_to_play)695 play_notes (backend_type_t backend, int port, int channel, chord * chord_to_play)
696 {
697 if (chord_to_play->notes)
698 {
699 GList *g;
700 for (g = chord_to_play->notes; g; g = g->next)
701 {
702 note *n = g->data;
703
704 /* Because mid_c_offset is a measure of notes and we need a measure of
705 * half-steps, this array will help */
706 const gint key_offset[] = { -10, -8, -7, -5, -3, -1, 0, 2, 4, 5, 7, 9, 11 };
707
708 gint offset = n->mid_c_offset;
709
710 /* 60 is middle-C in MIDI keys */
711 gchar key = 60 + 12 * (offset / 7) + key_offset[offset % 7 + 6];
712 key += n->enshift;
713
714 // FIXME
715 play_note (backend, port, channel, key, 200, 127);
716 }
717 }
718
719 return 0;
720 }
721
722 /* give audible feedback for entering a rhythmic element */
723 static gint rhythm_sounds[] = { 41, 48, 64, 62, 60, 70, 81, 69, 79 };
724
725 int
rhythm_feedback(backend_type_t backend,gint duration,gboolean rest,gboolean dot)726 rhythm_feedback (backend_type_t backend, gint duration, gboolean rest, gboolean dot)
727 {
728 int key;
729 if (dot)
730 play_note (backend, 0, 9, 67, 100, 60 * Denemo.project->movement->master_volume);
731 else
732 play_note (backend, 0, 9, rhythm_sounds[duration], rest ? 100 : 200, 127 * Denemo.project->movement->master_volume);
733 //add extra sound effect for rests
734 if (rest)
735 play_note (backend, 0, 9, 46, 300, 127 * Denemo.project->movement->master_volume);
736 while ((key = GPOINTER_TO_INT( g_queue_pop_head (Denemo.project->pending_midi)) ))
737 play_note (backend, 0, 9, key, 300, 127 * Denemo.project->movement->master_volume);
738 //g_debug("playing %d %d\n", rhythm_sounds[duration], (60/(4*Denemo.project->movement->tempo*(1<<duration)))*1000);
739
740 return 0;
741 }
742
743
744 int
panic(backend_type_t backend)745 panic (backend_type_t backend)
746 {
747 // g_critical ("Panicking");
748 return get_backend (backend)->panic ();
749 }
750
751 int
panic_all(void)752 panic_all (void)
753 {
754 backend_type_t n;
755 for (n = 0; n < NUM_BACKENDS; ++n)
756 {
757 panic (n);
758 }
759
760 return 0;
761 }
762
763
764 void
input_midi_event(backend_type_t backend,int port,unsigned char * buffer)765 input_midi_event (backend_type_t backend, int port, unsigned char *buffer)
766 {
767 midi_event_t ev;
768 ev.backend = backend;
769 ev.port = port;
770 // FIXME: size might be less than 3
771 memcpy (&ev.data, buffer, 3);
772
773 // normalize events: replace note-on with zero velocity by note-off
774 if ((ev.data[0] & 0xf0) == MIDI_NOTE_ON && ev.data[2] == 0)
775 {
776 ev.data[0] = (ev.data[0] & 0x0f) | MIDI_NOTE_OFF;
777 }
778
779 event_queue_write_input (get_event_queue (backend), &ev);
780
781 // if the lock fails, processing of the event will be delayed until the
782 // queue thread wakes up on its own
783 if (!try_signal_queue ())
784 {
785 g_debug ("Couldn't signal MIDI event input to queue");
786 }
787 }
788
789
790 void
queue_redraw_all()791 queue_redraw_all ()
792 {
793 g_atomic_int_set (&must_redraw_all, TRUE);
794
795 if (!try_signal_queue ())
796 {
797 g_debug ("Couldn't signal redraw request to queue");
798 }
799 }
800
801 void
queue_redraw_playhead(smf_event_t * event)802 queue_redraw_playhead (smf_event_t * event)
803 {
804 g_atomic_int_set (&must_redraw_playhead, TRUE);
805 redraw_event = event;
806
807 if (!try_signal_queue ())
808 {
809 g_debug ("Couldn't signal redraw request to queue");
810 }
811 }
812
813
814
815 // FIXME: not quite sure what to do with these yet
816
817 // from fluid.c
818 void
advance_time(gdouble seconds)819 advance_time (gdouble seconds)
820 {
821 }
822
823 #if 0
824 // from audiocapture.c
825 int
826 pa_main (AubioCallback * fn)
827 {
828 return 0;
829 }
830
831 int
832 init_audio_out ()
833 {
834 return 0;
835 }
836
837 int
838 collect_data_for_tuning (int ok)
839 {
840 return 0;
841 }
842
843 double
844 determine_frequency ()
845 {
846 return 0.0;
847 }
848
849 void
850 set_frequency_smoothing (double fraction)
851 {
852 }
853
854 void
855 setTuningTarget (double pitch)
856 {
857 }
858 #endif
859