b99af75461b094207d11d3b9f967fe0aa6d1d7db
[ardour.git] / libs / evoral / src / libsmf / smf_save.c
1 /*-
2  * Copyright (c) 2007, 2008 Edward Tomasz NapieraƂa <trasz@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * ALTHOUGH THIS SOFTWARE IS MADE OF WIN AND SCIENCE, IT IS PROVIDED BY THE
15  * AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
18  * THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
20  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
21  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27
28 /**
29  * \file
30  *
31  * Standard MIDI File writer.
32  *
33  */
34
35 /* Reference: http://www.borg.com/~jglatt/tech/midifile.htm */
36
37 #include <stdlib.h>
38 #include <string.h>
39 #include <assert.h>
40 #include <math.h>
41 #include <errno.h>
42 #include <arpa/inet.h>
43 #include "smf.h"
44 #include "smf_private.h"
45
46 #define MAX_VLQ_LENGTH 128
47
48 /**
49  * Extends (reallocates) smf->file_buffer and returns pointer to the newly added space,
50  * that is, pointer to the first byte after the previous buffer end.  Returns NULL in case
51  * of error.
52  */
53 static void *
54 smf_extend(smf_t *smf, const int length)
55 {
56         int i, previous_file_buffer_length = smf->file_buffer_length;
57         char *previous_file_buffer = smf->file_buffer;
58
59         /* XXX: Not terribly efficient. */
60         smf->file_buffer_length += length;
61         smf->file_buffer = realloc(smf->file_buffer, smf->file_buffer_length);
62         if (smf->file_buffer == NULL) {
63                 g_critical("realloc(3) failed: %s", strerror(errno));
64                 smf->file_buffer_length = 0;
65                 return (NULL);
66         }
67
68         /* Fix up pointers.  XXX: omgwtf. */
69         for (i = 1; i <= smf->number_of_tracks; i++) {
70                 smf_track_t *track;
71                 track = smf_get_track_by_number(smf, i);
72                 if (track->file_buffer != NULL)
73                         track->file_buffer = (char *)track->file_buffer + ((char *)smf->file_buffer - previous_file_buffer);
74         }
75
76         return ((char *)smf->file_buffer + previous_file_buffer_length);
77 }
78
79 /**
80  * Appends "buffer_length" bytes pointed to by "buffer" to the smf, reallocating storage as needed.  Returns 0
81  * if everything went ok, different value if there was any problem.
82  */
83 static int
84 smf_append(smf_t *smf, const void *buffer, const int buffer_length)
85 {
86         void *dest;
87
88         dest = smf_extend(smf, buffer_length);
89         if (dest == NULL) {
90                 g_critical("Cannot extend track buffer.");
91                 return (-1);
92         }
93
94         memcpy(dest, buffer, buffer_length);
95
96         return (0);
97 }
98
99 /**
100  * Appends MThd header to the track.  Returns 0 if everything went ok, different value if not.
101  */
102 static int
103 write_mthd_header(smf_t *smf)
104 {
105         struct mthd_chunk_struct mthd_chunk;
106
107         memcpy(mthd_chunk.mthd_header.id, "MThd", 4);
108         mthd_chunk.mthd_header.length = htonl(6);
109         mthd_chunk.format = htons(smf->format);
110         mthd_chunk.number_of_tracks = htons(smf->number_of_tracks);
111         mthd_chunk.division = htons(smf->ppqn);
112
113         return (smf_append(smf, &mthd_chunk, sizeof(mthd_chunk)));
114 }
115
116 /**
117  * Extends (reallocates) track->file_buffer and returns pointer to the newly added space,
118  * that is, pointer to the first byte after the previous buffer end.  Returns NULL in case
119  * of error.
120  */
121 static void *
122 track_extend(smf_track_t *track, const int length)
123 {
124         void *buf;
125
126         assert(track->smf);
127
128         buf = smf_extend(track->smf, length);
129         if (buf == NULL)
130                 return (NULL);
131
132         track->file_buffer_length += length;
133         if (track->file_buffer == NULL)
134                 track->file_buffer = buf;
135
136         return (buf);
137 }
138
139 /**
140  * Appends "buffer_length" bytes pointed to by "buffer" to the track, reallocating storage as needed.  Returns 0
141  * if everything went ok, different value if there was any problem.
142  */
143 static int
144 track_append(smf_track_t *track, const void *buffer, const int buffer_length)
145 {
146         void *dest;
147
148         dest = track_extend(track, buffer_length);
149         if (dest == NULL) {
150                 g_critical("Cannot extend track buffer.");
151                 return (-1);
152         }
153
154         memcpy(dest, buffer, buffer_length);
155
156         return (0);
157 }
158
159 int
160 smf_format_vlq(unsigned char *buf, int length, unsigned long value)
161 {
162         int i;
163         unsigned long buffer;
164
165         /* Taken from http://www.borg.com/~jglatt/tech/midifile/vari.htm */
166         buffer = value & 0x7F;
167
168         while ((value >>= 7)) {
169                 buffer <<= 8;
170                 buffer |= ((value & 0x7F) | 0x80);
171         }
172
173         for (i = 0;; i++) {
174                 buf[i] = buffer;
175
176                 if (buffer & 0x80)
177                         buffer >>= 8;
178                 else
179                         break;
180         }
181
182         assert(i <= length);
183
184         /* + 1, because "i" is an offset, not a count. */
185         return (i + 1);
186 }
187
188 smf_event_t *
189 smf_event_new_textual(int type, const char *text)
190 {
191         int vlq_length, text_length, copied_length;
192         smf_event_t *event;
193
194         assert(type >= 1 && type <= 9);
195
196         text_length = strlen(text);
197
198         event = smf_event_new();
199         if (event == NULL)
200                 return (NULL);
201
202         /* "2 +" is for leading 0xFF 0xtype. */
203         event->midi_buffer_length = 2 + text_length + MAX_VLQ_LENGTH;
204         event->midi_buffer = malloc(event->midi_buffer_length);
205         if (event->midi_buffer == NULL) {
206                 g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno));
207                 smf_event_delete(event);
208
209                 return (NULL); 
210         }
211
212         event->midi_buffer[0] = 0xFF;
213         event->midi_buffer[1] = type;
214
215         vlq_length = smf_format_vlq(event->midi_buffer + 2, MAX_VLQ_LENGTH - 2, text_length);
216         copied_length = snprintf((char *)event->midi_buffer + vlq_length + 2, event->midi_buffer_length - vlq_length - 2, "%s", text);
217
218         assert(copied_length == text_length);
219
220         event->midi_buffer_length = 2 + vlq_length + text_length;
221
222         return event;
223 }
224
225 /**
226   * Appends value, expressed as Variable Length Quantity, to event->track.
227   */
228 static int
229 write_vlq(smf_event_t *event, unsigned long value)
230 {
231         unsigned char buf[MAX_VLQ_LENGTH];
232         int vlq_length;
233
234         vlq_length = smf_format_vlq(buf, MAX_VLQ_LENGTH, value);
235
236         return (track_append(event->track, buf, vlq_length));
237 }
238
239 /**
240  * Appends event time as Variable Length Quantity.  Returns 0 if everything went ok,
241  * different value in case of error.
242  */
243 static int
244 write_event_time(smf_event_t *event)
245 {
246         assert(event->delta_time_pulses >= 0);
247
248         return (write_vlq(event, event->delta_time_pulses));
249 }
250
251 static int
252 write_sysex_contents(smf_event_t *event)
253 {
254         int ret;
255         unsigned char sysex_status = 0xF0;
256
257         assert(smf_event_is_sysex(event));
258
259         ret = track_append(event->track, &sysex_status, 1);
260         if (ret)
261                 return (ret);
262
263         /* -1, because length does not include status byte. */
264         ret = write_vlq(event, event->midi_buffer_length - 1);
265         if (ret)
266                 return (ret);
267
268         ret = track_append(event->track, event->midi_buffer + 1, event->midi_buffer_length - 1);
269         if (ret)
270                 return (ret);
271
272         return (0);
273 }
274
275 /**
276   * Appends contents of event->midi_buffer wrapped into 0xF7 MIDI event.
277   */
278 static int
279 write_escaped_event_contents(smf_event_t *event)
280 {
281         int ret;
282         unsigned char escape_status = 0xF7;
283
284         if (smf_event_is_sysex(event))
285                 return (write_sysex_contents(event));
286
287         ret = track_append(event->track, &escape_status, 1);
288         if (ret)
289                 return (ret);
290
291         ret = write_vlq(event, event->midi_buffer_length);
292         if (ret)
293                 return (ret);
294
295         ret = track_append(event->track, event->midi_buffer, event->midi_buffer_length);
296         if (ret)
297                 return (ret);
298
299         return (0);
300 }
301
302 /**
303  * Appends contents of event->midi_buffer.  Returns 0 if everything went 0,
304  * different value in case of error.
305  */
306 static int
307 write_event_contents(smf_event_t *event)
308 {
309         if (smf_event_is_system_realtime(event) || smf_event_is_system_common(event))
310                 return (write_escaped_event_contents(event));
311
312         return (track_append(event->track, event->midi_buffer, event->midi_buffer_length));
313 }
314
315 /**
316  * Writes out an event.
317  */
318 static int
319 write_event(smf_event_t *event)
320 {
321         int ret;
322
323         ret = write_event_time(event);
324         if (ret)
325                 return (ret);
326
327         ret = write_event_contents(event);
328         if (ret)
329                 return (ret);
330
331         return (0);
332 }
333
334 /**
335  * Writes out MTrk header, except of MTrk chunk length, which is written by write_mtrk_length().
336  */
337 static int
338 write_mtrk_header(smf_track_t *track)
339 {
340         struct chunk_header_struct mtrk_header;
341
342         memcpy(mtrk_header.id, "MTrk", 4);
343
344         return (track_append(track, &mtrk_header, sizeof(mtrk_header)));
345 }
346
347 /**
348  * Updates MTrk chunk length of a given track.
349  */
350 static int
351 write_mtrk_length(smf_track_t *track)
352 {
353         struct chunk_header_struct *mtrk_header;
354
355         assert(track->file_buffer != NULL);
356         assert(track->file_buffer_length >= 6);
357
358         mtrk_header = (struct chunk_header_struct *)track->file_buffer;
359         mtrk_header->length = htonl(track->file_buffer_length - sizeof(struct chunk_header_struct));
360
361         return (0);
362 }
363
364 /**
365  * Writes out the track.
366  */
367 static int
368 write_track(smf_track_t *track)
369 {
370         int ret;
371         smf_event_t *event;
372
373         ret = write_mtrk_header(track);
374         if (ret)
375                 return (ret);
376
377         while ((event = smf_track_get_next_event(track)) != NULL) {
378                 ret = write_event(event);
379                 if (ret)
380                         return (ret);
381         }
382
383         ret = write_mtrk_length(track);
384         if (ret)
385                 return (ret);
386
387         return (0);
388 }
389
390 /**
391  * Takes smf->file_buffer and saves it to the file.
392  */
393 static int
394 write_file(smf_t *smf, FILE* stream)
395 {
396         if (fwrite(smf->file_buffer, 1, smf->file_buffer_length, stream) != smf->file_buffer_length) {
397                 g_critical("fwrite(3) failed: %s", strerror(errno));
398
399                 return (-2);
400         }
401
402         return (0);
403 }
404
405 static void
406 free_buffer(smf_t *smf)
407 {
408         int i;
409         smf_track_t *track;
410
411         /* Clear the pointers. */
412         memset(smf->file_buffer, 0, smf->file_buffer_length);
413         free(smf->file_buffer);
414         smf->file_buffer = NULL;
415         smf->file_buffer_length = 0;
416
417         for (i = 1; i <= smf->number_of_tracks; i++) {
418                 track = smf_get_track_by_number(smf, i);
419                 assert(track);
420                 track->file_buffer = NULL;
421                 track->file_buffer_length = 0;
422         }
423 }
424
425 #ifndef NDEBUG
426
427 /**
428  * \return Nonzero, if all pointers supposed to be NULL are NULL.  Triggers assertion if not.
429  */
430 static int
431 pointers_are_clear(smf_t *smf)
432 {
433         int i;
434
435         smf_track_t *track;
436         assert(smf->file_buffer == NULL);
437         assert(smf->file_buffer_length == 0);
438
439         for (i = 1; i <= smf->number_of_tracks; i++) {
440                 track = smf_get_track_by_number(smf, i);
441
442                 assert(track != NULL);
443                 assert(track->file_buffer == NULL);
444                 assert(track->file_buffer_length == 0);
445         }
446
447         return (1);
448 }
449
450 #endif /* !NDEBUG */
451
452 /**
453  * \return Nonzero, if event is End Of Track metaevent.
454  */
455 int
456 smf_event_is_eot(const smf_event_t *event)
457 {
458         if (event->midi_buffer_length != 3)
459                 return (0);
460
461         if (event->midi_buffer[0] != 0xFF || event->midi_buffer[1] != 0x2F || event->midi_buffer[2] != 0x00)
462                 return (0);
463
464         return (1);
465 }
466
467 /**
468  * Check if SMF is valid and add missing EOT events.
469  *
470  * \return 0, if SMF is valid.
471  */
472 static int
473 smf_validate(smf_t *smf)
474 {
475         int trackno, eot_found;
476         size_t eventno;
477         smf_track_t *track;
478         smf_event_t *event;
479
480         if (smf->format < 0 || smf->format > 2) {
481                 g_critical("SMF error: smf->format is less than zero of greater than two.");
482                 return (-1);
483         }
484
485         if (smf->number_of_tracks < 1) {
486                 g_critical("SMF error: number of tracks is less than one.");
487                 return (-2);
488         }
489
490         if (smf->format == 0 && smf->number_of_tracks > 1) {
491                 g_critical("SMF error: format is 0, but number of tracks is more than one.");
492                 return (-3);
493         }
494
495         if (smf->ppqn <= 0) {
496                 g_critical("SMF error: PPQN has to be > 0.");
497                 return (-4);
498         }
499
500         for (trackno = 1; trackno <= smf->number_of_tracks; trackno++) {
501                 track = smf_get_track_by_number(smf, trackno);
502                 assert(track);
503
504                 eot_found = 0;
505
506                 for (eventno = 1; eventno <= track->number_of_events; eventno++) {
507                         event = smf_track_get_event_by_number(track, eventno);
508                         assert(event);
509
510                         if (!smf_event_is_valid(event)) {
511                                 g_critical("Event #%zu on track #%d is invalid.", eventno, trackno);
512                                 return (-5);
513                         }
514
515                         if (smf_event_is_eot(event)) {
516                                 if (eot_found) {
517                                         g_critical("Duplicate End Of Track event on track #%d.", trackno);
518                                         return (-6);
519                                 }
520
521                                 eot_found = 1;
522                         }
523                 }
524
525                 if (!eot_found) {
526                         if (smf_track_add_eot_delta_pulses(track, 0)) {
527                                 g_critical("smf_track_add_eot_delta_pulses failed.");
528                                 return (-6);
529                         }
530                 }
531                                 
532         }
533
534         return (0);
535 }
536
537 #ifndef NDEBUG
538
539 static void
540 assert_smf_event_is_identical(const smf_event_t *a, const smf_event_t *b)
541 {
542         assert(a->event_number == b->event_number);
543         assert(a->delta_time_pulses == b->delta_time_pulses);
544         assert(abs(a->time_pulses - b->time_pulses) <= 2);
545         assert(fabs(a->time_seconds - b->time_seconds) <= 0.01);
546         assert(a->track_number == b->track_number);
547         assert(a->midi_buffer_length == b->midi_buffer_length);
548         assert(memcmp(a->midi_buffer, b->midi_buffer, a->midi_buffer_length) == 0);
549 }
550
551 static void
552 assert_smf_track_is_identical(const smf_track_t *a, const smf_track_t *b)
553 {
554         size_t i;
555
556         assert(a->track_number == b->track_number);
557         assert(a->number_of_events == b->number_of_events);
558
559         for (i = 1; i <= a->number_of_events; i++)
560                 assert_smf_event_is_identical(smf_track_get_event_by_number(a, i), smf_track_get_event_by_number(b, i));
561 }
562
563 static void
564 assert_smf_is_identical(const smf_t *a, const smf_t *b)
565 {
566         int i;
567
568         assert(a->format == b->format);
569         assert(a->ppqn == b->ppqn);
570         assert(a->frames_per_second == b->frames_per_second);
571         assert(a->resolution == b->resolution);
572         assert(a->number_of_tracks == b->number_of_tracks);
573
574         for (i = 1; i <= a->number_of_tracks; i++)
575                 assert_smf_track_is_identical(smf_get_track_by_number(a, i), smf_get_track_by_number(b, i));
576
577         /* We do not need to compare tempos explicitly, as tempo is always computed from track contents. */
578 }
579
580 static void
581 assert_smf_saved_correctly(const smf_t *smf, FILE* file)
582 {
583         smf_t *saved;
584
585         saved = smf_load (file);
586         assert(saved != NULL);
587
588         assert_smf_is_identical(smf, saved);
589
590         smf_delete(saved);
591 }
592
593 #endif /* !NDEBUG */
594
595 /**
596   * Writes the contents of SMF to the file given.
597   * \param smf SMF.
598   * \param file File descriptor.
599   * \return 0, if saving was successfull.
600   */
601 int
602 smf_save(smf_t *smf, FILE* file)
603 {
604         int i, error;
605         smf_track_t *track;
606
607         smf_rewind(smf);
608
609         assert(pointers_are_clear(smf));
610
611         if (smf_validate(smf))
612                 return (-1);
613
614         if (write_mthd_header(smf))
615                 return (-2);
616
617         for (i = 1; i <= smf->number_of_tracks; i++) {
618                 track = smf_get_track_by_number(smf, i);
619
620                 assert(track != NULL);
621
622                 error = write_track(track);
623                 if (error) {
624                         free_buffer(smf);
625                         return (error);
626                 }
627         }
628
629         error = write_file(smf, file);
630
631         free_buffer(smf);
632
633         if (error)
634                 return (error);
635
636 #ifndef NDEBUG
637         assert_smf_saved_correctly(smf, file);
638 #endif
639
640         return (0);
641 }
642