rev |
line source |
nuclear@0
|
1 /*-
|
nuclear@0
|
2 * Copyright (c) 2007, 2008 Edward Tomasz NapieraĆa <trasz@FreeBSD.org>
|
nuclear@0
|
3 * All rights reserved.
|
nuclear@0
|
4 *
|
nuclear@0
|
5 * Redistribution and use in source and binary forms, with or without
|
nuclear@0
|
6 * modification, are permitted provided that the following conditions
|
nuclear@0
|
7 * are met:
|
nuclear@0
|
8 * 1. Redistributions of source code must retain the above copyright
|
nuclear@0
|
9 * notice, this list of conditions and the following disclaimer.
|
nuclear@0
|
10 * 2. Redistributions in binary form must reproduce the above copyright
|
nuclear@0
|
11 * notice, this list of conditions and the following disclaimer in the
|
nuclear@0
|
12 * documentation and/or other materials provided with the distribution.
|
nuclear@0
|
13 *
|
nuclear@0
|
14 * ALTHOUGH THIS SOFTWARE IS MADE OF WIN AND SCIENCE, IT IS PROVIDED BY THE
|
nuclear@0
|
15 * AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
nuclear@0
|
16 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
nuclear@0
|
17 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
nuclear@0
|
18 * THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
nuclear@0
|
20 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
nuclear@0
|
21 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
nuclear@0
|
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
nuclear@0
|
23 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
nuclear@0
|
24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
25 *
|
nuclear@0
|
26 */
|
nuclear@0
|
27
|
nuclear@0
|
28 /**
|
nuclear@0
|
29 * \file
|
nuclear@0
|
30 *
|
nuclear@0
|
31 * Various functions.
|
nuclear@0
|
32 *
|
nuclear@0
|
33 */
|
nuclear@0
|
34
|
nuclear@0
|
35 /* Reference: http://www.borg.com/~jglatt/tech/midifile.htm */
|
nuclear@0
|
36
|
nuclear@0
|
37 #include <stdlib.h>
|
nuclear@0
|
38 #include <string.h>
|
nuclear@0
|
39 #include <assert.h>
|
nuclear@0
|
40 #include <math.h>
|
nuclear@0
|
41 #include <errno.h>
|
nuclear@0
|
42 #ifdef __MINGW32__
|
nuclear@0
|
43 #include <windows.h>
|
nuclear@0
|
44 #else /* ! __MINGW32__ */
|
nuclear@0
|
45 #include <arpa/inet.h>
|
nuclear@0
|
46 #endif /* ! __MINGW32__ */
|
nuclear@0
|
47 #include "smf.h"
|
nuclear@0
|
48 #include "smf_private.h"
|
nuclear@0
|
49
|
nuclear@0
|
50 /**
|
nuclear@0
|
51 * Allocates new smf_t structure.
|
nuclear@0
|
52 * \return pointer to smf_t or NULL.
|
nuclear@0
|
53 */
|
nuclear@0
|
54 smf_t *
|
nuclear@0
|
55 smf_new(void)
|
nuclear@0
|
56 {
|
nuclear@0
|
57 int cantfail;
|
nuclear@0
|
58
|
nuclear@0
|
59 smf_t *smf = malloc(sizeof(smf_t));
|
nuclear@0
|
60 if (smf == NULL) {
|
nuclear@0
|
61 fg_critical("Cannot allocate smf_t structure: %s", strerror(errno));
|
nuclear@0
|
62 return (NULL);
|
nuclear@0
|
63 }
|
nuclear@0
|
64
|
nuclear@0
|
65 memset(smf, 0, sizeof(smf_t));
|
nuclear@0
|
66
|
nuclear@0
|
67 smf->tracks_array = fg_ptr_array_new();
|
nuclear@0
|
68 assert(smf->tracks_array);
|
nuclear@0
|
69
|
nuclear@0
|
70 smf->tempo_array = fg_ptr_array_new();
|
nuclear@0
|
71 assert(smf->tempo_array);
|
nuclear@0
|
72
|
nuclear@0
|
73 cantfail = smf_set_ppqn(smf, 120);
|
nuclear@0
|
74 assert(!cantfail);
|
nuclear@0
|
75
|
nuclear@0
|
76 cantfail = smf_set_format(smf, 0);
|
nuclear@0
|
77 assert(!cantfail);
|
nuclear@0
|
78
|
nuclear@0
|
79 smf_init_tempo(smf);
|
nuclear@0
|
80
|
nuclear@0
|
81 return (smf);
|
nuclear@0
|
82 }
|
nuclear@0
|
83
|
nuclear@0
|
84 /**
|
nuclear@0
|
85 * Frees smf and all it's descendant structures.
|
nuclear@0
|
86 */
|
nuclear@0
|
87 void
|
nuclear@0
|
88 smf_delete(smf_t *smf)
|
nuclear@0
|
89 {
|
nuclear@0
|
90 /* Remove all the tracks, from last to first. */
|
nuclear@0
|
91 while (smf->tracks_array->len > 0)
|
nuclear@0
|
92 smf_track_delete(fg_ptr_array_index(smf->tracks_array, smf->tracks_array->len - 1));
|
nuclear@0
|
93
|
nuclear@0
|
94 smf_fini_tempo(smf);
|
nuclear@0
|
95
|
nuclear@0
|
96 assert(smf->tracks_array->len == 0);
|
nuclear@0
|
97 assert(smf->number_of_tracks == 0);
|
nuclear@0
|
98 fg_ptr_array_free(smf->tracks_array, TRUE);
|
nuclear@0
|
99 fg_ptr_array_free(smf->tempo_array, TRUE);
|
nuclear@0
|
100
|
nuclear@0
|
101 memset(smf, 0, sizeof(smf_t));
|
nuclear@0
|
102 free(smf);
|
nuclear@0
|
103 }
|
nuclear@0
|
104
|
nuclear@0
|
105 /**
|
nuclear@0
|
106 * Allocates new smf_track_t structure.
|
nuclear@0
|
107 * \return pointer to smf_track_t or NULL.
|
nuclear@0
|
108 */
|
nuclear@0
|
109 smf_track_t *
|
nuclear@0
|
110 smf_track_new(void)
|
nuclear@0
|
111 {
|
nuclear@0
|
112 smf_track_t *track = malloc(sizeof(smf_track_t));
|
nuclear@0
|
113 if (track == NULL) {
|
nuclear@0
|
114 fg_critical("Cannot allocate smf_track_t structure: %s", strerror(errno));
|
nuclear@0
|
115 return (NULL);
|
nuclear@0
|
116 }
|
nuclear@0
|
117
|
nuclear@0
|
118 memset(track, 0, sizeof(smf_track_t));
|
nuclear@0
|
119 track->next_event_number = -1;
|
nuclear@0
|
120
|
nuclear@0
|
121 track->events_array = fg_ptr_array_new();
|
nuclear@0
|
122 assert(track->events_array);
|
nuclear@0
|
123
|
nuclear@0
|
124 return (track);
|
nuclear@0
|
125 }
|
nuclear@0
|
126
|
nuclear@0
|
127 /**
|
nuclear@0
|
128 * Detaches track from its smf and frees it.
|
nuclear@0
|
129 */
|
nuclear@0
|
130 void
|
nuclear@0
|
131 smf_track_delete(smf_track_t *track)
|
nuclear@0
|
132 {
|
nuclear@0
|
133 assert(track);
|
nuclear@0
|
134 assert(track->events_array);
|
nuclear@0
|
135
|
nuclear@0
|
136 /* Remove all the events, from last to first. */
|
nuclear@0
|
137 while (track->events_array->len > 0)
|
nuclear@0
|
138 smf_event_delete(fg_ptr_array_index(track->events_array, track->events_array->len - 1));
|
nuclear@0
|
139
|
nuclear@0
|
140 if (track->smf)
|
nuclear@0
|
141 smf_track_remove_from_smf(track);
|
nuclear@0
|
142
|
nuclear@0
|
143 assert(track->events_array->len == 0);
|
nuclear@0
|
144 assert(track->number_of_events == 0);
|
nuclear@0
|
145 fg_ptr_array_free(track->events_array, TRUE);
|
nuclear@0
|
146
|
nuclear@0
|
147 memset(track, 0, sizeof(smf_track_t));
|
nuclear@0
|
148 free(track);
|
nuclear@0
|
149 }
|
nuclear@0
|
150
|
nuclear@0
|
151
|
nuclear@0
|
152 /**
|
nuclear@0
|
153 * Appends smf_track_t to smf.
|
nuclear@0
|
154 */
|
nuclear@0
|
155 void
|
nuclear@0
|
156 smf_add_track(smf_t *smf, smf_track_t *track)
|
nuclear@0
|
157 {
|
nuclear@0
|
158 int cantfail;
|
nuclear@0
|
159
|
nuclear@0
|
160 assert(track->smf == NULL);
|
nuclear@0
|
161
|
nuclear@0
|
162 track->smf = smf;
|
nuclear@0
|
163 fg_ptr_array_add(smf->tracks_array, track);
|
nuclear@0
|
164
|
nuclear@0
|
165 smf->number_of_tracks++;
|
nuclear@0
|
166 track->track_number = smf->number_of_tracks;
|
nuclear@0
|
167
|
nuclear@0
|
168 if (smf->number_of_tracks > 1) {
|
nuclear@0
|
169 cantfail = smf_set_format(smf, 1);
|
nuclear@0
|
170 assert(!cantfail);
|
nuclear@0
|
171 }
|
nuclear@0
|
172 }
|
nuclear@0
|
173
|
nuclear@0
|
174 /**
|
nuclear@0
|
175 * Detaches track from the smf.
|
nuclear@0
|
176 */
|
nuclear@0
|
177 void
|
nuclear@0
|
178 smf_track_remove_from_smf(smf_track_t *track)
|
nuclear@0
|
179 {
|
nuclear@0
|
180 int i, j;
|
nuclear@0
|
181 smf_track_t *tmp;
|
nuclear@0
|
182 smf_event_t *ev;
|
nuclear@0
|
183
|
nuclear@0
|
184 assert(track->smf != NULL);
|
nuclear@0
|
185
|
nuclear@0
|
186 track->smf->number_of_tracks--;
|
nuclear@0
|
187
|
nuclear@0
|
188 assert(track->smf->tracks_array);
|
nuclear@0
|
189 fg_ptr_array_remove(track->smf->tracks_array, track);
|
nuclear@0
|
190
|
nuclear@0
|
191 /* Renumber the rest of the tracks, so they are consecutively numbered. */
|
nuclear@0
|
192 for (i = track->track_number; i <= track->smf->number_of_tracks; i++) {
|
nuclear@0
|
193 tmp = smf_get_track_by_number(track->smf, i);
|
nuclear@0
|
194 tmp->track_number = i;
|
nuclear@0
|
195
|
nuclear@0
|
196 /*
|
nuclear@0
|
197 * Events have track numbers too. I guess this wasn't a wise
|
nuclear@0
|
198 * decision. ;-/
|
nuclear@0
|
199 */
|
nuclear@0
|
200 for (j = 1; j <= tmp->number_of_events; j++) {
|
nuclear@0
|
201 ev = smf_track_get_event_by_number(tmp, j);
|
nuclear@0
|
202 ev->track_number = i;
|
nuclear@0
|
203 }
|
nuclear@0
|
204 }
|
nuclear@0
|
205
|
nuclear@0
|
206 track->track_number = -1;
|
nuclear@0
|
207 track->smf = NULL;
|
nuclear@0
|
208 }
|
nuclear@0
|
209
|
nuclear@0
|
210 /**
|
nuclear@0
|
211 * Allocates new smf_event_t structure. The caller is responsible for allocating
|
nuclear@0
|
212 * event->midi_buffer, filling it with MIDI data and setting event->midi_buffer_length properly.
|
nuclear@0
|
213 * Note that event->midi_buffer will be freed by smf_event_delete.
|
nuclear@0
|
214 * \return pointer to smf_event_t or NULL.
|
nuclear@0
|
215 */
|
nuclear@0
|
216 smf_event_t *
|
nuclear@0
|
217 smf_event_new(void)
|
nuclear@0
|
218 {
|
nuclear@0
|
219 smf_event_t *event = malloc(sizeof(smf_event_t));
|
nuclear@0
|
220 if (event == NULL) {
|
nuclear@0
|
221 fg_critical("Cannot allocate smf_event_t structure: %s", strerror(errno));
|
nuclear@0
|
222 return (NULL);
|
nuclear@0
|
223 }
|
nuclear@0
|
224
|
nuclear@0
|
225 memset(event, 0, sizeof(smf_event_t));
|
nuclear@0
|
226
|
nuclear@0
|
227 event->delta_time_pulses = -1;
|
nuclear@0
|
228 event->time_pulses = -1;
|
nuclear@0
|
229 event->time_seconds = -1.0;
|
nuclear@0
|
230 event->track_number = -1;
|
nuclear@0
|
231
|
nuclear@0
|
232 return (event);
|
nuclear@0
|
233 }
|
nuclear@0
|
234
|
nuclear@0
|
235 /**
|
nuclear@0
|
236 * Allocates an smf_event_t structure and fills it with "len" bytes copied
|
nuclear@0
|
237 * from "midi_data".
|
nuclear@0
|
238 * \param midi_data Pointer to MIDI data. It sill be copied to the newly allocated event->midi_buffer.
|
nuclear@0
|
239 * \param len Length of the buffer. It must be proper MIDI event length, e.g. 3 for Note On event.
|
nuclear@0
|
240 * \return Event containing MIDI data or NULL.
|
nuclear@0
|
241 */
|
nuclear@0
|
242 smf_event_t *
|
nuclear@0
|
243 smf_event_new_from_pointer(void *midi_data, int len)
|
nuclear@0
|
244 {
|
nuclear@0
|
245 smf_event_t *event;
|
nuclear@0
|
246
|
nuclear@0
|
247 event = smf_event_new();
|
nuclear@0
|
248 if (event == NULL)
|
nuclear@0
|
249 return (NULL);
|
nuclear@0
|
250
|
nuclear@0
|
251 event->midi_buffer_length = len;
|
nuclear@0
|
252 event->midi_buffer = malloc(event->midi_buffer_length);
|
nuclear@0
|
253 if (event->midi_buffer == NULL) {
|
nuclear@0
|
254 fg_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno));
|
nuclear@0
|
255 smf_event_delete(event);
|
nuclear@0
|
256
|
nuclear@0
|
257 return (NULL);
|
nuclear@0
|
258 }
|
nuclear@0
|
259
|
nuclear@0
|
260 memcpy(event->midi_buffer, midi_data, len);
|
nuclear@0
|
261
|
nuclear@0
|
262 return (event);
|
nuclear@0
|
263 }
|
nuclear@0
|
264
|
nuclear@0
|
265 /**
|
nuclear@0
|
266 * Allocates an smf_event_t structure and fills it with at most three bytes of data.
|
nuclear@0
|
267 * For example, if you need to create Note On event, do something like this:
|
nuclear@0
|
268 *
|
nuclear@0
|
269 * smf_event_new_from_bytes(0x90, 0x3C, 0x7f);
|
nuclear@0
|
270 *
|
nuclear@0
|
271 * To create event for MIDI message that is shorter than three bytes, do something
|
nuclear@0
|
272 * like this:
|
nuclear@0
|
273 *
|
nuclear@0
|
274 * smf_event_new_from_bytes(0xC0, 0x42, -1);
|
nuclear@0
|
275 *
|
nuclear@0
|
276 * \param first_byte First byte of MIDI message. Must be valid status byte.
|
nuclear@0
|
277 * \param second_byte Second byte of MIDI message or -1, if message is one byte long.
|
nuclear@0
|
278 * \param third_byte Third byte of MIDI message or -1, if message is two bytes long.
|
nuclear@0
|
279 * \return Event containing MIDI data or NULL.
|
nuclear@0
|
280 */
|
nuclear@0
|
281 smf_event_t *
|
nuclear@0
|
282 smf_event_new_from_bytes(int first_byte, int second_byte, int third_byte)
|
nuclear@0
|
283 {
|
nuclear@0
|
284 int len;
|
nuclear@0
|
285
|
nuclear@0
|
286 smf_event_t *event;
|
nuclear@0
|
287
|
nuclear@0
|
288 event = smf_event_new();
|
nuclear@0
|
289 if (event == NULL)
|
nuclear@0
|
290 return (NULL);
|
nuclear@0
|
291
|
nuclear@0
|
292 if (first_byte < 0) {
|
nuclear@0
|
293 fg_critical("First byte of MIDI message cannot be < 0");
|
nuclear@0
|
294 smf_event_delete(event);
|
nuclear@0
|
295
|
nuclear@0
|
296 return (NULL);
|
nuclear@0
|
297 }
|
nuclear@0
|
298
|
nuclear@0
|
299 if (first_byte > 255) {
|
nuclear@0
|
300 fg_critical("smf_event_new_from_bytes: first byte is %d, which is larger than 255.", first_byte);
|
nuclear@0
|
301 return (NULL);
|
nuclear@0
|
302 }
|
nuclear@0
|
303
|
nuclear@0
|
304 if (!is_status_byte(first_byte)) {
|
nuclear@0
|
305 fg_critical("smf_event_new_from_bytes: first byte is not a valid status byte.");
|
nuclear@0
|
306 return (NULL);
|
nuclear@0
|
307 }
|
nuclear@0
|
308
|
nuclear@0
|
309
|
nuclear@0
|
310 if (second_byte < 0)
|
nuclear@0
|
311 len = 1;
|
nuclear@0
|
312 else if (third_byte < 0)
|
nuclear@0
|
313 len = 2;
|
nuclear@0
|
314 else
|
nuclear@0
|
315 len = 3;
|
nuclear@0
|
316
|
nuclear@0
|
317 if (len > 1) {
|
nuclear@0
|
318 if (second_byte > 255) {
|
nuclear@0
|
319 fg_critical("smf_event_new_from_bytes: second byte is %d, which is larger than 255.", second_byte);
|
nuclear@0
|
320 return (NULL);
|
nuclear@0
|
321 }
|
nuclear@0
|
322
|
nuclear@0
|
323 if (is_status_byte(second_byte)) {
|
nuclear@0
|
324 fg_critical("smf_event_new_from_bytes: second byte cannot be a status byte.");
|
nuclear@0
|
325 return (NULL);
|
nuclear@0
|
326 }
|
nuclear@0
|
327 }
|
nuclear@0
|
328
|
nuclear@0
|
329 if (len > 2) {
|
nuclear@0
|
330 if (third_byte > 255) {
|
nuclear@0
|
331 fg_critical("smf_event_new_from_bytes: third byte is %d, which is larger than 255.", third_byte);
|
nuclear@0
|
332 return (NULL);
|
nuclear@0
|
333 }
|
nuclear@0
|
334
|
nuclear@0
|
335 if (is_status_byte(third_byte)) {
|
nuclear@0
|
336 fg_critical("smf_event_new_from_bytes: third byte cannot be a status byte.");
|
nuclear@0
|
337 return (NULL);
|
nuclear@0
|
338 }
|
nuclear@0
|
339 }
|
nuclear@0
|
340
|
nuclear@0
|
341 event->midi_buffer_length = len;
|
nuclear@0
|
342 event->midi_buffer = malloc(event->midi_buffer_length);
|
nuclear@0
|
343 if (event->midi_buffer == NULL) {
|
nuclear@0
|
344 fg_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno));
|
nuclear@0
|
345 smf_event_delete(event);
|
nuclear@0
|
346
|
nuclear@0
|
347 return (NULL);
|
nuclear@0
|
348 }
|
nuclear@0
|
349
|
nuclear@0
|
350 event->midi_buffer[0] = first_byte;
|
nuclear@0
|
351 if (len > 1)
|
nuclear@0
|
352 event->midi_buffer[1] = second_byte;
|
nuclear@0
|
353 if (len > 2)
|
nuclear@0
|
354 event->midi_buffer[2] = third_byte;
|
nuclear@0
|
355
|
nuclear@0
|
356 return (event);
|
nuclear@0
|
357 }
|
nuclear@0
|
358
|
nuclear@0
|
359 /**
|
nuclear@0
|
360 * Detaches event from its track and frees it.
|
nuclear@0
|
361 */
|
nuclear@0
|
362 void
|
nuclear@0
|
363 smf_event_delete(smf_event_t *event)
|
nuclear@0
|
364 {
|
nuclear@0
|
365 if (event->track != NULL)
|
nuclear@0
|
366 smf_event_remove_from_track(event);
|
nuclear@0
|
367
|
nuclear@0
|
368 if (event->midi_buffer != NULL) {
|
nuclear@0
|
369 memset(event->midi_buffer, 0, event->midi_buffer_length);
|
nuclear@0
|
370 free(event->midi_buffer);
|
nuclear@0
|
371 }
|
nuclear@0
|
372
|
nuclear@0
|
373 memset(event, 0, sizeof(smf_event_t));
|
nuclear@0
|
374 free(event);
|
nuclear@0
|
375 }
|
nuclear@0
|
376
|
nuclear@0
|
377 /**
|
nuclear@0
|
378 * Used for sorting track->events_array.
|
nuclear@0
|
379 */
|
nuclear@0
|
380 static gint
|
nuclear@0
|
381 events_array_compare_function(gconstpointer aa, gconstpointer bb)
|
nuclear@0
|
382 {
|
nuclear@0
|
383 smf_event_t *a, *b;
|
nuclear@0
|
384
|
nuclear@0
|
385 /* "The comparison function for fg_ptr_array_sort() doesn't take the pointers
|
nuclear@0
|
386 from the array as arguments, it takes pointers to the pointers in the array." */
|
nuclear@0
|
387 a = (smf_event_t *)*(gpointer *)aa;
|
nuclear@0
|
388 b = (smf_event_t *)*(gpointer *)bb;
|
nuclear@0
|
389
|
nuclear@0
|
390 if (a->time_pulses < b->time_pulses)
|
nuclear@0
|
391 return (-1);
|
nuclear@0
|
392
|
nuclear@0
|
393 if (a->time_pulses > b->time_pulses)
|
nuclear@0
|
394 return (1);
|
nuclear@0
|
395
|
nuclear@0
|
396 /*
|
nuclear@0
|
397 * We need to preserve original order, otherwise things will break
|
nuclear@0
|
398 * when there are several events with the same ->time_pulses.
|
nuclear@0
|
399 * XXX: This is an ugly hack; we should remove sorting altogether.
|
nuclear@0
|
400 */
|
nuclear@0
|
401
|
nuclear@0
|
402 if (a->event_number < b->event_number)
|
nuclear@0
|
403 return (-1);
|
nuclear@0
|
404
|
nuclear@0
|
405 if (a->event_number > b->event_number)
|
nuclear@0
|
406 return (1);
|
nuclear@0
|
407
|
nuclear@0
|
408 return (0);
|
nuclear@0
|
409 }
|
nuclear@0
|
410
|
nuclear@0
|
411 /*
|
nuclear@0
|
412 * An assumption here is that if there is an EOT event, it will be at the end of the track.
|
nuclear@0
|
413 */
|
nuclear@0
|
414 static void
|
nuclear@0
|
415 remove_eot_if_before_pulses(smf_track_t *track, int pulses)
|
nuclear@0
|
416 {
|
nuclear@0
|
417 smf_event_t *event;
|
nuclear@0
|
418
|
nuclear@0
|
419 event = smf_track_get_last_event(track);
|
nuclear@0
|
420
|
nuclear@0
|
421 if (event == NULL)
|
nuclear@0
|
422 return;
|
nuclear@0
|
423
|
nuclear@0
|
424 if (!smf_event_is_eot(event))
|
nuclear@0
|
425 return;
|
nuclear@0
|
426
|
nuclear@0
|
427 if (event->time_pulses > pulses)
|
nuclear@0
|
428 return;
|
nuclear@0
|
429
|
nuclear@0
|
430 smf_event_remove_from_track(event);
|
nuclear@0
|
431 }
|
nuclear@0
|
432
|
nuclear@0
|
433 /**
|
nuclear@0
|
434 * Adds the event to the track and computes ->delta_pulses. Note that it is faster
|
nuclear@0
|
435 * to append events to the end of the track than to insert them in the middle.
|
nuclear@0
|
436 * Usually you want to use smf_track_add_event_seconds or smf_track_add_event_pulses
|
nuclear@0
|
437 * instead of this one. Event needs to have ->time_pulses and ->time_seconds already set.
|
nuclear@0
|
438 * If you try to add event after an EOT, EOT event will be automatically deleted.
|
nuclear@0
|
439 */
|
nuclear@0
|
440 void
|
nuclear@0
|
441 smf_track_add_event(smf_track_t *track, smf_event_t *event)
|
nuclear@0
|
442 {
|
nuclear@0
|
443 int i, last_pulses = 0;
|
nuclear@0
|
444
|
nuclear@0
|
445 assert(track->smf != NULL);
|
nuclear@0
|
446 assert(event->track == NULL);
|
nuclear@0
|
447 assert(event->delta_time_pulses == -1);
|
nuclear@0
|
448 assert(event->time_pulses >= 0);
|
nuclear@0
|
449 assert(event->time_seconds >= 0.0);
|
nuclear@0
|
450
|
nuclear@0
|
451 remove_eot_if_before_pulses(track, event->time_pulses);
|
nuclear@0
|
452
|
nuclear@0
|
453 event->track = track;
|
nuclear@0
|
454 event->track_number = track->track_number;
|
nuclear@0
|
455
|
nuclear@0
|
456 if (track->number_of_events == 0) {
|
nuclear@0
|
457 assert(track->next_event_number == -1);
|
nuclear@0
|
458 track->next_event_number = 1;
|
nuclear@0
|
459 }
|
nuclear@0
|
460
|
nuclear@0
|
461 if (track->number_of_events > 0)
|
nuclear@0
|
462 last_pulses = smf_track_get_last_event(track)->time_pulses;
|
nuclear@0
|
463
|
nuclear@0
|
464 track->number_of_events++;
|
nuclear@0
|
465
|
nuclear@0
|
466 /* Are we just appending element at the end of the track? */
|
nuclear@0
|
467 if (last_pulses <= event->time_pulses) {
|
nuclear@0
|
468 event->delta_time_pulses = event->time_pulses - last_pulses;
|
nuclear@0
|
469 assert(event->delta_time_pulses >= 0);
|
nuclear@0
|
470 fg_ptr_array_add(track->events_array, event);
|
nuclear@0
|
471 event->event_number = track->number_of_events;
|
nuclear@0
|
472
|
nuclear@0
|
473 /* We need to insert in the middle of the track. XXX: This is slow. */
|
nuclear@0
|
474 } else {
|
nuclear@0
|
475 /* Append, then sort according to ->time_pulses. */
|
nuclear@0
|
476 fg_ptr_array_add(track->events_array, event);
|
nuclear@0
|
477 fg_ptr_array_sort(track->events_array, events_array_compare_function);
|
nuclear@0
|
478
|
nuclear@0
|
479 /* Renumber entries and fix their ->delta_pulses. */
|
nuclear@0
|
480 for (i = 1; i <= track->number_of_events; i++) {
|
nuclear@0
|
481 smf_event_t *tmp = smf_track_get_event_by_number(track, i);
|
nuclear@0
|
482 tmp->event_number = i;
|
nuclear@0
|
483
|
nuclear@0
|
484 if (tmp->delta_time_pulses != -1)
|
nuclear@0
|
485 continue;
|
nuclear@0
|
486
|
nuclear@0
|
487 if (i == 1) {
|
nuclear@0
|
488 tmp->delta_time_pulses = tmp->time_pulses;
|
nuclear@0
|
489 } else {
|
nuclear@0
|
490 tmp->delta_time_pulses = tmp->time_pulses -
|
nuclear@0
|
491 smf_track_get_event_by_number(track, i - 1)->time_pulses;
|
nuclear@0
|
492 assert(tmp->delta_time_pulses >= 0);
|
nuclear@0
|
493 }
|
nuclear@0
|
494 }
|
nuclear@0
|
495
|
nuclear@0
|
496 /* Adjust ->delta_time_pulses of the next event. */
|
nuclear@0
|
497 if (event->event_number < track->number_of_events) {
|
nuclear@0
|
498 smf_event_t *next_event = smf_track_get_event_by_number(track, event->event_number + 1);
|
nuclear@0
|
499 assert(next_event);
|
nuclear@0
|
500 assert(next_event->time_pulses >= event->time_pulses);
|
nuclear@0
|
501 next_event->delta_time_pulses -= event->delta_time_pulses;
|
nuclear@0
|
502 assert(next_event->delta_time_pulses >= 0);
|
nuclear@0
|
503 }
|
nuclear@0
|
504 }
|
nuclear@0
|
505
|
nuclear@0
|
506 if (smf_event_is_tempo_change_or_time_signature(event)) {
|
nuclear@0
|
507 if (smf_event_is_last(event))
|
nuclear@0
|
508 maybe_add_to_tempo_map(event);
|
nuclear@0
|
509 else
|
nuclear@0
|
510 smf_create_tempo_map_and_compute_seconds(event->track->smf);
|
nuclear@0
|
511 }
|
nuclear@0
|
512 }
|
nuclear@0
|
513
|
nuclear@0
|
514 /**
|
nuclear@0
|
515 * Add End Of Track metaevent. Using it is optional, libsmf will automatically
|
nuclear@0
|
516 * add EOT to the tracks during smf_save, with delta_pulses 0. If you try to add EOT
|
nuclear@0
|
517 * in the middle of the track, it will fail and nonzero value will be returned.
|
nuclear@0
|
518 * If you try to add EOT after another EOT event, it will be added, but the existing
|
nuclear@0
|
519 * EOT event will be removed.
|
nuclear@0
|
520 *
|
nuclear@0
|
521 * \return 0 if everything went ok, nonzero otherwise.
|
nuclear@0
|
522 */
|
nuclear@0
|
523 int
|
nuclear@0
|
524 smf_track_add_eot_delta_pulses(smf_track_t *track, int delta)
|
nuclear@0
|
525 {
|
nuclear@0
|
526 smf_event_t *event;
|
nuclear@0
|
527
|
nuclear@0
|
528 event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00);
|
nuclear@0
|
529 if (event == NULL)
|
nuclear@0
|
530 return (-1);
|
nuclear@0
|
531
|
nuclear@0
|
532 smf_track_add_event_delta_pulses(track, event, delta);
|
nuclear@0
|
533
|
nuclear@0
|
534 return (0);
|
nuclear@0
|
535 }
|
nuclear@0
|
536
|
nuclear@0
|
537 int
|
nuclear@0
|
538 smf_track_add_eot_pulses(smf_track_t *track, int pulses)
|
nuclear@0
|
539 {
|
nuclear@0
|
540 smf_event_t *event, *last_event;
|
nuclear@0
|
541
|
nuclear@0
|
542 last_event = smf_track_get_last_event(track);
|
nuclear@0
|
543 if (last_event != NULL) {
|
nuclear@0
|
544 if (last_event->time_pulses > pulses)
|
nuclear@0
|
545 return (-2);
|
nuclear@0
|
546 }
|
nuclear@0
|
547
|
nuclear@0
|
548 event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00);
|
nuclear@0
|
549 if (event == NULL)
|
nuclear@0
|
550 return (-3);
|
nuclear@0
|
551
|
nuclear@0
|
552 smf_track_add_event_pulses(track, event, pulses);
|
nuclear@0
|
553
|
nuclear@0
|
554 return (0);
|
nuclear@0
|
555 }
|
nuclear@0
|
556
|
nuclear@0
|
557 int
|
nuclear@0
|
558 smf_track_add_eot_seconds(smf_track_t *track, double seconds)
|
nuclear@0
|
559 {
|
nuclear@0
|
560 smf_event_t *event, *last_event;
|
nuclear@0
|
561
|
nuclear@0
|
562 last_event = smf_track_get_last_event(track);
|
nuclear@0
|
563 if (last_event != NULL) {
|
nuclear@0
|
564 if (last_event->time_seconds > seconds)
|
nuclear@0
|
565 return (-2);
|
nuclear@0
|
566 }
|
nuclear@0
|
567
|
nuclear@0
|
568 event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00);
|
nuclear@0
|
569 if (event == NULL)
|
nuclear@0
|
570 return (-1);
|
nuclear@0
|
571
|
nuclear@0
|
572 smf_track_add_event_seconds(track, event, seconds);
|
nuclear@0
|
573
|
nuclear@0
|
574 return (0);
|
nuclear@0
|
575 }
|
nuclear@0
|
576
|
nuclear@0
|
577 /**
|
nuclear@0
|
578 * Detaches event from its track.
|
nuclear@0
|
579 */
|
nuclear@0
|
580 void
|
nuclear@0
|
581 smf_event_remove_from_track(smf_event_t *event)
|
nuclear@0
|
582 {
|
nuclear@0
|
583 int i, was_last;
|
nuclear@0
|
584 smf_event_t *tmp;
|
nuclear@0
|
585 smf_track_t *track;
|
nuclear@0
|
586
|
nuclear@0
|
587 assert(event->track != NULL);
|
nuclear@0
|
588 assert(event->track->smf != NULL);
|
nuclear@0
|
589
|
nuclear@0
|
590 track = event->track;
|
nuclear@0
|
591 was_last = smf_event_is_last(event);
|
nuclear@0
|
592
|
nuclear@0
|
593 /* Adjust ->delta_time_pulses of the next event. */
|
nuclear@0
|
594 if (event->event_number < track->number_of_events) {
|
nuclear@0
|
595 tmp = smf_track_get_event_by_number(track, event->event_number + 1);
|
nuclear@0
|
596 assert(tmp);
|
nuclear@0
|
597 tmp->delta_time_pulses += event->delta_time_pulses;
|
nuclear@0
|
598 }
|
nuclear@0
|
599
|
nuclear@0
|
600 track->number_of_events--;
|
nuclear@0
|
601 fg_ptr_array_remove(track->events_array, event);
|
nuclear@0
|
602
|
nuclear@0
|
603 if (track->number_of_events == 0)
|
nuclear@0
|
604 track->next_event_number = -1;
|
nuclear@0
|
605
|
nuclear@0
|
606 /* Renumber the rest of the events, so they are consecutively numbered. */
|
nuclear@0
|
607 for (i = event->event_number; i <= track->number_of_events; i++) {
|
nuclear@0
|
608 tmp = smf_track_get_event_by_number(track, i);
|
nuclear@0
|
609 tmp->event_number = i;
|
nuclear@0
|
610 }
|
nuclear@0
|
611
|
nuclear@0
|
612 if (smf_event_is_tempo_change_or_time_signature(event)) {
|
nuclear@0
|
613 /* XXX: This will cause problems, when there is more than one Tempo Change event at a given time. */
|
nuclear@0
|
614 if (was_last)
|
nuclear@0
|
615 remove_last_tempo_with_pulses(event->track->smf, event->time_pulses);
|
nuclear@0
|
616 else
|
nuclear@0
|
617 smf_create_tempo_map_and_compute_seconds(track->smf);
|
nuclear@0
|
618 }
|
nuclear@0
|
619
|
nuclear@0
|
620 event->track = NULL;
|
nuclear@0
|
621 event->event_number = -1;
|
nuclear@0
|
622 event->delta_time_pulses = -1;
|
nuclear@0
|
623 event->time_pulses = -1;
|
nuclear@0
|
624 event->time_seconds = -1.0;
|
nuclear@0
|
625 }
|
nuclear@0
|
626
|
nuclear@0
|
627 /**
|
nuclear@0
|
628 * \return Nonzero if event is Tempo Change or Time Signature metaevent.
|
nuclear@0
|
629 */
|
nuclear@0
|
630 int
|
nuclear@0
|
631 smf_event_is_tempo_change_or_time_signature(const smf_event_t *event)
|
nuclear@0
|
632 {
|
nuclear@0
|
633 if (!smf_event_is_metadata(event))
|
nuclear@0
|
634 return (0);
|
nuclear@0
|
635
|
nuclear@0
|
636 assert(event->midi_buffer_length >= 2);
|
nuclear@0
|
637
|
nuclear@0
|
638 if (event->midi_buffer[1] == 0x51 || event->midi_buffer[1] == 0x58)
|
nuclear@0
|
639 return (1);
|
nuclear@0
|
640
|
nuclear@0
|
641 return (0);
|
nuclear@0
|
642 }
|
nuclear@0
|
643
|
nuclear@0
|
644 /**
|
nuclear@0
|
645 * Sets "Format" field of MThd header to the specified value. Note that you
|
nuclear@0
|
646 * don't really need to use this, as libsmf will automatically change format
|
nuclear@0
|
647 * from 0 to 1 when you add the second track.
|
nuclear@0
|
648 * \param smf SMF.
|
nuclear@0
|
649 * \param format 0 for one track per file, 1 for several tracks per file.
|
nuclear@0
|
650 */
|
nuclear@0
|
651 int
|
nuclear@0
|
652 smf_set_format(smf_t *smf, int format)
|
nuclear@0
|
653 {
|
nuclear@0
|
654 assert(format == 0 || format == 1);
|
nuclear@0
|
655
|
nuclear@0
|
656 if (smf->number_of_tracks > 1 && format == 0) {
|
nuclear@0
|
657 fg_critical("There is more than one track, cannot set format to 0.");
|
nuclear@0
|
658 return (-1);
|
nuclear@0
|
659 }
|
nuclear@0
|
660
|
nuclear@0
|
661 smf->format = format;
|
nuclear@0
|
662
|
nuclear@0
|
663 return (0);
|
nuclear@0
|
664 }
|
nuclear@0
|
665
|
nuclear@0
|
666 /**
|
nuclear@0
|
667 * Sets the PPQN ("Division") field of MThd header. This is mandatory, you
|
nuclear@0
|
668 * should call it right after smf_new. Note that changing PPQN will change time_seconds
|
nuclear@0
|
669 * of all the events.
|
nuclear@0
|
670 * \param smf SMF.
|
nuclear@0
|
671 * \param ppqn New PPQN.
|
nuclear@0
|
672 */
|
nuclear@0
|
673 int
|
nuclear@0
|
674 smf_set_ppqn(smf_t *smf, int ppqn)
|
nuclear@0
|
675 {
|
nuclear@0
|
676 assert(ppqn > 0);
|
nuclear@0
|
677
|
nuclear@0
|
678 smf->ppqn = ppqn;
|
nuclear@0
|
679
|
nuclear@0
|
680 return (0);
|
nuclear@0
|
681 }
|
nuclear@0
|
682
|
nuclear@0
|
683 /**
|
nuclear@0
|
684 * Returns next event from the track given and advances next event counter.
|
nuclear@0
|
685 * Do not depend on End Of Track event being the last event on the track - it
|
nuclear@0
|
686 * is possible that the track will not end with EOT if you haven't added it
|
nuclear@0
|
687 * yet. EOTs are added automatically during smf_save().
|
nuclear@0
|
688 *
|
nuclear@0
|
689 * \return Event or NULL, if there are no more events left in this track.
|
nuclear@0
|
690 */
|
nuclear@0
|
691 smf_event_t *
|
nuclear@0
|
692 smf_track_get_next_event(smf_track_t *track)
|
nuclear@0
|
693 {
|
nuclear@0
|
694 smf_event_t *event, *next_event;
|
nuclear@0
|
695
|
nuclear@0
|
696 /* End of track? */
|
nuclear@0
|
697 if (track->next_event_number == -1)
|
nuclear@0
|
698 return (NULL);
|
nuclear@0
|
699
|
nuclear@0
|
700 assert(track->next_event_number >= 1);
|
nuclear@0
|
701 assert(track->number_of_events > 0);
|
nuclear@0
|
702
|
nuclear@0
|
703 event = smf_track_get_event_by_number(track, track->next_event_number);
|
nuclear@0
|
704
|
nuclear@0
|
705 assert(event != NULL);
|
nuclear@0
|
706
|
nuclear@0
|
707 /* Is this the last event in the track? */
|
nuclear@0
|
708 if (track->next_event_number < track->number_of_events) {
|
nuclear@0
|
709 next_event = smf_track_get_event_by_number(track, track->next_event_number + 1);
|
nuclear@0
|
710 assert(next_event);
|
nuclear@0
|
711
|
nuclear@0
|
712 track->time_of_next_event = next_event->time_pulses;
|
nuclear@0
|
713 track->next_event_number++;
|
nuclear@0
|
714 } else {
|
nuclear@0
|
715 track->next_event_number = -1;
|
nuclear@0
|
716 }
|
nuclear@0
|
717
|
nuclear@0
|
718 return (event);
|
nuclear@0
|
719 }
|
nuclear@0
|
720
|
nuclear@0
|
721 /**
|
nuclear@0
|
722 * Returns next event from the track given. Does not change next event counter,
|
nuclear@0
|
723 * so repeatedly calling this routine will return the same event.
|
nuclear@0
|
724 * \return Event or NULL, if there are no more events left in this track.
|
nuclear@0
|
725 */
|
nuclear@0
|
726 static smf_event_t *
|
nuclear@0
|
727 smf_peek_next_event_from_track(smf_track_t *track)
|
nuclear@0
|
728 {
|
nuclear@0
|
729 smf_event_t *event;
|
nuclear@0
|
730
|
nuclear@0
|
731 /* End of track? */
|
nuclear@0
|
732 if (track->next_event_number == -1)
|
nuclear@0
|
733 return (NULL);
|
nuclear@0
|
734
|
nuclear@0
|
735 assert(track->next_event_number >= 1);
|
nuclear@0
|
736 assert(track->events_array->len != 0);
|
nuclear@0
|
737
|
nuclear@0
|
738 event = smf_track_get_event_by_number(track, track->next_event_number);
|
nuclear@0
|
739
|
nuclear@0
|
740 return (event);
|
nuclear@0
|
741 }
|
nuclear@0
|
742
|
nuclear@0
|
743 /**
|
nuclear@0
|
744 * \return Track with a given number or NULL, if there is no such track.
|
nuclear@0
|
745 * Tracks are numbered consecutively starting from one.
|
nuclear@0
|
746 */
|
nuclear@0
|
747 smf_track_t *
|
nuclear@0
|
748 smf_get_track_by_number(const smf_t *smf, int track_number)
|
nuclear@0
|
749 {
|
nuclear@0
|
750 smf_track_t *track;
|
nuclear@0
|
751
|
nuclear@0
|
752 assert(track_number >= 1);
|
nuclear@0
|
753
|
nuclear@0
|
754 if (track_number > smf->number_of_tracks)
|
nuclear@0
|
755 return (NULL);
|
nuclear@0
|
756
|
nuclear@0
|
757 track = (smf_track_t *)fg_ptr_array_index(smf->tracks_array, track_number - 1);
|
nuclear@0
|
758
|
nuclear@0
|
759 assert(track);
|
nuclear@0
|
760
|
nuclear@0
|
761 return (track);
|
nuclear@0
|
762 }
|
nuclear@0
|
763
|
nuclear@0
|
764 /**
|
nuclear@0
|
765 * \return Event with a given number or NULL, if there is no such event.
|
nuclear@0
|
766 * Events are numbered consecutively starting from one.
|
nuclear@0
|
767 */
|
nuclear@0
|
768 smf_event_t *
|
nuclear@0
|
769 smf_track_get_event_by_number(const smf_track_t *track, int event_number)
|
nuclear@0
|
770 {
|
nuclear@0
|
771 smf_event_t *event;
|
nuclear@0
|
772
|
nuclear@0
|
773 assert(event_number >= 1);
|
nuclear@0
|
774
|
nuclear@0
|
775 if (event_number > track->number_of_events)
|
nuclear@0
|
776 return (NULL);
|
nuclear@0
|
777
|
nuclear@0
|
778 event = fg_ptr_array_index(track->events_array, event_number - 1);
|
nuclear@0
|
779
|
nuclear@0
|
780 assert(event);
|
nuclear@0
|
781
|
nuclear@0
|
782 return (event);
|
nuclear@0
|
783 }
|
nuclear@0
|
784
|
nuclear@0
|
785 /**
|
nuclear@0
|
786 * \return Last event on the track or NULL, if track is empty.
|
nuclear@0
|
787 */
|
nuclear@0
|
788 smf_event_t *
|
nuclear@0
|
789 smf_track_get_last_event(const smf_track_t *track)
|
nuclear@0
|
790 {
|
nuclear@0
|
791 smf_event_t *event;
|
nuclear@0
|
792
|
nuclear@0
|
793 if (track->number_of_events == 0)
|
nuclear@0
|
794 return (NULL);
|
nuclear@0
|
795
|
nuclear@0
|
796 event = smf_track_get_event_by_number(track, track->number_of_events);
|
nuclear@0
|
797
|
nuclear@0
|
798 return (event);
|
nuclear@0
|
799 }
|
nuclear@0
|
800
|
nuclear@0
|
801 /**
|
nuclear@0
|
802 * Searches for track that contains next event, in time order. In other words,
|
nuclear@0
|
803 * returns the track that contains event that should be played next.
|
nuclear@0
|
804 * \return Track with next event or NULL, if there are no events left.
|
nuclear@0
|
805 */
|
nuclear@0
|
806 smf_track_t *
|
nuclear@0
|
807 smf_find_track_with_next_event(smf_t *smf)
|
nuclear@0
|
808 {
|
nuclear@0
|
809 int i, min_time = 0;
|
nuclear@0
|
810 smf_track_t *track = NULL, *min_time_track = NULL;
|
nuclear@0
|
811
|
nuclear@0
|
812 /* Find track with event that should be played next. */
|
nuclear@0
|
813 for (i = 1; i <= smf->number_of_tracks; i++) {
|
nuclear@0
|
814 track = smf_get_track_by_number(smf, i);
|
nuclear@0
|
815
|
nuclear@0
|
816 assert(track);
|
nuclear@0
|
817
|
nuclear@0
|
818 /* No more events in this track? */
|
nuclear@0
|
819 if (track->next_event_number == -1)
|
nuclear@0
|
820 continue;
|
nuclear@0
|
821
|
nuclear@0
|
822 if (track->time_of_next_event < min_time || min_time_track == NULL) {
|
nuclear@0
|
823 min_time = track->time_of_next_event;
|
nuclear@0
|
824 min_time_track = track;
|
nuclear@0
|
825 }
|
nuclear@0
|
826 }
|
nuclear@0
|
827
|
nuclear@0
|
828 return (min_time_track);
|
nuclear@0
|
829 }
|
nuclear@0
|
830
|
nuclear@0
|
831 /**
|
nuclear@0
|
832 * \return Next event, in time order, or NULL, if there are none left.
|
nuclear@0
|
833 */
|
nuclear@0
|
834 smf_event_t *
|
nuclear@0
|
835 smf_get_next_event(smf_t *smf)
|
nuclear@0
|
836 {
|
nuclear@0
|
837 smf_event_t *event;
|
nuclear@0
|
838 smf_track_t *track = smf_find_track_with_next_event(smf);
|
nuclear@0
|
839
|
nuclear@0
|
840 if (track == NULL) {
|
nuclear@0
|
841 #if 0
|
nuclear@0
|
842 g_debug("End of the song.");
|
nuclear@0
|
843 #endif
|
nuclear@0
|
844
|
nuclear@0
|
845 return (NULL);
|
nuclear@0
|
846 }
|
nuclear@0
|
847
|
nuclear@0
|
848 event = smf_track_get_next_event(track);
|
nuclear@0
|
849
|
nuclear@0
|
850 assert(event != NULL);
|
nuclear@0
|
851
|
nuclear@0
|
852 event->track->smf->last_seek_position = -1.0;
|
nuclear@0
|
853
|
nuclear@0
|
854 return (event);
|
nuclear@0
|
855 }
|
nuclear@0
|
856
|
nuclear@0
|
857 /**
|
nuclear@0
|
858 * Advance the "next event counter". This is functionally the same as calling
|
nuclear@0
|
859 * smf_get_next_event and ignoring the return value.
|
nuclear@0
|
860 */
|
nuclear@0
|
861 void
|
nuclear@0
|
862 smf_skip_next_event(smf_t *smf)
|
nuclear@0
|
863 {
|
nuclear@0
|
864 void *notused;
|
nuclear@0
|
865
|
nuclear@0
|
866 notused = smf_get_next_event(smf);
|
nuclear@0
|
867 }
|
nuclear@0
|
868
|
nuclear@0
|
869 /**
|
nuclear@0
|
870 * \return Next event, in time order, or NULL, if there are none left. Does
|
nuclear@0
|
871 * not advance position in song.
|
nuclear@0
|
872 */
|
nuclear@0
|
873 smf_event_t *
|
nuclear@0
|
874 smf_peek_next_event(smf_t *smf)
|
nuclear@0
|
875 {
|
nuclear@0
|
876 smf_event_t *event;
|
nuclear@0
|
877 smf_track_t *track = smf_find_track_with_next_event(smf);
|
nuclear@0
|
878
|
nuclear@0
|
879 if (track == NULL) {
|
nuclear@0
|
880 #if 0
|
nuclear@0
|
881 g_debug("End of the song.");
|
nuclear@0
|
882 #endif
|
nuclear@0
|
883
|
nuclear@0
|
884 return (NULL);
|
nuclear@0
|
885 }
|
nuclear@0
|
886
|
nuclear@0
|
887 event = smf_peek_next_event_from_track(track);
|
nuclear@0
|
888
|
nuclear@0
|
889 assert(event != NULL);
|
nuclear@0
|
890
|
nuclear@0
|
891 return (event);
|
nuclear@0
|
892 }
|
nuclear@0
|
893
|
nuclear@0
|
894 /**
|
nuclear@0
|
895 * Rewinds the SMF. What that means is, after calling this routine, smf_get_next_event
|
nuclear@0
|
896 * will return first event in the song.
|
nuclear@0
|
897 */
|
nuclear@0
|
898 void
|
nuclear@0
|
899 smf_rewind(smf_t *smf)
|
nuclear@0
|
900 {
|
nuclear@0
|
901 int i;
|
nuclear@0
|
902 smf_track_t *track = NULL;
|
nuclear@0
|
903 smf_event_t *event;
|
nuclear@0
|
904
|
nuclear@0
|
905 assert(smf);
|
nuclear@0
|
906
|
nuclear@0
|
907 smf->last_seek_position = 0.0;
|
nuclear@0
|
908
|
nuclear@0
|
909 for (i = 1; i <= smf->number_of_tracks; i++) {
|
nuclear@0
|
910 track = smf_get_track_by_number(smf, i);
|
nuclear@0
|
911
|
nuclear@0
|
912 assert(track != NULL);
|
nuclear@0
|
913
|
nuclear@0
|
914 if (track->number_of_events > 0) {
|
nuclear@0
|
915 track->next_event_number = 1;
|
nuclear@0
|
916 event = smf_peek_next_event_from_track(track);
|
nuclear@0
|
917 assert(event);
|
nuclear@0
|
918 track->time_of_next_event = event->time_pulses;
|
nuclear@0
|
919 } else {
|
nuclear@0
|
920 track->next_event_number = -1;
|
nuclear@0
|
921 track->time_of_next_event = 0;
|
nuclear@0
|
922 #if 0
|
nuclear@0
|
923 g_warning("Warning: empty track.");
|
nuclear@0
|
924 #endif
|
nuclear@0
|
925 }
|
nuclear@0
|
926 }
|
nuclear@0
|
927 }
|
nuclear@0
|
928
|
nuclear@0
|
929 /**
|
nuclear@0
|
930 * Seeks the SMF to the given event. After calling this routine, smf_get_next_event
|
nuclear@0
|
931 * will return the event that was the second argument of this call.
|
nuclear@0
|
932 */
|
nuclear@0
|
933 int
|
nuclear@0
|
934 smf_seek_to_event(smf_t *smf, const smf_event_t *target)
|
nuclear@0
|
935 {
|
nuclear@0
|
936 smf_event_t *event;
|
nuclear@0
|
937
|
nuclear@0
|
938 smf_rewind(smf);
|
nuclear@0
|
939
|
nuclear@0
|
940 #if 0
|
nuclear@0
|
941 g_debug("Seeking to event %d, track %d.", target->event_number, target->track->track_number);
|
nuclear@0
|
942 #endif
|
nuclear@0
|
943
|
nuclear@0
|
944 for (;;) {
|
nuclear@0
|
945 event = smf_peek_next_event(smf);
|
nuclear@0
|
946
|
nuclear@0
|
947 /* There can't be NULL here, unless "target" is not in this smf. */
|
nuclear@0
|
948 assert(event);
|
nuclear@0
|
949
|
nuclear@0
|
950 if (event != target)
|
nuclear@0
|
951 smf_skip_next_event(smf);
|
nuclear@0
|
952 else
|
nuclear@0
|
953 break;
|
nuclear@0
|
954 }
|
nuclear@0
|
955
|
nuclear@0
|
956 smf->last_seek_position = event->time_seconds;
|
nuclear@0
|
957
|
nuclear@0
|
958 return (0);
|
nuclear@0
|
959 }
|
nuclear@0
|
960
|
nuclear@0
|
961 /**
|
nuclear@0
|
962 * Seeks the SMF to the given position. For example, after seeking to 1.0 seconds,
|
nuclear@0
|
963 * smf_get_next_event will return first event that happens after the first second of song.
|
nuclear@0
|
964 */
|
nuclear@0
|
965 int
|
nuclear@0
|
966 smf_seek_to_seconds(smf_t *smf, double seconds)
|
nuclear@0
|
967 {
|
nuclear@0
|
968 smf_event_t *event;
|
nuclear@0
|
969
|
nuclear@0
|
970 assert(seconds >= 0.0);
|
nuclear@0
|
971
|
nuclear@0
|
972 if (seconds == smf->last_seek_position) {
|
nuclear@0
|
973 #if 0
|
nuclear@0
|
974 g_debug("Avoiding seek to %f seconds.", seconds);
|
nuclear@0
|
975 #endif
|
nuclear@0
|
976 return (0);
|
nuclear@0
|
977 }
|
nuclear@0
|
978
|
nuclear@0
|
979 smf_rewind(smf);
|
nuclear@0
|
980
|
nuclear@0
|
981 #if 0
|
nuclear@0
|
982 g_debug("Seeking to %f seconds.", seconds);
|
nuclear@0
|
983 #endif
|
nuclear@0
|
984
|
nuclear@0
|
985 for (;;) {
|
nuclear@0
|
986 event = smf_peek_next_event(smf);
|
nuclear@0
|
987
|
nuclear@0
|
988 if (event == NULL) {
|
nuclear@0
|
989 fg_critical("Trying to seek past the end of song.");
|
nuclear@0
|
990 return (-1);
|
nuclear@0
|
991 }
|
nuclear@0
|
992
|
nuclear@0
|
993 if (event->time_seconds < seconds)
|
nuclear@0
|
994 smf_skip_next_event(smf);
|
nuclear@0
|
995 else
|
nuclear@0
|
996 break;
|
nuclear@0
|
997 }
|
nuclear@0
|
998
|
nuclear@0
|
999 smf->last_seek_position = seconds;
|
nuclear@0
|
1000
|
nuclear@0
|
1001 return (0);
|
nuclear@0
|
1002 }
|
nuclear@0
|
1003
|
nuclear@0
|
1004 /**
|
nuclear@0
|
1005 * Seeks the SMF to the given position. For example, after seeking to 10 pulses,
|
nuclear@0
|
1006 * smf_get_next_event will return first event that happens after the first ten pulses.
|
nuclear@0
|
1007 */
|
nuclear@0
|
1008 int
|
nuclear@0
|
1009 smf_seek_to_pulses(smf_t *smf, int pulses)
|
nuclear@0
|
1010 {
|
nuclear@0
|
1011 smf_event_t *event;
|
nuclear@0
|
1012
|
nuclear@0
|
1013 assert(pulses >= 0);
|
nuclear@0
|
1014
|
nuclear@0
|
1015 smf_rewind(smf);
|
nuclear@0
|
1016
|
nuclear@0
|
1017 #if 0
|
nuclear@0
|
1018 g_debug("Seeking to %d pulses.", pulses);
|
nuclear@0
|
1019 #endif
|
nuclear@0
|
1020
|
nuclear@0
|
1021 for (;;) {
|
nuclear@0
|
1022 event = smf_peek_next_event(smf);
|
nuclear@0
|
1023
|
nuclear@0
|
1024 if (event == NULL) {
|
nuclear@0
|
1025 fg_critical("Trying to seek past the end of song.");
|
nuclear@0
|
1026 return (-1);
|
nuclear@0
|
1027 }
|
nuclear@0
|
1028
|
nuclear@0
|
1029 if (event->time_pulses < pulses)
|
nuclear@0
|
1030 smf_skip_next_event(smf);
|
nuclear@0
|
1031 else
|
nuclear@0
|
1032 break;
|
nuclear@0
|
1033 }
|
nuclear@0
|
1034
|
nuclear@0
|
1035 smf->last_seek_position = event->time_seconds;
|
nuclear@0
|
1036
|
nuclear@0
|
1037 return (0);
|
nuclear@0
|
1038 }
|
nuclear@0
|
1039
|
nuclear@0
|
1040 /**
|
nuclear@0
|
1041 * \return Length of SMF, in pulses.
|
nuclear@0
|
1042 */
|
nuclear@0
|
1043 int
|
nuclear@0
|
1044 smf_get_length_pulses(const smf_t *smf)
|
nuclear@0
|
1045 {
|
nuclear@0
|
1046 int pulses = 0, i;
|
nuclear@0
|
1047
|
nuclear@0
|
1048 for (i = 1; i <= smf->number_of_tracks; i++) {
|
nuclear@0
|
1049 smf_track_t *track;
|
nuclear@0
|
1050 smf_event_t *event;
|
nuclear@0
|
1051
|
nuclear@0
|
1052 track = smf_get_track_by_number(smf, i);
|
nuclear@0
|
1053 assert(track);
|
nuclear@0
|
1054
|
nuclear@0
|
1055 event = smf_track_get_last_event(track);
|
nuclear@0
|
1056 /* Empty track? */
|
nuclear@0
|
1057 if (event == NULL)
|
nuclear@0
|
1058 continue;
|
nuclear@0
|
1059
|
nuclear@0
|
1060 if (event->time_pulses > pulses)
|
nuclear@0
|
1061 pulses = event->time_pulses;
|
nuclear@0
|
1062 }
|
nuclear@0
|
1063
|
nuclear@0
|
1064 return (pulses);
|
nuclear@0
|
1065 }
|
nuclear@0
|
1066
|
nuclear@0
|
1067 /**
|
nuclear@0
|
1068 * \return Length of SMF, in seconds.
|
nuclear@0
|
1069 */
|
nuclear@0
|
1070 double
|
nuclear@0
|
1071 smf_get_length_seconds(const smf_t *smf)
|
nuclear@0
|
1072 {
|
nuclear@0
|
1073 int i;
|
nuclear@0
|
1074 double seconds = 0.0;
|
nuclear@0
|
1075
|
nuclear@0
|
1076 for (i = 1; i <= smf->number_of_tracks; i++) {
|
nuclear@0
|
1077 smf_track_t *track;
|
nuclear@0
|
1078 smf_event_t *event;
|
nuclear@0
|
1079
|
nuclear@0
|
1080 track = smf_get_track_by_number(smf, i);
|
nuclear@0
|
1081 assert(track);
|
nuclear@0
|
1082
|
nuclear@0
|
1083 event = smf_track_get_last_event(track);
|
nuclear@0
|
1084 /* Empty track? */
|
nuclear@0
|
1085 if (event == NULL)
|
nuclear@0
|
1086 continue;
|
nuclear@0
|
1087
|
nuclear@0
|
1088 if (event->time_seconds > seconds)
|
nuclear@0
|
1089 seconds = event->time_seconds;
|
nuclear@0
|
1090 }
|
nuclear@0
|
1091
|
nuclear@0
|
1092 return (seconds);
|
nuclear@0
|
1093 }
|
nuclear@0
|
1094
|
nuclear@0
|
1095 /**
|
nuclear@0
|
1096 * \return Nonzero, if there are no events in the SMF after this one.
|
nuclear@0
|
1097 * Note that may be more than one "last event", if they occur at the same time.
|
nuclear@0
|
1098 */
|
nuclear@0
|
1099 int
|
nuclear@0
|
1100 smf_event_is_last(const smf_event_t *event)
|
nuclear@0
|
1101 {
|
nuclear@0
|
1102 if (smf_get_length_pulses(event->track->smf) <= event->time_pulses)
|
nuclear@0
|
1103 return (1);
|
nuclear@0
|
1104
|
nuclear@0
|
1105 return (0);
|
nuclear@0
|
1106 }
|
nuclear@0
|
1107
|
nuclear@0
|
1108 /**
|
nuclear@0
|
1109 * \return Version of libsmf.
|
nuclear@0
|
1110 */
|
nuclear@0
|
1111 const char *
|
nuclear@0
|
1112 smf_get_version(void)
|
nuclear@0
|
1113 {
|
nuclear@0
|
1114 return (SMF_VERSION);
|
nuclear@0
|
1115 }
|
nuclear@0
|
1116
|