Attempt at fixing premature release of notes on update_playback.
[calfbox.git] / mididest.c
blob4c8933d2fdf73a923abbf83c88aa2a3f6c8bec54
1 /*
2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2013 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 "mididest.h"
20 #include "rt.h"
21 #include "stm.h"
23 void cbox_midi_merger_init(struct cbox_midi_merger *dest, struct cbox_midi_buffer *output)
25 dest->inputs = NULL;
26 dest->input_count = 0;
27 dest->output = output;
28 if (dest->output)
29 cbox_midi_buffer_clear(dest->output);
32 // void cbox_midi_buffer_merge(struct cbox_midi_buffer *output, struct cbox_midi_buffer **inputs, int count, int *positions)
33 void cbox_midi_merger_render_to(struct cbox_midi_merger *dest, struct cbox_midi_buffer *output)
35 if (!output)
36 return;
37 cbox_midi_buffer_clear(output);
38 for (int i = 0; i < dest->input_count; i++)
40 if (dest->inputs[i]->streaming)
41 dest->inputs[i]->bpos = 0;
44 while(1)
46 struct cbox_midi_source *earliest_source = NULL;
47 uint32_t earliest_time = (uint32_t)-1;
49 uint32_t mask = 0;
50 int icount = dest->input_count;
51 int spos = 0;
53 for (int i = spos; i < icount; i++)
55 if (mask & (1 << i))
56 continue;
57 struct cbox_midi_source *src = dest->inputs[i];
58 struct cbox_midi_buffer *data = src->data;
59 if (src->bpos < data->count)
61 const struct cbox_midi_event *event = cbox_midi_buffer_get_event(data, src->bpos);
62 if (event->time < earliest_time)
64 earliest_source = src;
65 earliest_time = event->time;
68 else
70 mask |= 1 << i;
71 // Narrow down the range from top and bottom
72 if (i == spos)
73 spos = i + 1;
74 if (i == icount - 1)
75 icount = i;
78 if (earliest_source)
80 cbox_midi_buffer_copy_event(output, cbox_midi_buffer_get_event(earliest_source->data, earliest_source->bpos), earliest_time);
81 earliest_source->bpos++;
83 else
84 break;
88 int cbox_midi_merger_find_source(struct cbox_midi_merger *dest, struct cbox_midi_buffer *buffer)
90 for (int i = 0; i < dest->input_count; i++)
91 if (dest->inputs[i]->data == buffer)
92 return i;
93 return -1;
96 void cbox_midi_merger_connect(struct cbox_midi_merger *dest, struct cbox_midi_buffer *buffer, struct cbox_rt *rt)
98 if (cbox_midi_merger_find_source(dest, buffer) != -1)
99 return;
101 struct cbox_midi_source *src = calloc(1, sizeof(struct cbox_midi_source));
102 src->data = buffer;
103 src->bpos = 0;
104 src->streaming = TRUE;
105 cbox_rt_array_insert(rt, (void ***)&dest->inputs, &dest->input_count, dest->input_count, src);
108 void cbox_midi_merger_disconnect(struct cbox_midi_merger *dest, struct cbox_midi_buffer *buffer, struct cbox_rt *rt)
110 int pos = cbox_midi_merger_find_source(dest, buffer);
111 if (pos == -1)
112 return;
114 cbox_rt_array_remove(rt, (void ***)&dest->inputs, &dest->input_count, pos);
117 void cbox_midi_merger_push(struct cbox_midi_merger *dest, struct cbox_midi_buffer *buffer, struct cbox_rt *rt)
119 if (!buffer->count)
120 return;
121 struct cbox_midi_source src;
122 src.data = buffer;
123 src.bpos = 0;
124 src.streaming = FALSE;
125 cbox_rt_array_insert(rt, (void ***)&dest->inputs, &dest->input_count, dest->input_count, &src);
126 while(src.bpos < buffer->count)
127 cbox_rt_handle_cmd_queue(rt);
128 cbox_rt_array_remove(rt, (void ***)&dest->inputs, &dest->input_count, dest->input_count - 1);
131 void cbox_midi_merger_close(struct cbox_midi_merger *dest)
133 for (int i = 0; i < dest->input_count; i++)
134 free(dest->inputs[i]);
135 free(dest->inputs);