smflite

diff src/smf.c @ 0:4264abea8b06

smf-lite initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 26 Jan 2012 11:25:11 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/smf.c	Thu Jan 26 11:25:11 2012 +0200
     1.3 @@ -0,0 +1,1116 @@
     1.4 +/*-
     1.5 + * Copyright (c) 2007, 2008 Edward Tomasz NapieraƂa <trasz@FreeBSD.org>
     1.6 + * All rights reserved.
     1.7 + *
     1.8 + * Redistribution and use in source and binary forms, with or without
     1.9 + * modification, are permitted provided that the following conditions
    1.10 + * are met:
    1.11 + * 1. Redistributions of source code must retain the above copyright
    1.12 + *    notice, this list of conditions and the following disclaimer.
    1.13 + * 2. Redistributions in binary form must reproduce the above copyright
    1.14 + *    notice, this list of conditions and the following disclaimer in the
    1.15 + *    documentation and/or other materials provided with the distribution.
    1.16 + *
    1.17 + * ALTHOUGH THIS SOFTWARE IS MADE OF WIN AND SCIENCE, IT IS PROVIDED BY THE
    1.18 + * AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
    1.19 + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
    1.20 + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
    1.21 + * THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.22 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
    1.23 + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
    1.24 + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    1.25 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    1.26 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    1.27 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.28 + *
    1.29 + */
    1.30 +
    1.31 +/**
    1.32 + * \file
    1.33 + *
    1.34 + * Various functions.
    1.35 + *
    1.36 + */
    1.37 +
    1.38 +/* Reference: http://www.borg.com/~jglatt/tech/midifile.htm */
    1.39 +
    1.40 +#include <stdlib.h>
    1.41 +#include <string.h>
    1.42 +#include <assert.h>
    1.43 +#include <math.h>
    1.44 +#include <errno.h>
    1.45 +#ifdef __MINGW32__
    1.46 +#include <windows.h>
    1.47 +#else /* ! __MINGW32__ */
    1.48 +#include <arpa/inet.h>
    1.49 +#endif /* ! __MINGW32__ */
    1.50 +#include "smf.h"
    1.51 +#include "smf_private.h"
    1.52 +
    1.53 +/**
    1.54 + * Allocates new smf_t structure.
    1.55 + * \return pointer to smf_t or NULL.
    1.56 + */
    1.57 +smf_t *
    1.58 +smf_new(void)
    1.59 +{
    1.60 +	int cantfail;
    1.61 +
    1.62 +	smf_t *smf = malloc(sizeof(smf_t));
    1.63 +	if (smf == NULL) {
    1.64 +		fg_critical("Cannot allocate smf_t structure: %s", strerror(errno));
    1.65 +		return (NULL);
    1.66 +	}
    1.67 +
    1.68 +	memset(smf, 0, sizeof(smf_t));
    1.69 +
    1.70 +	smf->tracks_array = fg_ptr_array_new();
    1.71 +	assert(smf->tracks_array);
    1.72 +
    1.73 +	smf->tempo_array = fg_ptr_array_new();
    1.74 +	assert(smf->tempo_array);
    1.75 +
    1.76 +	cantfail = smf_set_ppqn(smf, 120);
    1.77 +	assert(!cantfail);
    1.78 +
    1.79 +	cantfail = smf_set_format(smf, 0);
    1.80 +	assert(!cantfail);
    1.81 +
    1.82 +	smf_init_tempo(smf);
    1.83 +
    1.84 +	return (smf);
    1.85 +}
    1.86 +
    1.87 +/**
    1.88 + * Frees smf and all it's descendant structures.
    1.89 + */
    1.90 +void
    1.91 +smf_delete(smf_t *smf)
    1.92 +{
    1.93 +	/* Remove all the tracks, from last to first. */
    1.94 +	while (smf->tracks_array->len > 0)
    1.95 +		smf_track_delete(fg_ptr_array_index(smf->tracks_array, smf->tracks_array->len - 1));
    1.96 +
    1.97 +	smf_fini_tempo(smf);
    1.98 +
    1.99 +	assert(smf->tracks_array->len == 0);
   1.100 +	assert(smf->number_of_tracks == 0);
   1.101 +	fg_ptr_array_free(smf->tracks_array, TRUE);
   1.102 +	fg_ptr_array_free(smf->tempo_array, TRUE);
   1.103 +
   1.104 +	memset(smf, 0, sizeof(smf_t));
   1.105 +	free(smf);
   1.106 +}
   1.107 +
   1.108 +/**
   1.109 + * Allocates new smf_track_t structure.
   1.110 + * \return pointer to smf_track_t or NULL.
   1.111 + */
   1.112 +smf_track_t *
   1.113 +smf_track_new(void)
   1.114 +{
   1.115 +	smf_track_t *track = malloc(sizeof(smf_track_t));
   1.116 +	if (track == NULL) {
   1.117 +		fg_critical("Cannot allocate smf_track_t structure: %s", strerror(errno));
   1.118 +		return (NULL);
   1.119 +	}
   1.120 +
   1.121 +	memset(track, 0, sizeof(smf_track_t));
   1.122 +	track->next_event_number = -1;
   1.123 +
   1.124 +	track->events_array = fg_ptr_array_new();
   1.125 +	assert(track->events_array);
   1.126 +
   1.127 +	return (track);
   1.128 +}
   1.129 +
   1.130 +/**
   1.131 + * Detaches track from its smf and frees it.
   1.132 + */
   1.133 +void
   1.134 +smf_track_delete(smf_track_t *track)
   1.135 +{
   1.136 +	assert(track);
   1.137 +	assert(track->events_array);
   1.138 +
   1.139 +	/* Remove all the events, from last to first. */
   1.140 +	while (track->events_array->len > 0)
   1.141 +		smf_event_delete(fg_ptr_array_index(track->events_array, track->events_array->len - 1));
   1.142 +
   1.143 +	if (track->smf)
   1.144 +		smf_track_remove_from_smf(track);
   1.145 +
   1.146 +	assert(track->events_array->len == 0);
   1.147 +	assert(track->number_of_events == 0);
   1.148 +	fg_ptr_array_free(track->events_array, TRUE);
   1.149 +
   1.150 +	memset(track, 0, sizeof(smf_track_t));
   1.151 +	free(track);
   1.152 +}
   1.153 +
   1.154 +
   1.155 +/**
   1.156 + * Appends smf_track_t to smf.
   1.157 + */
   1.158 +void
   1.159 +smf_add_track(smf_t *smf, smf_track_t *track)
   1.160 +{
   1.161 +	int cantfail;
   1.162 +
   1.163 +	assert(track->smf == NULL);
   1.164 +
   1.165 +	track->smf = smf;
   1.166 +	fg_ptr_array_add(smf->tracks_array, track);
   1.167 +
   1.168 +	smf->number_of_tracks++;
   1.169 +	track->track_number = smf->number_of_tracks;
   1.170 +
   1.171 +	if (smf->number_of_tracks > 1) {
   1.172 +		cantfail = smf_set_format(smf, 1);
   1.173 +		assert(!cantfail);
   1.174 +	}
   1.175 +}
   1.176 +
   1.177 +/**
   1.178 + * Detaches track from the smf.
   1.179 + */
   1.180 +void
   1.181 +smf_track_remove_from_smf(smf_track_t *track)
   1.182 +{
   1.183 +	int i, j;
   1.184 +	smf_track_t *tmp;
   1.185 +	smf_event_t *ev;
   1.186 +
   1.187 +	assert(track->smf != NULL);
   1.188 +
   1.189 +	track->smf->number_of_tracks--;
   1.190 +
   1.191 +	assert(track->smf->tracks_array);
   1.192 +	fg_ptr_array_remove(track->smf->tracks_array, track);
   1.193 +
   1.194 +	/* Renumber the rest of the tracks, so they are consecutively numbered. */
   1.195 +	for (i = track->track_number; i <= track->smf->number_of_tracks; i++) {
   1.196 +		tmp = smf_get_track_by_number(track->smf, i);
   1.197 +		tmp->track_number = i;
   1.198 +
   1.199 +		/*
   1.200 +		 * Events have track numbers too.  I guess this wasn't a wise
   1.201 +		 * decision.  ;-/
   1.202 +		 */
   1.203 +		for (j = 1; j <= tmp->number_of_events; j++) {
   1.204 +			ev = smf_track_get_event_by_number(tmp, j);
   1.205 +			ev->track_number = i;
   1.206 +		}
   1.207 +	}
   1.208 +
   1.209 +	track->track_number = -1;
   1.210 +	track->smf = NULL;
   1.211 +}
   1.212 +
   1.213 +/**
   1.214 + * Allocates new smf_event_t structure.  The caller is responsible for allocating
   1.215 + * event->midi_buffer, filling it with MIDI data and setting event->midi_buffer_length properly.
   1.216 + * Note that event->midi_buffer will be freed by smf_event_delete.
   1.217 + * \return pointer to smf_event_t or NULL.
   1.218 + */
   1.219 +smf_event_t *
   1.220 +smf_event_new(void)
   1.221 +{
   1.222 +	smf_event_t *event = malloc(sizeof(smf_event_t));
   1.223 +	if (event == NULL) {
   1.224 +		fg_critical("Cannot allocate smf_event_t structure: %s", strerror(errno));
   1.225 +		return (NULL);
   1.226 +	}
   1.227 +
   1.228 +	memset(event, 0, sizeof(smf_event_t));
   1.229 +
   1.230 +	event->delta_time_pulses = -1;
   1.231 +	event->time_pulses = -1;
   1.232 +	event->time_seconds = -1.0;
   1.233 +	event->track_number = -1;
   1.234 +
   1.235 +	return (event);
   1.236 +}
   1.237 +
   1.238 +/**
   1.239 + * Allocates an smf_event_t structure and fills it with "len" bytes copied
   1.240 + * from "midi_data".
   1.241 + * \param midi_data Pointer to MIDI data.  It sill be copied to the newly allocated event->midi_buffer.
   1.242 + * \param len Length of the buffer.  It must be proper MIDI event length, e.g. 3 for Note On event.
   1.243 + * \return Event containing MIDI data or NULL.
   1.244 + */
   1.245 +smf_event_t *
   1.246 +smf_event_new_from_pointer(void *midi_data, int len)
   1.247 +{
   1.248 +	smf_event_t *event;
   1.249 +
   1.250 +	event = smf_event_new();
   1.251 +	if (event == NULL)
   1.252 +		return (NULL);
   1.253 +
   1.254 +	event->midi_buffer_length = len;
   1.255 +	event->midi_buffer = malloc(event->midi_buffer_length);
   1.256 +	if (event->midi_buffer == NULL) {
   1.257 +		fg_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno));
   1.258 +		smf_event_delete(event);
   1.259 +
   1.260 +		return (NULL);
   1.261 +	}
   1.262 +
   1.263 +	memcpy(event->midi_buffer, midi_data, len);
   1.264 +
   1.265 +	return (event);
   1.266 +}
   1.267 +
   1.268 +/**
   1.269 + * Allocates an smf_event_t structure and fills it with at most three bytes of data.
   1.270 + * For example, if you need to create Note On event, do something like this:
   1.271 + *
   1.272 + * smf_event_new_from_bytes(0x90, 0x3C, 0x7f);
   1.273 + *
   1.274 + * To create event for MIDI message that is shorter than three bytes, do something
   1.275 + * like this:
   1.276 + *
   1.277 + * smf_event_new_from_bytes(0xC0, 0x42, -1);
   1.278 + *
   1.279 + * \param first_byte First byte of MIDI message.  Must be valid status byte.
   1.280 + * \param second_byte Second byte of MIDI message or -1, if message is one byte long.
   1.281 + * \param third_byte Third byte of MIDI message or -1, if message is two bytes long.
   1.282 + * \return Event containing MIDI data or NULL.
   1.283 + */
   1.284 +smf_event_t *
   1.285 +smf_event_new_from_bytes(int first_byte, int second_byte, int third_byte)
   1.286 +{
   1.287 +	int len;
   1.288 +
   1.289 +	smf_event_t *event;
   1.290 +
   1.291 +	event = smf_event_new();
   1.292 +	if (event == NULL)
   1.293 +		return (NULL);
   1.294 +
   1.295 +	if (first_byte < 0) {
   1.296 +		fg_critical("First byte of MIDI message cannot be < 0");
   1.297 +		smf_event_delete(event);
   1.298 +
   1.299 +		return (NULL);
   1.300 +	}
   1.301 +
   1.302 +	if (first_byte > 255) {
   1.303 +		fg_critical("smf_event_new_from_bytes: first byte is %d, which is larger than 255.", first_byte);
   1.304 +		return (NULL);
   1.305 +	}
   1.306 +
   1.307 +	if (!is_status_byte(first_byte)) {
   1.308 +		fg_critical("smf_event_new_from_bytes: first byte is not a valid status byte.");
   1.309 +		return (NULL);
   1.310 +	}
   1.311 +
   1.312 +
   1.313 +	if (second_byte < 0)
   1.314 +		len = 1;
   1.315 +	else if (third_byte < 0)
   1.316 +		len = 2;
   1.317 +	else
   1.318 +		len = 3;
   1.319 +
   1.320 +	if (len > 1) {
   1.321 +		if (second_byte > 255) {
   1.322 +			fg_critical("smf_event_new_from_bytes: second byte is %d, which is larger than 255.", second_byte);
   1.323 +			return (NULL);
   1.324 +		}
   1.325 +
   1.326 +		if (is_status_byte(second_byte)) {
   1.327 +			fg_critical("smf_event_new_from_bytes: second byte cannot be a status byte.");
   1.328 +			return (NULL);
   1.329 +		}
   1.330 +	}
   1.331 +
   1.332 +	if (len > 2) {
   1.333 +		if (third_byte > 255) {
   1.334 +			fg_critical("smf_event_new_from_bytes: third byte is %d, which is larger than 255.", third_byte);
   1.335 +			return (NULL);
   1.336 +		}
   1.337 +
   1.338 +		if (is_status_byte(third_byte)) {
   1.339 +			fg_critical("smf_event_new_from_bytes: third byte cannot be a status byte.");
   1.340 +			return (NULL);
   1.341 +		}
   1.342 +	}
   1.343 +
   1.344 +	event->midi_buffer_length = len;
   1.345 +	event->midi_buffer = malloc(event->midi_buffer_length);
   1.346 +	if (event->midi_buffer == NULL) {
   1.347 +		fg_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno));
   1.348 +		smf_event_delete(event);
   1.349 +
   1.350 +		return (NULL);
   1.351 +	}
   1.352 +
   1.353 +	event->midi_buffer[0] = first_byte;
   1.354 +	if (len > 1)
   1.355 +		event->midi_buffer[1] = second_byte;
   1.356 +	if (len > 2)
   1.357 +		event->midi_buffer[2] = third_byte;
   1.358 +
   1.359 +	return (event);
   1.360 +}
   1.361 +
   1.362 +/**
   1.363 + * Detaches event from its track and frees it.
   1.364 + */
   1.365 +void
   1.366 +smf_event_delete(smf_event_t *event)
   1.367 +{
   1.368 +	if (event->track != NULL)
   1.369 +		smf_event_remove_from_track(event);
   1.370 +
   1.371 +	if (event->midi_buffer != NULL) {
   1.372 +		memset(event->midi_buffer, 0, event->midi_buffer_length);
   1.373 +		free(event->midi_buffer);
   1.374 +	}
   1.375 +
   1.376 +	memset(event, 0, sizeof(smf_event_t));
   1.377 +	free(event);
   1.378 +}
   1.379 +
   1.380 +/**
   1.381 + * Used for sorting track->events_array.
   1.382 + */
   1.383 +static gint
   1.384 +events_array_compare_function(gconstpointer aa, gconstpointer bb)
   1.385 +{
   1.386 +	smf_event_t *a, *b;
   1.387 +
   1.388 +	/* "The comparison function for fg_ptr_array_sort() doesn't take the pointers
   1.389 +	    from the array as arguments, it takes pointers to the pointers in the array." */
   1.390 +	a = (smf_event_t *)*(gpointer *)aa;
   1.391 +	b = (smf_event_t *)*(gpointer *)bb;
   1.392 +
   1.393 +	if (a->time_pulses < b->time_pulses)
   1.394 +		return (-1);
   1.395 +
   1.396 +	if (a->time_pulses > b->time_pulses)
   1.397 +		return (1);
   1.398 +
   1.399 +	/*
   1.400 +	 * We need to preserve original order, otherwise things will break
   1.401 +	 * when there are several events with the same ->time_pulses.
   1.402 +	 * XXX: This is an ugly hack; we should remove sorting altogether.
   1.403 +	 */
   1.404 +
   1.405 +	if (a->event_number < b->event_number)
   1.406 +		return (-1);
   1.407 +
   1.408 +	if (a->event_number > b->event_number)
   1.409 +		return (1);
   1.410 +
   1.411 +	return (0);
   1.412 +}
   1.413 +
   1.414 +/*
   1.415 + * An assumption here is that if there is an EOT event, it will be at the end of the track.
   1.416 + */
   1.417 +static void
   1.418 +remove_eot_if_before_pulses(smf_track_t *track, int pulses)
   1.419 +{
   1.420 +	smf_event_t *event;
   1.421 +
   1.422 +	event = smf_track_get_last_event(track);
   1.423 +
   1.424 +	if (event == NULL)
   1.425 +		return;
   1.426 +
   1.427 +	if (!smf_event_is_eot(event))
   1.428 +		return;
   1.429 +
   1.430 +	if (event->time_pulses > pulses)
   1.431 +		return;
   1.432 +
   1.433 +	smf_event_remove_from_track(event);
   1.434 +}
   1.435 +
   1.436 +/**
   1.437 + * Adds the event to the track and computes ->delta_pulses.  Note that it is faster
   1.438 + * to append events to the end of the track than to insert them in the middle.
   1.439 + * Usually you want to use smf_track_add_event_seconds or smf_track_add_event_pulses
   1.440 + * instead of this one.  Event needs to have ->time_pulses and ->time_seconds already set.
   1.441 + * If you try to add event after an EOT, EOT event will be automatically deleted.
   1.442 + */
   1.443 +void
   1.444 +smf_track_add_event(smf_track_t *track, smf_event_t *event)
   1.445 +{
   1.446 +	int i, last_pulses = 0;
   1.447 +
   1.448 +	assert(track->smf != NULL);
   1.449 +	assert(event->track == NULL);
   1.450 +	assert(event->delta_time_pulses == -1);
   1.451 +	assert(event->time_pulses >= 0);
   1.452 +	assert(event->time_seconds >= 0.0);
   1.453 +
   1.454 +	remove_eot_if_before_pulses(track, event->time_pulses);
   1.455 +
   1.456 +	event->track = track;
   1.457 +	event->track_number = track->track_number;
   1.458 +
   1.459 +	if (track->number_of_events == 0) {
   1.460 +		assert(track->next_event_number == -1);
   1.461 +		track->next_event_number = 1;
   1.462 +	}
   1.463 +
   1.464 +	if (track->number_of_events > 0)
   1.465 +		last_pulses = smf_track_get_last_event(track)->time_pulses;
   1.466 +
   1.467 +	track->number_of_events++;
   1.468 +
   1.469 +	/* Are we just appending element at the end of the track? */
   1.470 +	if (last_pulses <= event->time_pulses) {
   1.471 +		event->delta_time_pulses = event->time_pulses - last_pulses;
   1.472 +		assert(event->delta_time_pulses >= 0);
   1.473 +		fg_ptr_array_add(track->events_array, event);
   1.474 +		event->event_number = track->number_of_events;
   1.475 +
   1.476 +	/* We need to insert in the middle of the track.  XXX: This is slow. */
   1.477 +	} else {
   1.478 +		/* Append, then sort according to ->time_pulses. */
   1.479 +		fg_ptr_array_add(track->events_array, event);
   1.480 +		fg_ptr_array_sort(track->events_array, events_array_compare_function);
   1.481 +
   1.482 +		/* Renumber entries and fix their ->delta_pulses. */
   1.483 +		for (i = 1; i <= track->number_of_events; i++) {
   1.484 +			smf_event_t *tmp = smf_track_get_event_by_number(track, i);
   1.485 +			tmp->event_number = i;
   1.486 +
   1.487 +			if (tmp->delta_time_pulses != -1)
   1.488 +				continue;
   1.489 +
   1.490 +			if (i == 1) {
   1.491 +				tmp->delta_time_pulses = tmp->time_pulses;
   1.492 +			} else {
   1.493 +				tmp->delta_time_pulses = tmp->time_pulses -
   1.494 +					smf_track_get_event_by_number(track, i - 1)->time_pulses;
   1.495 +				assert(tmp->delta_time_pulses >= 0);
   1.496 +			}
   1.497 +		}
   1.498 +
   1.499 +		/* Adjust ->delta_time_pulses of the next event. */
   1.500 +		if (event->event_number < track->number_of_events) {
   1.501 +			smf_event_t *next_event = smf_track_get_event_by_number(track, event->event_number + 1);
   1.502 +			assert(next_event);
   1.503 +			assert(next_event->time_pulses >= event->time_pulses);
   1.504 +			next_event->delta_time_pulses -= event->delta_time_pulses;
   1.505 +			assert(next_event->delta_time_pulses >= 0);
   1.506 +		}
   1.507 +	}
   1.508 +
   1.509 +	if (smf_event_is_tempo_change_or_time_signature(event)) {
   1.510 +		if (smf_event_is_last(event))
   1.511 +			maybe_add_to_tempo_map(event);
   1.512 +		else
   1.513 +			smf_create_tempo_map_and_compute_seconds(event->track->smf);
   1.514 +	}
   1.515 +}
   1.516 +
   1.517 +/**
   1.518 + * Add End Of Track metaevent.  Using it is optional, libsmf will automatically
   1.519 + * add EOT to the tracks during smf_save, with delta_pulses 0.  If you try to add EOT
   1.520 + * in the middle of the track, it will fail and nonzero value will be returned.
   1.521 + * If you try to add EOT after another EOT event, it will be added, but the existing
   1.522 + * EOT event will be removed.
   1.523 + *
   1.524 + * \return 0 if everything went ok, nonzero otherwise.
   1.525 + */
   1.526 +int
   1.527 +smf_track_add_eot_delta_pulses(smf_track_t *track, int delta)
   1.528 +{
   1.529 +	smf_event_t *event;
   1.530 +
   1.531 +	event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00);
   1.532 +	if (event == NULL)
   1.533 +		return (-1);
   1.534 +
   1.535 +	smf_track_add_event_delta_pulses(track, event, delta);
   1.536 +
   1.537 +	return (0);
   1.538 +}
   1.539 +
   1.540 +int
   1.541 +smf_track_add_eot_pulses(smf_track_t *track, int pulses)
   1.542 +{
   1.543 +	smf_event_t *event, *last_event;
   1.544 +
   1.545 +	last_event = smf_track_get_last_event(track);
   1.546 +	if (last_event != NULL) {
   1.547 +		if (last_event->time_pulses > pulses)
   1.548 +			return (-2);
   1.549 +	}
   1.550 +
   1.551 +	event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00);
   1.552 +	if (event == NULL)
   1.553 +		return (-3);
   1.554 +
   1.555 +	smf_track_add_event_pulses(track, event, pulses);
   1.556 +
   1.557 +	return (0);
   1.558 +}
   1.559 +
   1.560 +int
   1.561 +smf_track_add_eot_seconds(smf_track_t *track, double seconds)
   1.562 +{
   1.563 +	smf_event_t *event, *last_event;
   1.564 +
   1.565 +	last_event = smf_track_get_last_event(track);
   1.566 +	if (last_event != NULL) {
   1.567 +		if (last_event->time_seconds > seconds)
   1.568 +			return (-2);
   1.569 +	}
   1.570 +
   1.571 +	event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00);
   1.572 +	if (event == NULL)
   1.573 +		return (-1);
   1.574 +
   1.575 +	smf_track_add_event_seconds(track, event, seconds);
   1.576 +
   1.577 +	return (0);
   1.578 +}
   1.579 +
   1.580 +/**
   1.581 + * Detaches event from its track.
   1.582 + */
   1.583 +void
   1.584 +smf_event_remove_from_track(smf_event_t *event)
   1.585 +{
   1.586 +	int i, was_last;
   1.587 +	smf_event_t *tmp;
   1.588 +	smf_track_t *track;
   1.589 +
   1.590 +	assert(event->track != NULL);
   1.591 +	assert(event->track->smf != NULL);
   1.592 +
   1.593 +	track = event->track;
   1.594 +	was_last = smf_event_is_last(event);
   1.595 +
   1.596 +	/* Adjust ->delta_time_pulses of the next event. */
   1.597 +	if (event->event_number < track->number_of_events) {
   1.598 +		tmp = smf_track_get_event_by_number(track, event->event_number + 1);
   1.599 +		assert(tmp);
   1.600 +		tmp->delta_time_pulses += event->delta_time_pulses;
   1.601 +	}
   1.602 +
   1.603 +	track->number_of_events--;
   1.604 +	fg_ptr_array_remove(track->events_array, event);
   1.605 +
   1.606 +	if (track->number_of_events == 0)
   1.607 +		track->next_event_number = -1;
   1.608 +
   1.609 +	/* Renumber the rest of the events, so they are consecutively numbered. */
   1.610 +	for (i = event->event_number; i <= track->number_of_events; i++) {
   1.611 +		tmp = smf_track_get_event_by_number(track, i);
   1.612 +		tmp->event_number = i;
   1.613 +	}
   1.614 +
   1.615 +	if (smf_event_is_tempo_change_or_time_signature(event)) {
   1.616 +		/* XXX: This will cause problems, when there is more than one Tempo Change event at a given time. */
   1.617 +		if (was_last)
   1.618 +			remove_last_tempo_with_pulses(event->track->smf, event->time_pulses);
   1.619 +		else
   1.620 +			smf_create_tempo_map_and_compute_seconds(track->smf);
   1.621 +	}
   1.622 +
   1.623 +	event->track = NULL;
   1.624 +	event->event_number = -1;
   1.625 +	event->delta_time_pulses = -1;
   1.626 +	event->time_pulses = -1;
   1.627 +	event->time_seconds = -1.0;
   1.628 +}
   1.629 +
   1.630 +/**
   1.631 +  * \return Nonzero if event is Tempo Change or Time Signature metaevent.
   1.632 +  */
   1.633 +int
   1.634 +smf_event_is_tempo_change_or_time_signature(const smf_event_t *event)
   1.635 +{
   1.636 +	if (!smf_event_is_metadata(event))
   1.637 +		return (0);
   1.638 +
   1.639 +	assert(event->midi_buffer_length >= 2);
   1.640 +
   1.641 +	if (event->midi_buffer[1] == 0x51 || event->midi_buffer[1] == 0x58)
   1.642 +		return (1);
   1.643 +
   1.644 +	return (0);
   1.645 +}
   1.646 +
   1.647 +/**
   1.648 +  * Sets "Format" field of MThd header to the specified value.  Note that you
   1.649 +  * don't really need to use this, as libsmf will automatically change format
   1.650 +  * from 0 to 1 when you add the second track.
   1.651 +  * \param smf SMF.
   1.652 +  * \param format 0 for one track per file, 1 for several tracks per file.
   1.653 +  */
   1.654 +int
   1.655 +smf_set_format(smf_t *smf, int format)
   1.656 +{
   1.657 +	assert(format == 0 || format == 1);
   1.658 +
   1.659 +	if (smf->number_of_tracks > 1 && format == 0) {
   1.660 +		fg_critical("There is more than one track, cannot set format to 0.");
   1.661 +		return (-1);
   1.662 +	}
   1.663 +
   1.664 +	smf->format = format;
   1.665 +
   1.666 +	return (0);
   1.667 +}
   1.668 +
   1.669 +/**
   1.670 +  * Sets the PPQN ("Division") field of MThd header.  This is mandatory, you
   1.671 +  * should call it right after smf_new.  Note that changing PPQN will change time_seconds
   1.672 +  * of all the events.
   1.673 +  * \param smf SMF.
   1.674 +  * \param ppqn New PPQN.
   1.675 +  */
   1.676 +int
   1.677 +smf_set_ppqn(smf_t *smf, int ppqn)
   1.678 +{
   1.679 +	assert(ppqn > 0);
   1.680 +
   1.681 +	smf->ppqn = ppqn;
   1.682 +
   1.683 +	return (0);
   1.684 +}
   1.685 +
   1.686 +/**
   1.687 +  * Returns next event from the track given and advances next event counter.
   1.688 +  * Do not depend on End Of Track event being the last event on the track - it
   1.689 +  * is possible that the track will not end with EOT if you haven't added it
   1.690 +  * yet.  EOTs are added automatically during smf_save().
   1.691 +  *
   1.692 +  * \return Event or NULL, if there are no more events left in this track.
   1.693 +  */
   1.694 +smf_event_t *
   1.695 +smf_track_get_next_event(smf_track_t *track)
   1.696 +{
   1.697 +	smf_event_t *event, *next_event;
   1.698 +
   1.699 +	/* End of track? */
   1.700 +	if (track->next_event_number == -1)
   1.701 +		return (NULL);
   1.702 +
   1.703 +	assert(track->next_event_number >= 1);
   1.704 +	assert(track->number_of_events > 0);
   1.705 +
   1.706 +	event = smf_track_get_event_by_number(track, track->next_event_number);
   1.707 +
   1.708 +	assert(event != NULL);
   1.709 +
   1.710 +	/* Is this the last event in the track? */
   1.711 +	if (track->next_event_number < track->number_of_events) {
   1.712 +		next_event = smf_track_get_event_by_number(track, track->next_event_number + 1);
   1.713 +		assert(next_event);
   1.714 +
   1.715 +		track->time_of_next_event = next_event->time_pulses;
   1.716 +		track->next_event_number++;
   1.717 +	} else {
   1.718 +		track->next_event_number = -1;
   1.719 +	}
   1.720 +
   1.721 +	return (event);
   1.722 +}
   1.723 +
   1.724 +/**
   1.725 +  * Returns next event from the track given.  Does not change next event counter,
   1.726 +  * so repeatedly calling this routine will return the same event.
   1.727 +  * \return Event or NULL, if there are no more events left in this track.
   1.728 +  */
   1.729 +static smf_event_t *
   1.730 +smf_peek_next_event_from_track(smf_track_t *track)
   1.731 +{
   1.732 +	smf_event_t *event;
   1.733 +
   1.734 +	/* End of track? */
   1.735 +	if (track->next_event_number == -1)
   1.736 +		return (NULL);
   1.737 +
   1.738 +	assert(track->next_event_number >= 1);
   1.739 +	assert(track->events_array->len != 0);
   1.740 +
   1.741 +	event = smf_track_get_event_by_number(track, track->next_event_number);
   1.742 +
   1.743 +	return (event);
   1.744 +}
   1.745 +
   1.746 +/**
   1.747 + * \return Track with a given number or NULL, if there is no such track.
   1.748 + * Tracks are numbered consecutively starting from one.
   1.749 + */
   1.750 +smf_track_t *
   1.751 +smf_get_track_by_number(const smf_t *smf, int track_number)
   1.752 +{
   1.753 +	smf_track_t *track;
   1.754 +
   1.755 +	assert(track_number >= 1);
   1.756 +
   1.757 +	if (track_number > smf->number_of_tracks)
   1.758 +		return (NULL);
   1.759 +
   1.760 +	track = (smf_track_t *)fg_ptr_array_index(smf->tracks_array, track_number - 1);
   1.761 +
   1.762 +	assert(track);
   1.763 +
   1.764 +	return (track);
   1.765 +}
   1.766 +
   1.767 +/**
   1.768 + * \return Event with a given number or NULL, if there is no such event.
   1.769 + * Events are numbered consecutively starting from one.
   1.770 + */
   1.771 +smf_event_t *
   1.772 +smf_track_get_event_by_number(const smf_track_t *track, int event_number)
   1.773 +{
   1.774 +	smf_event_t *event;
   1.775 +
   1.776 +	assert(event_number >= 1);
   1.777 +
   1.778 +	if (event_number > track->number_of_events)
   1.779 +		return (NULL);
   1.780 +
   1.781 +	event = fg_ptr_array_index(track->events_array, event_number - 1);
   1.782 +
   1.783 +	assert(event);
   1.784 +
   1.785 +	return (event);
   1.786 +}
   1.787 +
   1.788 +/**
   1.789 + * \return Last event on the track or NULL, if track is empty.
   1.790 + */
   1.791 +smf_event_t *
   1.792 +smf_track_get_last_event(const smf_track_t *track)
   1.793 +{
   1.794 +	smf_event_t *event;
   1.795 +
   1.796 +	if (track->number_of_events == 0)
   1.797 +		return (NULL);
   1.798 +
   1.799 +	event = smf_track_get_event_by_number(track, track->number_of_events);
   1.800 +
   1.801 +	return (event);
   1.802 +}
   1.803 +
   1.804 +/**
   1.805 + * Searches for track that contains next event, in time order.  In other words,
   1.806 + * returns the track that contains event that should be played next.
   1.807 + * \return Track with next event or NULL, if there are no events left.
   1.808 + */
   1.809 +smf_track_t *
   1.810 +smf_find_track_with_next_event(smf_t *smf)
   1.811 +{
   1.812 +	int i, min_time = 0;
   1.813 +	smf_track_t *track = NULL, *min_time_track = NULL;
   1.814 +
   1.815 +	/* Find track with event that should be played next. */
   1.816 +	for (i = 1; i <= smf->number_of_tracks; i++) {
   1.817 +		track = smf_get_track_by_number(smf, i);
   1.818 +
   1.819 +		assert(track);
   1.820 +
   1.821 +		/* No more events in this track? */
   1.822 +		if (track->next_event_number == -1)
   1.823 +			continue;
   1.824 +
   1.825 +		if (track->time_of_next_event < min_time || min_time_track == NULL) {
   1.826 +			min_time = track->time_of_next_event;
   1.827 +			min_time_track = track;
   1.828 +		}
   1.829 +	}
   1.830 +
   1.831 +	return (min_time_track);
   1.832 +}
   1.833 +
   1.834 +/**
   1.835 +  * \return Next event, in time order, or NULL, if there are none left.
   1.836 +  */
   1.837 +smf_event_t *
   1.838 +smf_get_next_event(smf_t *smf)
   1.839 +{
   1.840 +	smf_event_t *event;
   1.841 +	smf_track_t *track = smf_find_track_with_next_event(smf);
   1.842 +
   1.843 +	if (track == NULL) {
   1.844 +#if 0
   1.845 +		g_debug("End of the song.");
   1.846 +#endif
   1.847 +
   1.848 +		return (NULL);
   1.849 +	}
   1.850 +
   1.851 +	event = smf_track_get_next_event(track);
   1.852 +
   1.853 +	assert(event != NULL);
   1.854 +
   1.855 +	event->track->smf->last_seek_position = -1.0;
   1.856 +
   1.857 +	return (event);
   1.858 +}
   1.859 +
   1.860 +/**
   1.861 +  * Advance the "next event counter".  This is functionally the same as calling
   1.862 +  * smf_get_next_event and ignoring the return value.
   1.863 +  */
   1.864 +void
   1.865 +smf_skip_next_event(smf_t *smf)
   1.866 +{
   1.867 +	void *notused;
   1.868 +
   1.869 +	notused = smf_get_next_event(smf);
   1.870 +}
   1.871 +
   1.872 +/**
   1.873 +  * \return Next event, in time order, or NULL, if there are none left.  Does
   1.874 +  * not advance position in song.
   1.875 +  */
   1.876 +smf_event_t *
   1.877 +smf_peek_next_event(smf_t *smf)
   1.878 +{
   1.879 +	smf_event_t *event;
   1.880 +	smf_track_t *track = smf_find_track_with_next_event(smf);
   1.881 +
   1.882 +	if (track == NULL) {
   1.883 +#if 0
   1.884 +		g_debug("End of the song.");
   1.885 +#endif
   1.886 +
   1.887 +		return (NULL);
   1.888 +	}
   1.889 +
   1.890 +	event = smf_peek_next_event_from_track(track);
   1.891 +
   1.892 +	assert(event != NULL);
   1.893 +
   1.894 +	return (event);
   1.895 +}
   1.896 +
   1.897 +/**
   1.898 +  * Rewinds the SMF.  What that means is, after calling this routine, smf_get_next_event
   1.899 +  * will return first event in the song.
   1.900 +  */
   1.901 +void
   1.902 +smf_rewind(smf_t *smf)
   1.903 +{
   1.904 +	int i;
   1.905 +	smf_track_t *track = NULL;
   1.906 +	smf_event_t *event;
   1.907 +
   1.908 +	assert(smf);
   1.909 +
   1.910 +	smf->last_seek_position = 0.0;
   1.911 +
   1.912 +	for (i = 1; i <= smf->number_of_tracks; i++) {
   1.913 +		track = smf_get_track_by_number(smf, i);
   1.914 +
   1.915 +		assert(track != NULL);
   1.916 +
   1.917 +		if (track->number_of_events > 0) {
   1.918 +			track->next_event_number = 1;
   1.919 +			event = smf_peek_next_event_from_track(track);
   1.920 +			assert(event);
   1.921 +			track->time_of_next_event = event->time_pulses;
   1.922 +		} else {
   1.923 +			track->next_event_number = -1;
   1.924 +			track->time_of_next_event = 0;
   1.925 +#if 0
   1.926 +			g_warning("Warning: empty track.");
   1.927 +#endif
   1.928 +		}
   1.929 +	}
   1.930 +}
   1.931 +
   1.932 +/**
   1.933 +  * Seeks the SMF to the given event.  After calling this routine, smf_get_next_event
   1.934 +  * will return the event that was the second argument of this call.
   1.935 +  */
   1.936 +int
   1.937 +smf_seek_to_event(smf_t *smf, const smf_event_t *target)
   1.938 +{
   1.939 +	smf_event_t *event;
   1.940 +
   1.941 +	smf_rewind(smf);
   1.942 +
   1.943 +#if 0
   1.944 +	g_debug("Seeking to event %d, track %d.", target->event_number, target->track->track_number);
   1.945 +#endif
   1.946 +
   1.947 +	for (;;) {
   1.948 +		event = smf_peek_next_event(smf);
   1.949 +
   1.950 +		/* There can't be NULL here, unless "target" is not in this smf. */
   1.951 +		assert(event);
   1.952 +
   1.953 +		if (event != target)
   1.954 +			smf_skip_next_event(smf);
   1.955 +		else
   1.956 +			break;
   1.957 +	}
   1.958 +
   1.959 +	smf->last_seek_position = event->time_seconds;
   1.960 +
   1.961 +	return (0);
   1.962 +}
   1.963 +
   1.964 +/**
   1.965 +  * Seeks the SMF to the given position.  For example, after seeking to 1.0 seconds,
   1.966 +  * smf_get_next_event will return first event that happens after the first second of song.
   1.967 +  */
   1.968 +int
   1.969 +smf_seek_to_seconds(smf_t *smf, double seconds)
   1.970 +{
   1.971 +	smf_event_t *event;
   1.972 +
   1.973 +	assert(seconds >= 0.0);
   1.974 +
   1.975 +	if (seconds == smf->last_seek_position) {
   1.976 +#if 0
   1.977 +		g_debug("Avoiding seek to %f seconds.", seconds);
   1.978 +#endif
   1.979 +		return (0);
   1.980 +	}
   1.981 +
   1.982 +	smf_rewind(smf);
   1.983 +
   1.984 +#if 0
   1.985 +	g_debug("Seeking to %f seconds.", seconds);
   1.986 +#endif
   1.987 +
   1.988 +	for (;;) {
   1.989 +		event = smf_peek_next_event(smf);
   1.990 +
   1.991 +		if (event == NULL) {
   1.992 +			fg_critical("Trying to seek past the end of song.");
   1.993 +			return (-1);
   1.994 +		}
   1.995 +
   1.996 +		if (event->time_seconds < seconds)
   1.997 +			smf_skip_next_event(smf);
   1.998 +		else
   1.999 +			break;
  1.1000 +	}
  1.1001 +
  1.1002 +	smf->last_seek_position = seconds;
  1.1003 +
  1.1004 +	return (0);
  1.1005 +}
  1.1006 +
  1.1007 +/**
  1.1008 +  * Seeks the SMF to the given position.  For example, after seeking to 10 pulses,
  1.1009 +  * smf_get_next_event will return first event that happens after the first ten pulses.
  1.1010 +  */
  1.1011 +int
  1.1012 +smf_seek_to_pulses(smf_t *smf, int pulses)
  1.1013 +{
  1.1014 +	smf_event_t *event;
  1.1015 +
  1.1016 +	assert(pulses >= 0);
  1.1017 +
  1.1018 +	smf_rewind(smf);
  1.1019 +
  1.1020 +#if 0
  1.1021 +	g_debug("Seeking to %d pulses.", pulses);
  1.1022 +#endif
  1.1023 +
  1.1024 +	for (;;) {
  1.1025 +		event = smf_peek_next_event(smf);
  1.1026 +
  1.1027 +		if (event == NULL) {
  1.1028 +			fg_critical("Trying to seek past the end of song.");
  1.1029 +			return (-1);
  1.1030 +		}
  1.1031 +
  1.1032 +		if (event->time_pulses < pulses)
  1.1033 +			smf_skip_next_event(smf);
  1.1034 +		else
  1.1035 +			break;
  1.1036 +	}
  1.1037 +
  1.1038 +	smf->last_seek_position = event->time_seconds;
  1.1039 +
  1.1040 +	return (0);
  1.1041 +}
  1.1042 +
  1.1043 +/**
  1.1044 +  * \return Length of SMF, in pulses.
  1.1045 +  */
  1.1046 +int
  1.1047 +smf_get_length_pulses(const smf_t *smf)
  1.1048 +{
  1.1049 +	int pulses = 0, i;
  1.1050 +
  1.1051 +	for (i = 1; i <= smf->number_of_tracks; i++) {
  1.1052 +		smf_track_t *track;
  1.1053 +		smf_event_t *event;
  1.1054 +
  1.1055 +		track = smf_get_track_by_number(smf, i);
  1.1056 +		assert(track);
  1.1057 +
  1.1058 +		event = smf_track_get_last_event(track);
  1.1059 +		/* Empty track? */
  1.1060 +		if (event == NULL)
  1.1061 +			continue;
  1.1062 +
  1.1063 +		if (event->time_pulses > pulses)
  1.1064 +			pulses = event->time_pulses;
  1.1065 +	}
  1.1066 +
  1.1067 +	return (pulses);
  1.1068 +}
  1.1069 +
  1.1070 +/**
  1.1071 +  * \return Length of SMF, in seconds.
  1.1072 +  */
  1.1073 +double
  1.1074 +smf_get_length_seconds(const smf_t *smf)
  1.1075 +{
  1.1076 +	int i;
  1.1077 +	double seconds = 0.0;
  1.1078 +
  1.1079 +	for (i = 1; i <= smf->number_of_tracks; i++) {
  1.1080 +		smf_track_t *track;
  1.1081 +		smf_event_t *event;
  1.1082 +
  1.1083 +		track = smf_get_track_by_number(smf, i);
  1.1084 +		assert(track);
  1.1085 +
  1.1086 +		event = smf_track_get_last_event(track);
  1.1087 +		/* Empty track? */
  1.1088 +		if (event == NULL)
  1.1089 +			continue;
  1.1090 +
  1.1091 +		if (event->time_seconds > seconds)
  1.1092 +			seconds = event->time_seconds;
  1.1093 +	}
  1.1094 +
  1.1095 +	return (seconds);
  1.1096 +}
  1.1097 +
  1.1098 +/**
  1.1099 +  * \return Nonzero, if there are no events in the SMF after this one.
  1.1100 +  * Note that may be more than one "last event", if they occur at the same time.
  1.1101 +  */
  1.1102 +int
  1.1103 +smf_event_is_last(const smf_event_t *event)
  1.1104 +{
  1.1105 +	if (smf_get_length_pulses(event->track->smf) <= event->time_pulses)
  1.1106 +		return (1);
  1.1107 +
  1.1108 +	return (0);
  1.1109 +}
  1.1110 +
  1.1111 +/**
  1.1112 +  * \return Version of libsmf.
  1.1113 +  */
  1.1114 +const char *
  1.1115 +smf_get_version(void)
  1.1116 +{
  1.1117 +	return (SMF_VERSION);
  1.1118 +}
  1.1119 +