95ed14b1d7ea5ae4453e24f10327a10be647b451
[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 static int
160 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 = 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 = 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, const char *file_name)
395 {
396         FILE *stream;
397
398         stream = fopen(file_name, "w+");
399         if (stream == NULL) {
400                 g_critical("Cannot open input file: %s", strerror(errno));
401
402                 return (-1);
403         }
404
405         if (fwrite(smf->file_buffer, 1, smf->file_buffer_length, stream) != smf->file_buffer_length) {
406                 g_critical("fwrite(3) failed: %s", strerror(errno));
407
408                 return (-2);
409         }
410
411         if (fclose(stream)) {
412                 g_critical("fclose(3) failed: %s", strerror(errno));
413
414                 return (-3);
415         }
416
417         return (0);
418 }
419
420 static void
421 free_buffer(smf_t *smf)
422 {
423         int i;
424         smf_track_t *track;
425
426         /* Clear the pointers. */
427         memset(smf->file_buffer, 0, smf->file_buffer_length);
428         free(smf->file_buffer);
429         smf->file_buffer = NULL;
430         smf->file_buffer_length = 0;
431
432         for (i = 1; i <= smf->number_of_tracks; i++) {
433                 track = smf_get_track_by_number(smf, i);
434                 assert(track);
435                 track->file_buffer = NULL;
436                 track->file_buffer_length = 0;
437         }
438 }
439
440 #ifndef NDEBUG
441
442 /**
443  * \return Nonzero, if all pointers supposed to be NULL are NULL.  Triggers assertion if not.
444  */
445 static int
446 pointers_are_clear(smf_t *smf)
447 {
448         int i;
449
450         smf_track_t *track;
451         assert(smf->file_buffer == NULL);
452         assert(smf->file_buffer_length == 0);
453
454         for (i = 1; i <= smf->number_of_tracks; i++) {
455                 track = smf_get_track_by_number(smf, i);
456
457                 assert(track != NULL);
458                 assert(track->file_buffer == NULL);
459                 assert(track->file_buffer_length == 0);
460         }
461
462         return (1);
463 }
464
465 #endif /* !NDEBUG */
466
467 /**
468  * \return Nonzero, if event is End Of Track metaevent.
469  */
470 int
471 smf_event_is_eot(const smf_event_t *event)
472 {
473         if (event->midi_buffer_length != 3)
474                 return (0);
475
476         if (event->midi_buffer[0] != 0xFF || event->midi_buffer[1] != 0x2F || event->midi_buffer[2] != 0x00)
477                 return (0);
478
479         return (1);
480 }
481
482 /**
483  * Check if SMF is valid and add missing EOT events.
484  *
485  * \return 0, if SMF is valid.
486  */
487 static int
488 smf_validate(smf_t *smf)
489 {
490         int trackno, eventno, eot_found;
491         smf_track_t *track;
492         smf_event_t *event;
493
494         if (smf->format < 0 || smf->format > 2) {
495                 g_critical("SMF error: smf->format is less than zero of greater than two.");
496                 return (-1);
497         }
498
499         if (smf->number_of_tracks < 1) {
500                 g_critical("SMF error: number of tracks is less than one.");
501                 return (-2);
502         }
503
504         if (smf->format == 0 && smf->number_of_tracks > 1) {
505                 g_critical("SMF error: format is 0, but number of tracks is more than one.");
506                 return (-3);
507         }
508
509         if (smf->ppqn <= 0) {
510                 g_critical("SMF error: PPQN has to be > 0.");
511                 return (-4);
512         }
513
514         for (trackno = 1; trackno <= smf->number_of_tracks; trackno++) {
515                 track = smf_get_track_by_number(smf, trackno);
516                 assert(track);
517
518                 eot_found = 0;
519
520                 for (eventno = 1; eventno <= track->number_of_events; eventno++) {
521                         event = smf_track_get_event_by_number(track, eventno);
522                         assert(event);
523
524                         if (!smf_event_is_valid(event)) {
525                                 g_critical("Event #%d on track #%d is invalid.", eventno, trackno);
526                                 return (-5);
527                         }
528
529                         if (smf_event_is_eot(event)) {
530                                 if (eot_found) {
531                                         g_critical("Duplicate End Of Track event on track #%d.", trackno);
532                                         return (-6);
533                                 }
534
535                                 eot_found = 1;
536                         }
537                 }
538
539                 if (!eot_found) {
540                         if (smf_track_add_eot_delta_pulses(track, 0)) {
541                                 g_critical("smf_track_add_eot_delta_pulses failed.");
542                                 return (-6);
543                         }
544                 }
545                                 
546         }
547
548         return (0);
549 }
550
551 #ifndef NDEBUG
552
553 static void
554 assert_smf_event_is_identical(const smf_event_t *a, const smf_event_t *b)
555 {
556         assert(a->event_number == b->event_number);
557         assert(a->delta_time_pulses == b->delta_time_pulses);
558         assert(abs(a->time_pulses - b->time_pulses) <= 2);
559         assert(fabs(a->time_seconds - b->time_seconds) <= 0.01);
560         assert(a->track_number == b->track_number);
561         assert(a->midi_buffer_length == b->midi_buffer_length);
562         assert(memcmp(a->midi_buffer, b->midi_buffer, a->midi_buffer_length) == 0);
563 }
564
565 static void
566 assert_smf_track_is_identical(const smf_track_t *a, const smf_track_t *b)
567 {
568         int i;
569
570         assert(a->track_number == b->track_number);
571         assert(a->number_of_events == b->number_of_events);
572
573         for (i = 1; i <= a->number_of_events; i++)
574                 assert_smf_event_is_identical(smf_track_get_event_by_number(a, i), smf_track_get_event_by_number(b, i));
575 }
576
577 static void
578 assert_smf_is_identical(const smf_t *a, const smf_t *b)
579 {
580         int i;
581
582         assert(a->format == b->format);
583         assert(a->ppqn == b->ppqn);
584         assert(a->frames_per_second == b->frames_per_second);
585         assert(a->resolution == b->resolution);
586         assert(a->number_of_tracks == b->number_of_tracks);
587
588         for (i = 1; i <= a->number_of_tracks; i++)
589                 assert_smf_track_is_identical(smf_get_track_by_number(a, i), smf_get_track_by_number(b, i));
590
591         /* We do not need to compare tempos explicitly, as tempo is always computed from track contents. */
592 }
593
594 static void
595 assert_smf_saved_correctly(const smf_t *smf, const char *file_name)
596 {
597         smf_t *saved;
598
599         saved = smf_load(file_name);
600         assert(saved != NULL);
601
602         assert_smf_is_identical(smf, saved);
603
604         smf_delete(saved);
605 }
606
607 #endif /* !NDEBUG */
608
609 /**
610   * Writes the contents of SMF to the file given.
611   * \param smf SMF.
612   * \param file_name Path to the file.
613   * \return 0, if saving was successfull.
614   */
615 int
616 smf_save(smf_t *smf, const char *file_name)
617 {
618         int i, error;
619         smf_track_t *track;
620
621         smf_rewind(smf);
622
623         assert(pointers_are_clear(smf));
624
625         if (smf_validate(smf))
626                 return (-1);
627
628         if (write_mthd_header(smf))
629                 return (-2);
630
631         for (i = 1; i <= smf->number_of_tracks; i++) {
632                 track = smf_get_track_by_number(smf, i);
633
634                 assert(track != NULL);
635
636                 error = write_track(track);
637                 if (error) {
638                         free_buffer(smf);
639                         return (error);
640                 }
641         }
642
643         error = write_file(smf, file_name);
644
645         free_buffer(smf);
646
647         if (error)
648                 return (error);
649
650 #ifndef NDEBUG
651         assert_smf_saved_correctly(smf, file_name);
652 #endif
653
654         return (0);
655 }
656