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