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