1 /*
2 * eventqueue.c
3 * event queue for audio/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/eventqueue.h"
15 #include "audio/midi.h"
16 #include "ui/moveviewport.h"
17
18 #include <glib.h>
19 #include <string.h>
20
21
22 event_queue_t *
event_queue_new(size_t playback_queue_size,size_t immediate_queue_size,size_t input_queue_size,size_t mixer_queue_size,size_t rubberband_queue_size)23 event_queue_new (size_t playback_queue_size, size_t immediate_queue_size, size_t input_queue_size, size_t mixer_queue_size
24 #ifdef _HAVE_RUBBERBAND_
25 , size_t rubberband_queue_size
26 #endif
27 )
28 {
29 event_queue_t *queue = g_malloc0 (sizeof (event_queue_t));
30
31 if (playback_queue_size)
32 {
33 queue->playback = jack_ringbuffer_create (playback_queue_size * sizeof (smf_event_t *));
34 jack_ringbuffer_reset (queue->playback);
35 }
36
37 if (immediate_queue_size)
38 {
39 queue->immediate = jack_ringbuffer_create (immediate_queue_size * sizeof (midi_event_t));
40 jack_ringbuffer_reset (queue->immediate);
41 }
42
43 if (input_queue_size)
44 {
45 queue->input = jack_ringbuffer_create (input_queue_size * sizeof (midi_event_t));
46 jack_ringbuffer_reset (queue->input);
47 }
48 if (mixer_queue_size)
49 {
50 queue->mixer = jack_ringbuffer_create (mixer_queue_size * sizeof (float));
51 jack_ringbuffer_reset (queue->mixer);
52 }
53 #ifdef _HAVE_RUBBERBAND_
54 if (rubberband_queue_size)
55 {
56 queue->rubberband = jack_ringbuffer_create (rubberband_queue_size * sizeof (float));
57 jack_ringbuffer_reset (queue->rubberband);
58 }
59 #endif
60
61 return queue;
62 }
63
64
65 void
event_queue_free(event_queue_t * queue)66 event_queue_free (event_queue_t * queue)
67 {
68 if (queue->playback)
69 {
70 jack_ringbuffer_free (queue->playback);
71 }
72
73 if (queue->immediate)
74 {
75 jack_ringbuffer_free (queue->immediate);
76 }
77
78 if (queue->input)
79 {
80 jack_ringbuffer_free (queue->input);
81 }
82
83 g_free (queue);
84 }
85
86
87 void
event_queue_reset_playback(event_queue_t * queue)88 event_queue_reset_playback (event_queue_t * queue)
89 {
90 if (queue->playback)
91 {
92 jack_ringbuffer_reset (queue->playback);
93 }
94 }
95
96 void
event_queue_reset_mixer(event_queue_t * queue)97 event_queue_reset_mixer (event_queue_t * queue)
98 {
99 if (queue->mixer)
100 {
101 jack_ringbuffer_reset (queue->mixer);
102 }
103 }
104 #ifdef _HAVE_RUBBERBAND_
105 void
event_queue_reset_rubberband(event_queue_t * queue)106 event_queue_reset_rubberband (event_queue_t * queue)
107 {
108 if (queue->rubberband)
109 {
110 jack_ringbuffer_reset (queue->rubberband);
111 }
112 }
113 #endif
114
115 gboolean
event_queue_write_playback(event_queue_t * queue,smf_event_t * event)116 event_queue_write_playback (event_queue_t * queue, smf_event_t * event)
117 {
118 if (!queue->playback || jack_ringbuffer_write_space (queue->playback) < sizeof (smf_event_t *))
119 {
120 return FALSE;
121 }
122
123 size_t n = jack_ringbuffer_write (queue->playback, (char const *) &event, sizeof (smf_event_t *));
124
125 return n == sizeof (smf_event_t *);
126 }
127
128
129 gboolean
event_queue_write_immediate(event_queue_t * queue,guchar * data,guint length)130 event_queue_write_immediate (event_queue_t * queue, guchar * data, guint length)
131 {
132 if (!queue->immediate || jack_ringbuffer_write_space (queue->immediate) < length)
133 {
134 return FALSE;
135 }
136 size_t n = jack_ringbuffer_write (queue->immediate, (char const *) data, length);
137
138 return n == length;
139
140 }
141
142 gboolean
event_queue_write_mixer(event_queue_t * queue,float * data)143 event_queue_write_mixer (event_queue_t * queue, float *data)
144 {
145 if (!queue->mixer || jack_ringbuffer_write_space (queue->mixer) < sizeof (float))
146 {
147 return FALSE;
148 }
149 size_t n = jack_ringbuffer_write (queue->mixer, (char const *) data, sizeof (float));
150
151 return n == sizeof (float);
152
153 }
154
155 #ifdef _HAVE_RUBBERBAND_
156 gboolean
event_queue_write_rubberband(event_queue_t * queue,float * data)157 event_queue_write_rubberband (event_queue_t * queue, float *data)
158 {
159 if (!queue->rubberband || jack_ringbuffer_write_space (queue->rubberband) < sizeof (float))
160 {
161 return FALSE;
162 }
163 size_t n = jack_ringbuffer_write (queue->rubberband, (char const *) data, sizeof (float));
164
165 return n == sizeof (float);
166
167 }
168 #endif
169
do_page_viewport(void)170 static gboolean do_page_viewport(void)
171 {
172
173 page_viewport ();
174 return FALSE;
175 }
176
177 static gboolean
page_viewport_callback(gpointer data)178 page_viewport_callback (gpointer data)
179 {
180
181 g_main_context_invoke (NULL, (GSourceFunc)do_page_viewport, NULL);
182
183 return FALSE;
184 }
185
186 static void
page_for_time(gdouble time_seconds)187 page_for_time (gdouble time_seconds)
188 {
189 DenemoMovement *si = Denemo.project->movement;
190 if ((si->rightmost_time > 0.0) && (time_seconds > si->rightmost_time))
191 {
192 si->rightmost_time = -1;
193 g_idle_add_full (G_PRIORITY_HIGH_IDLE, page_viewport_callback, NULL, NULL);
194 }
195 }
196
197
198 gboolean
mixer_queue_read_output(event_queue_t * queue,unsigned char * event_buffer,size_t * event_length)199 mixer_queue_read_output (event_queue_t * queue, unsigned char *event_buffer, size_t * event_length)
200 {
201 if (jack_ringbuffer_read_space (queue->mixer) >= (*event_length) * sizeof (float))
202 {
203 *event_length = jack_ringbuffer_read (queue->mixer, (char *) event_buffer, (*event_length) * sizeof (float)) / sizeof (float);
204 return TRUE;
205 }
206 *event_length = 0;
207 return FALSE;
208 }
209 #ifdef _HAVE_RUBBERBAND_
210 gboolean
rubberband_queue_read_output(event_queue_t * queue,unsigned char * event_buffer,size_t * event_length)211 rubberband_queue_read_output (event_queue_t * queue, unsigned char *event_buffer, size_t * event_length)
212 {
213 if (jack_ringbuffer_read_space (queue->rubberband) >= (*event_length) * sizeof (float))
214 {
215 *event_length = jack_ringbuffer_read (queue->rubberband, (char *) event_buffer, (*event_length) * sizeof (float)) / sizeof (float);
216 return TRUE;
217 }
218 *event_length = 0;
219 return FALSE;
220 }
221 #endif
222 gboolean
event_queue_read_output(event_queue_t * queue,unsigned char * event_buffer,size_t * event_length,double * event_time,double until_time)223 event_queue_read_output (event_queue_t * queue, unsigned char *event_buffer, size_t * event_length, double *event_time, double until_time)
224 {
225
226 #if 0
227 //old fixed length code
228 if (jack_ringbuffer_read_space (queue->immediate))
229 {
230 midi_event_t event;
231
232 jack_ringbuffer_read (queue->immediate, (char *) &event, sizeof (midi_event_t));
233
234 memcpy (event_buffer, &event.data, 3);
235 // FIXME
236 *event_length = 3;
237 *event_time = 0.0;
238
239 return TRUE;
240 }
241 #else
242 if (jack_ringbuffer_read_space (queue->immediate))
243 {
244 jack_ringbuffer_data_t vec[2];
245 jack_ringbuffer_get_read_vector (queue->immediate, vec);
246 if (vec[0].len)
247 {
248 guchar length;
249 jack_ringbuffer_read (queue->immediate, (char*) &length, 1);
250 //g_assert (length < 255);
251 jack_ringbuffer_read (queue->immediate, (char*) event_buffer, length);
252 *event_length = length;
253 *event_time = 0.0;
254 return TRUE;
255 }
256 }
257 #endif
258
259 if (!queue->playback)
260 {
261 return FALSE;
262 }
263
264 for (;;)
265 {
266 smf_event_t *event;
267
268 // printf("is_playing=%d, playback_time=%f, end_time=%f\n", is_playing(), get_playback_time(), get_end_time());
269
270 if (!jack_ringbuffer_read_space (queue->playback))
271 {
272 // printf("no more events in playback queue\n");
273
274 return FALSE;
275 }
276
277 jack_ringbuffer_peek (queue->playback, (char *) &event, sizeof (smf_event_t *));
278
279 if (event->time_seconds >= until_time)
280 {
281 // printf("no event to play right now\n");
282
283 return FALSE;
284 }
285
286 if (smf_event_is_metadata (event))
287 {
288 // consume metadata event and continue with the next one
289 jack_ringbuffer_read_advance (queue->playback, sizeof (smf_event_t *));
290 continue;
291 }
292
293 // consume the event
294 jack_ringbuffer_read_advance (queue->playback, sizeof (smf_event_t *));
295
296 //g_assert(event->midi_buffer_length <= 3);
297
298 update_position (event);
299 adjust_midi_velocity ((gchar*)event->midi_buffer, 100 - Denemo.prefs.dynamic_compression);
300 memcpy (event_buffer, event->midi_buffer, event->midi_buffer_length);
301 *event_length = event->midi_buffer_length;
302 *event_time = event->time_seconds;
303 page_for_time (*event_time);
304
305 // printf("event_time=%f\n", *event_time);
306
307 return TRUE;
308 }
309 }
310
311
312 gboolean
event_queue_write_input(event_queue_t * queue,midi_event_t const * event)313 event_queue_write_input (event_queue_t * queue, midi_event_t const *event)
314 {
315 if (!queue->input || jack_ringbuffer_write_space (queue->input) < sizeof (midi_event_t))
316 {
317 return FALSE;
318 }
319
320 size_t n = jack_ringbuffer_write (queue->input, (char *) event, sizeof (midi_event_t));
321
322 return n == sizeof (midi_event_t);
323 }
324
325
326 midi_event_t *
event_queue_read_input(event_queue_t * queue)327 event_queue_read_input (event_queue_t * queue)
328 {
329 if (!queue->input)
330 {
331 return NULL;
332 }
333
334 if (jack_ringbuffer_read_space (queue->input))
335 {
336 midi_event_t *ev = g_malloc (sizeof (midi_event_t));
337 jack_ringbuffer_read (queue->input, (char *) ev, sizeof (midi_event_t));
338 return ev;
339 }
340 else
341 {
342 return NULL;
343 }
344 }
345