1 /*
2  * dummybackend.c
3  * Dummy audio and MIDI backend.
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/dummybackend.h"
15 #include "audio/midi.h"
16 
17 #include <glib.h>
18 
19 
20 // only affects GUI update, 10 Hz should be enough
21 static int const PLAYBACK_INTERVAL = 100000;
22 
23 
24 #if 0
25 static GThread *process_thread = NULL;
26 static GCond *process_cond = NULL;
27 static gboolean quit_thread = FALSE;
28 #endif
29 
30 static gboolean dummy_audio = FALSE;
31 static gboolean dummy_midi = FALSE;
32 
33 static double playback_start_time;
34 
35 
36 #if 0
37 static gpointer
38 process_thread_func (gpointer data)
39 {
40   GMutex *mutex = g_mutex_new ();
41   gint64 end_time;
42   g_mutex_lock (mutex);
43   for (;;)
44     {
45       end_time = g_get_monotonic_time () +  (PLAYBACK_INTERVAL * G_TIME_SPAN_SECOND)/1000000;
46       g_cond_wait_until (process_cond, mutex, end_time);
47 
48       if (g_atomic_int_get (&quit_thread))
49         {
50           break;
51         }
52 
53       GTimeVal tv;
54       g_get_current_time (&tv);
55       double now = (double) tv.tv_sec + tv.tv_usec / 1000000.0;
56       double playback_time = now - playback_start_time;
57 
58       unsigned char event_data[3];
59       size_t event_length;
60       double event_time;
61 
62       double until_time = playback_time + PLAYBACK_INTERVAL / 1000000.0;
63 
64       if (g_atomic_int_get (&dummy_audio))
65         {
66           // clear the audio event queue
67           while (read_event_from_queue (AUDIO_BACKEND, event_data, &event_length, &event_time, until_time))
68             {
69               // do nothing. this is the dummy backend after all
70             }
71           if (is_playing ())
72             {
73                 update_playback_time (TIMEBASE_PRIO_DUMMY, playback_time);
74             }
75         }
76 
77       if (g_atomic_int_get (&dummy_midi))
78         {
79           // clear the MIDI event queue
80           while (read_event_from_queue (MIDI_BACKEND, event_data, &event_length, &event_time, until_time))
81             {
82               // do nothing. this is the dummy backend after all
83             }
84         }
85     }
86   g_mutex_unlock (mutex);
87   g_mutex_free (mutex);
88   return NULL;
89 }
90 
91 
92 static void
93 start_process_thread ()
94 {
95   if (!process_thread)
96     {
97       process_cond = g_cond_new ();
98       process_thread = g_thread_try_new ("Dummy process", process_thread_func, NULL, NULL);
99     }
100 }
101 
102 
103 static void
104 stop_process_thread ()
105 {
106   if (dummy_audio || dummy_midi)
107     {
108       return;
109     }
110 
111   if (process_thread)
112     {
113       g_atomic_int_set (&quit_thread, TRUE);
114       g_cond_signal (process_cond);
115       g_thread_join (process_thread);
116 
117       process_thread = NULL;
118     }
119 }
120 #endif
121 
122 
123 static int
dummy_audio_initialize(DenemoPrefs * config)124 dummy_audio_initialize (DenemoPrefs * config)
125 {
126   g_message ("Initializing dummy audio backend");
127 
128 #if 0
129   start_process_thread ();
130 #endif
131 
132   g_atomic_int_set (&dummy_audio, TRUE);
133 
134   return 0;
135 }
136 
137 static int
dummy_midi_initialize(DenemoPrefs * config)138 dummy_midi_initialize (DenemoPrefs * config)
139 {
140   g_message ("Initializing dummy MIDI backend");
141 
142 #if 0
143   start_process_thread ();
144 #endif
145 
146   g_atomic_int_set (&dummy_midi, TRUE);
147 
148   return 0;
149 }
150 
151 
152 static int
dummy_audio_destroy()153 dummy_audio_destroy ()
154 {
155   g_message ("Destroying dummy audio backend");
156 
157   g_atomic_int_set (&dummy_audio, FALSE);
158 
159 #if 0
160   stop_process_thread ();
161 #endif
162 
163   return 0;
164 }
165 
166 static int
dummy_midi_destroy()167 dummy_midi_destroy ()
168 {
169   g_message ("Destroying dummy MIDI backend");
170 
171   g_atomic_int_set (&dummy_midi, FALSE);
172 
173 #if 0
174   stop_process_thread ();
175 #endif
176 
177   return 0;
178 }
179 
180 
181 static int
dummy_audio_reconfigure(DenemoPrefs * config)182 dummy_audio_reconfigure (DenemoPrefs * config)
183 {
184   dummy_audio_destroy ();
185   return dummy_audio_initialize (config);
186 }
187 
188 static int
dummy_midi_reconfigure(DenemoPrefs * config)189 dummy_midi_reconfigure (DenemoPrefs * config)
190 {
191   dummy_midi_destroy ();
192   return dummy_midi_initialize (config);
193 }
194 
195 
196 static int
dummy_start_playing()197 dummy_start_playing ()
198 {
199   GTimeVal tv;
200   g_get_current_time (&tv);
201   playback_start_time = (double) tv.tv_sec + tv.tv_usec / 1000000.0;
202   playback_start_time -= get_playback_time ();
203   return 0;
204 }
205 
206 
207 static int
dummy_stop_playing()208 dummy_stop_playing ()
209 {
210   return 0;
211 }
212 
213 
214 static int
dummy_panic()215 dummy_panic ()
216 {
217   return 0;
218 }
219 
220 
221 backend_t dummy_audio_backend = {
222   dummy_audio_initialize,
223   dummy_audio_destroy,
224   dummy_audio_reconfigure,
225   dummy_start_playing,
226   dummy_stop_playing,
227   dummy_panic,
228 };
229 
230 backend_t dummy_midi_backend = {
231   dummy_midi_initialize,
232   dummy_midi_destroy,
233   dummy_midi_reconfigure,
234   dummy_start_playing,
235   dummy_stop_playing,
236   dummy_panic,
237 };
238