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