Eliminate known memory leaks.
[calfbox.git] / rt.c
blobd845ff8b7df9de7a2c08fd3fb891f1c6dfbc2703
1 /*
2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2011 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "auxbus.h"
20 #include "instr.h"
21 #include "io.h"
22 #include "layer.h"
23 #include "midi.h"
24 #include "module.h"
25 #include "rt.h"
26 #include "scene.h"
27 #include "seq.h"
28 #include "song.h"
29 #include "stm.h"
30 #include "track.h"
31 #include <assert.h>
32 #include <stdio.h>
33 #include <unistd.h>
35 CBOX_CLASS_DEFINITION_ROOT(cbox_rt)
37 struct cbox_rt_cmd_instance
39 struct cbox_rt_cmd_definition *definition;
40 void *user_data;
41 int is_async;
44 static gboolean cbox_rt_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error)
46 struct cbox_rt *rt = ct->user_data;
47 if (!strcmp(cmd->command, "/status") && !strcmp(cmd->arg_types, ""))
49 if (!cbox_check_fb_channel(fb, cmd->command, error))
50 return FALSE;
51 if (rt->io)
53 GError *cerror = NULL;
54 if (cbox_io_get_disconnect_status(rt->io, &cerror))
56 return cbox_execute_on(fb, NULL, "/audio_channels", "ii", error, rt->io->input_count, rt->io->output_count) &&
57 cbox_execute_on(fb, NULL, "/state", "is", error, 1, "OK") &&
58 CBOX_OBJECT_DEFAULT_STATUS(rt, fb, error);
60 else
62 return cbox_execute_on(fb, NULL, "/audio_channels", "ii", error, rt->io->input_count, rt->io->output_count) &&
63 cbox_execute_on(fb, NULL, "/state", "is", error, -1, cerror ? cerror->message : "Unknown error") &&
64 CBOX_OBJECT_DEFAULT_STATUS(rt, fb, error);
67 else
68 return cbox_execute_on(fb, NULL, "/audio_channels", "ii", error, 0, 2) &&
69 cbox_execute_on(fb, NULL, "/state", "is", error, 0, "Offline") &&
70 CBOX_OBJECT_DEFAULT_STATUS(rt, fb, error);
72 else if (!strcmp(cmd->command, "/cycle") && !strcmp(cmd->arg_types, ""))
74 if (rt->io && !cbox_io_get_disconnect_status(rt->io, NULL))
76 return cbox_io_cycle(rt->io, fb, error);
78 else
80 if (rt->io)
81 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Already connected");
82 else
83 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot cycle connection in off-line mode");
84 return FALSE;
87 else
88 return cbox_object_default_process_cmd(ct, fb, cmd, error);
91 struct cbox_rt *cbox_rt_new(struct cbox_document *doc)
93 struct cbox_rt *rt = malloc(sizeof(struct cbox_rt));
94 CBOX_OBJECT_HEADER_INIT(rt, cbox_rt, doc);
95 rt->scene = NULL;
96 rt->effect = NULL;
97 rt->rb_execute = jack_ringbuffer_create(sizeof(struct cbox_rt_cmd_instance) * RT_CMD_QUEUE_ITEMS);
98 rt->rb_cleanup = jack_ringbuffer_create(sizeof(struct cbox_rt_cmd_instance) * RT_CMD_QUEUE_ITEMS * 2);
99 rt->io = NULL;
100 rt->master = cbox_master_new(rt);
101 rt->master->song = cbox_song_new(CBOX_GET_DOCUMENT(rt));
102 rt->started = FALSE;
103 rt->disconnected = FALSE;
104 rt->srate = 0;
105 rt->buffer_size = 0;
106 cbox_midi_buffer_init(&rt->midibuf_aux);
107 cbox_midi_buffer_init(&rt->midibuf_jack);
108 cbox_midi_buffer_init(&rt->midibuf_song);
109 cbox_midi_buffer_init(&rt->midibuf_total);
110 cbox_midi_merger_init(&rt->scene_input_merger, &rt->midibuf_total);
112 cbox_midi_merger_connect(&rt->scene_input_merger, &rt->midibuf_aux, NULL);
113 cbox_midi_merger_connect(&rt->scene_input_merger, &rt->midibuf_jack, NULL);
114 cbox_midi_merger_connect(&rt->scene_input_merger, &rt->midibuf_song, NULL);
116 cbox_command_target_init(&rt->cmd_target, cbox_rt_process_cmd, rt);
117 CBOX_OBJECT_REGISTER(rt);
118 cbox_document_set_service(doc, "rt", &rt->_obj_hdr);
120 return rt;
123 struct cbox_objhdr *cbox_rt_newfunc(struct cbox_class *class_ptr, struct cbox_document *doc)
125 return NULL;
128 void cbox_rt_destroyfunc(struct cbox_objhdr *obj_ptr)
132 static void cbox_rt_on_disconnected(void *user_data)
134 struct cbox_rt *rt = user_data;
135 rt->disconnected = TRUE;
138 static void cbox_rt_on_reconnected(void *user_data)
140 struct cbox_rt *rt = user_data;
141 rt->disconnected = FALSE;
144 static void cbox_rt_process(void *user_data, struct cbox_io *io, uint32_t nframes)
146 struct cbox_rt *rt = user_data;
147 struct cbox_module *effect = rt->effect;
148 struct cbox_rt_cmd_instance cmd;
149 int cost;
150 uint32_t i, j;
152 cbox_midi_buffer_clear(&rt->midibuf_aux);
153 cbox_midi_buffer_clear(&rt->midibuf_song);
154 cbox_midi_buffer_clear(&rt->midibuf_total);
155 cbox_io_get_midi_data(io, &rt->midibuf_jack);
157 // Process command queue, needs MIDI aux buf to work
158 cost = 0;
159 while(cost < RT_MAX_COST_PER_CALL && jack_ringbuffer_peek(rt->rb_execute, (char *)&cmd, sizeof(cmd)))
161 int result = (cmd.definition->execute)(cmd.user_data);
162 if (!result)
163 break;
164 cost += result;
165 jack_ringbuffer_read_advance(rt->rb_execute, sizeof(cmd));
166 if (cmd.definition->cleanup || !cmd.is_async)
168 jack_ringbuffer_write(rt->rb_cleanup, (const char *)&cmd, sizeof(cmd));
172 // Combine various sources of events (song, non-RT thread, JACK input)
173 if (rt->scene && rt->scene->spb)
174 cbox_song_playback_render(rt->scene->spb, &rt->midibuf_song, nframes);
176 cbox_midi_merger_render(&rt->scene_input_merger);
178 if (rt->scene)
179 cbox_scene_render(rt->scene, nframes, &rt->midibuf_total, io->output_buffers);
181 // Process "master" effect
182 if (effect)
184 for (i = 0; i < nframes; i += CBOX_BLOCK_SIZE)
186 cbox_sample_t left[CBOX_BLOCK_SIZE], right[CBOX_BLOCK_SIZE];
187 cbox_sample_t *in_bufs[2] = {io->output_buffers[0] + i, io->output_buffers[1] + i};
188 cbox_sample_t *out_bufs[2] = {left, right};
189 (*effect->process_block)(effect, in_bufs, out_bufs);
190 for (j = 0; j < CBOX_BLOCK_SIZE; j++)
192 io->output_buffers[0][i + j] = left[j];
193 io->output_buffers[1][i + j] = right[j];
200 void cbox_rt_set_io(struct cbox_rt *rt, struct cbox_io *io)
202 assert(!rt->started);
203 rt->io = io;
204 if (io)
206 rt->srate = cbox_io_get_sample_rate(io);
207 rt->buffer_size = cbox_io_get_buffer_size(io);
208 cbox_master_set_sample_rate(rt->master, rt->srate);
210 else
212 rt->srate = 0;
213 rt->buffer_size = 0;
217 void cbox_rt_set_offline(struct cbox_rt *rt, int sample_rate, int buffer_size)
219 assert(!rt->started);
220 rt->io = NULL;
221 rt->srate = sample_rate;
222 rt->buffer_size = buffer_size;
223 cbox_master_set_sample_rate(rt->master, rt->srate);
226 void cbox_rt_start(struct cbox_rt *rt, struct cbox_command_target *fb)
228 if (rt->io)
230 rt->started = 1;
231 rt->cbs = malloc(sizeof(struct cbox_io_callbacks));
232 rt->cbs->user_data = rt;
233 rt->cbs->process = cbox_rt_process;
234 rt->cbs->on_disconnected = cbox_rt_on_disconnected;
235 rt->cbs->on_reconnected = cbox_rt_on_reconnected;
237 cbox_io_start(rt->io, rt->cbs, fb);
241 void cbox_rt_stop(struct cbox_rt *rt)
243 if (rt->io)
245 assert(rt->started);
246 cbox_io_stop(rt->io);
247 free(rt->cbs);
248 rt->cbs = NULL;
249 rt->started = 0;
253 void cbox_rt_handle_cmd_queue(struct cbox_rt *rt)
255 struct cbox_rt_cmd_instance cmd;
257 while(jack_ringbuffer_read(rt->rb_cleanup, (char *)&cmd, sizeof(cmd)))
259 cmd.definition->cleanup(cmd.user_data);
263 static void wait_write_space(jack_ringbuffer_t *rb)
265 int t = 0;
266 while (jack_ringbuffer_write_space(rb) < sizeof(struct cbox_rt_cmd_instance))
268 // wait until some space frees up in the execute queue
269 usleep(1000);
270 t++;
271 if (t >= 1000)
273 fprintf(stderr, "Execute queue full, waiting...\n");
274 t = 0;
279 void cbox_rt_execute_cmd_sync(struct cbox_rt *rt, struct cbox_rt_cmd_definition *def, void *user_data)
281 struct cbox_rt_cmd_instance cmd;
283 if (def->prepare)
284 if (def->prepare(user_data))
285 return;
287 // No realtime thread - do it all in the main thread
288 if (!rt->started || rt->disconnected)
290 def->execute(user_data);
291 if (def->cleanup)
292 def->cleanup(user_data);
293 return;
296 memset(&cmd, 0, sizeof(cmd));
297 cmd.definition = def;
298 cmd.user_data = user_data;
299 cmd.is_async = 0;
301 wait_write_space(rt->rb_execute);
302 jack_ringbuffer_write(rt->rb_execute, (const char *)&cmd, sizeof(cmd));
305 struct cbox_rt_cmd_instance cmd2;
307 if (jack_ringbuffer_read_space(rt->rb_cleanup) < sizeof(cmd2))
309 // still no result in cleanup queue - wait
310 usleep(10000);
311 continue;
313 jack_ringbuffer_read(rt->rb_cleanup, (char *)&cmd2, sizeof(cmd2));
314 if (!memcmp(&cmd, &cmd2, sizeof(cmd)))
316 if (def->cleanup)
317 def->cleanup(user_data);
318 break;
320 // async command - clean it up
321 if (cmd2.definition->cleanup)
322 cmd2.definition->cleanup(cmd2.user_data);
323 } while(1);
326 void cbox_rt_execute_cmd_async(struct cbox_rt *rt, struct cbox_rt_cmd_definition *def, void *user_data)
328 struct cbox_rt_cmd_instance cmd = { def, user_data, 1 };
330 if (def->prepare)
332 if (def->prepare(user_data))
333 return;
335 // No realtime thread - do it all in the main thread
336 if (!rt->started)
338 def->execute(user_data);
339 if (def->cleanup)
340 def->cleanup(user_data);
341 return;
344 wait_write_space(rt->rb_execute);
345 jack_ringbuffer_write(rt->rb_execute, (const char *)&cmd, sizeof(cmd));
347 // will be cleaned up by next sync call or by cbox_rt_cmd_handle_queue
350 ////////////////////////////////////////////////////////////////////////////////////////
352 struct set_song_command
354 struct cbox_rt *rt;
355 struct cbox_song_playback *new_song, *old_song;
356 int new_time_ppqn;
359 static int set_song_command_execute(void *user_data)
361 struct set_song_command *cmd = user_data;
363 if (cmd->rt->scene && cmd->rt->scene->spb &&
364 cbox_song_playback_active_notes_release(cmd->rt->scene->spb, &cmd->rt->midibuf_aux) < 0)
365 return 0;
366 cmd->old_song = cmd->rt->master->spb;
367 if (cmd->rt->scene)
368 cmd->rt->scene->spb = cmd->new_song;
369 cmd->rt->master->spb = cmd->new_song;
370 if (cmd->new_song)
372 if (cmd->new_time_ppqn == -1)
373 cbox_song_playback_seek_samples(cmd->rt->master->spb, cmd->old_song ? cmd->old_song->song_pos_samples : 0);
374 else
375 cbox_song_playback_seek_ppqn(cmd->rt->master->spb, cmd->new_time_ppqn, FALSE);
378 return 1;
381 void cbox_rt_update_song(struct cbox_rt *rt, int new_pos_ppqn)
383 static struct cbox_rt_cmd_definition def = { .prepare = NULL, .execute = set_song_command_execute, .cleanup = NULL };
385 struct set_song_command cmd = { rt, cbox_song_playback_new(rt->master->song, rt->master), NULL, new_pos_ppqn };
386 cbox_rt_execute_cmd_sync(rt, &def, &cmd);
387 if (cmd.old_song)
388 cbox_song_playback_destroy(cmd.old_song);
391 ////////////////////////////////////////////////////////////////////////////////////////
393 void cbox_rt_update_song_playback(struct cbox_rt *rt)
395 cbox_rt_update_song(rt, -1);
398 ////////////////////////////////////////////////////////////////////////////////////////
400 struct send_events_command
402 struct cbox_rt *rt;
404 struct cbox_midi_buffer *buffer;
405 int pos;
406 int time_delta;
409 static int send_events_command_execute(void *user_data)
411 struct send_events_command *cmd = user_data;
413 // all done?
414 if (cmd->pos >= cbox_midi_buffer_get_count(cmd->buffer))
415 return 1;
417 int last_time = cbox_midi_buffer_get_last_event_time(&cmd->rt->midibuf_aux);
418 while (cmd->pos < cbox_midi_buffer_get_count(cmd->buffer))
420 struct cbox_midi_event *event = cbox_midi_buffer_get_event(cmd->buffer, cmd->pos);
421 int time = event->time - cmd->time_delta;
422 if (time < last_time)
423 time = last_time;
424 cbox_midi_buffer_copy_event(&cmd->rt->midibuf_aux, event, time);
425 cmd->pos++;
427 assert(cmd->rt->buffer_size);
428 cmd->time_delta += cmd->rt->buffer_size;
430 return (cmd->pos >= cbox_midi_buffer_get_count(cmd->buffer)) ? 1 : 0;
433 void cbox_rt_send_events(struct cbox_rt *rt, struct cbox_midi_buffer *buffer)
435 if (cbox_midi_buffer_get_count(buffer) == 0)
436 return;
438 static struct cbox_rt_cmd_definition def = { .prepare = NULL, .execute = send_events_command_execute, .cleanup = NULL };
440 struct send_events_command cmd = { rt, buffer, 0, 0 };
442 cbox_rt_execute_cmd_sync(rt, &def, &cmd);
445 ////////////////////////////////////////////////////////////////////////////////////////
447 struct swap_pointers_command
449 void **ptr;
450 void *old_value;
451 void *new_value;
452 int *pcount;
453 int new_count;
456 static int swap_pointers_command_execute(void *user_data)
458 struct swap_pointers_command *cmd = user_data;
460 cmd->old_value = *cmd->ptr;
461 *cmd->ptr = cmd->new_value;
462 if (cmd->pcount)
463 *cmd->pcount = cmd->new_count;
465 return 1;
468 void *cbox_rt_swap_pointers(struct cbox_rt *rt, void **ptr, void *new_value)
470 if (rt)
472 static struct cbox_rt_cmd_definition scdef = { .prepare = NULL, .execute = swap_pointers_command_execute, .cleanup = NULL };
474 struct swap_pointers_command sc = { ptr, NULL, new_value, NULL, 0 };
476 cbox_rt_execute_cmd_sync(rt, &scdef, &sc);
478 return sc.old_value;
479 } else {
480 void *old_ptr = *ptr;
481 *ptr = new_value;
482 return old_ptr;
486 void *cbox_rt_swap_pointers_and_update_count(struct cbox_rt *rt, void **ptr, void *new_value, int *pcount, int new_count)
488 if (rt)
490 static struct cbox_rt_cmd_definition scdef = { .prepare = NULL, .execute = swap_pointers_command_execute, .cleanup = NULL };
492 struct swap_pointers_command sc = { ptr, NULL, new_value, pcount, new_count };
494 cbox_rt_execute_cmd_sync(rt, &scdef, &sc);
496 return sc.old_value;
498 else
500 void *old_ptr = *ptr;
501 *ptr = new_value;
502 *pcount = new_count;
503 return old_ptr;
507 void cbox_rt_array_insert(struct cbox_rt *rt, void ***ptr, int *pcount, int index, void *new_value)
509 assert(index >= -1);
510 assert(index <= *pcount);
511 assert(*pcount >= 0);
512 void **new_array = stm_array_clone_insert(*ptr, *pcount, index, new_value);
513 free(cbox_rt_swap_pointers_and_update_count(rt, (void **)ptr, new_array, pcount, *pcount + 1));
516 void *cbox_rt_array_remove(struct cbox_rt *rt, void ***ptr, int *pcount, int index)
518 if (index == -1)
519 index = *pcount - 1;
520 assert(index >= 0);
521 assert(index < *pcount);
522 assert(*pcount > 0);
523 void *p = (*ptr)[index];
524 void **new_array = stm_array_clone_remove(*ptr, *pcount, index);
525 free(cbox_rt_swap_pointers_and_update_count(rt, (void **)ptr, new_array, pcount, *pcount - 1));
526 return p;
529 ////////////////////////////////////////////////////////////////////////////////////////
531 struct cbox_scene *cbox_rt_set_scene(struct cbox_rt *rt, struct cbox_scene *scene)
533 if (scene)
534 scene->spb = rt->master->spb;
535 return cbox_rt_swap_pointers(rt, (void **)&rt->scene, scene);
538 ////////////////////////////////////////////////////////////////////////////////////////
540 int cbox_rt_get_sample_rate(struct cbox_rt *rt)
542 assert(rt->srate);
543 return rt->srate;
546 int cbox_rt_get_buffer_size(struct cbox_rt *rt)
548 assert(rt->buffer_size);
549 return rt->buffer_size;
552 ////////////////////////////////////////////////////////////////////////////////////////
554 void cbox_rt_destroy(struct cbox_rt *rt)
556 if (rt->master->song)
557 CBOX_DELETE(rt->master->song);
558 jack_ringbuffer_free(rt->rb_execute);
559 jack_ringbuffer_free(rt->rb_cleanup);
561 cbox_master_destroy(rt->master);
562 rt->master = NULL;
564 cbox_midi_merger_close(&rt->scene_input_merger);
566 free(rt);