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