00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00035
00036
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <assert.h>
00040 #include <math.h>
00041 #include <errno.h>
00042 #ifdef __MINGW32__
00043 #include <windows.h>
00044 #else
00045 #include <arpa/inet.h>
00046 #endif
00047 #include "smf.h"
00048 #include "smf_private.h"
00049
00054 smf_t *
00055 smf_new(void)
00056 {
00057 int cantfail;
00058
00059 smf_t *smf = malloc(sizeof(smf_t));
00060 if (smf == NULL) {
00061 g_critical("Cannot allocate smf_t structure: %s", strerror(errno));
00062 return (NULL);
00063 }
00064
00065 memset(smf, 0, sizeof(smf_t));
00066
00067 smf->tracks_array = g_ptr_array_new();
00068 assert(smf->tracks_array);
00069
00070 smf->tempo_array = g_ptr_array_new();
00071 assert(smf->tempo_array);
00072
00073 cantfail = smf_set_ppqn(smf, 120);
00074 assert(!cantfail);
00075
00076 cantfail = smf_set_format(smf, 0);
00077 assert(!cantfail);
00078
00079 smf_init_tempo(smf);
00080
00081 return (smf);
00082 }
00083
00087 void
00088 smf_delete(smf_t *smf)
00089 {
00090
00091 while (smf->tracks_array->len > 0)
00092 smf_track_delete(g_ptr_array_index(smf->tracks_array, smf->tracks_array->len - 1));
00093
00094 smf_fini_tempo(smf);
00095
00096 assert(smf->tracks_array->len == 0);
00097 assert(smf->number_of_tracks == 0);
00098 g_ptr_array_free(smf->tracks_array, TRUE);
00099 g_ptr_array_free(smf->tempo_array, TRUE);
00100
00101 memset(smf, 0, sizeof(smf_t));
00102 free(smf);
00103 }
00104
00109 smf_track_t *
00110 smf_track_new(void)
00111 {
00112 smf_track_t *track = malloc(sizeof(smf_track_t));
00113 if (track == NULL) {
00114 g_critical("Cannot allocate smf_track_t structure: %s", strerror(errno));
00115 return (NULL);
00116 }
00117
00118 memset(track, 0, sizeof(smf_track_t));
00119 track->next_event_number = -1;
00120
00121 track->events_array = g_ptr_array_new();
00122 assert(track->events_array);
00123
00124 return (track);
00125 }
00126
00130 void
00131 smf_track_delete(smf_track_t *track)
00132 {
00133 assert(track);
00134 assert(track->events_array);
00135
00136
00137 while (track->events_array->len > 0)
00138 smf_event_delete(g_ptr_array_index(track->events_array, track->events_array->len - 1));
00139
00140 if (track->smf)
00141 smf_track_remove_from_smf(track);
00142
00143 assert(track->events_array->len == 0);
00144 assert(track->number_of_events == 0);
00145 g_ptr_array_free(track->events_array, TRUE);
00146
00147 memset(track, 0, sizeof(smf_track_t));
00148 free(track);
00149 }
00150
00151
00155 void
00156 smf_add_track(smf_t *smf, smf_track_t *track)
00157 {
00158 int cantfail;
00159
00160 assert(track->smf == NULL);
00161
00162 track->smf = smf;
00163 g_ptr_array_add(smf->tracks_array, track);
00164
00165 smf->number_of_tracks++;
00166 track->track_number = smf->number_of_tracks;
00167
00168 if (smf->number_of_tracks > 1) {
00169 cantfail = smf_set_format(smf, 1);
00170 assert(!cantfail);
00171 }
00172 }
00173
00177 void
00178 smf_track_remove_from_smf(smf_track_t *track)
00179 {
00180 int i, j;
00181 smf_track_t *tmp;
00182 smf_event_t *ev;
00183
00184 assert(track->smf != NULL);
00185
00186 track->smf->number_of_tracks--;
00187
00188 assert(track->smf->tracks_array);
00189 g_ptr_array_remove(track->smf->tracks_array, track);
00190
00191
00192 for (i = track->track_number; i <= track->smf->number_of_tracks; i++) {
00193 tmp = smf_get_track_by_number(track->smf, i);
00194 tmp->track_number = i;
00195
00196
00197
00198
00199
00200 for (j = 1; j <= tmp->number_of_events; j++) {
00201 ev = smf_track_get_event_by_number(tmp, j);
00202 ev->track_number = i;
00203 }
00204 }
00205
00206 track->track_number = -1;
00207 track->smf = NULL;
00208 }
00209
00216 smf_event_t *
00217 smf_event_new(void)
00218 {
00219 smf_event_t *event = malloc(sizeof(smf_event_t));
00220 if (event == NULL) {
00221 g_critical("Cannot allocate smf_event_t structure: %s", strerror(errno));
00222 return (NULL);
00223 }
00224
00225 memset(event, 0, sizeof(smf_event_t));
00226
00227 event->delta_time_pulses = -1;
00228 event->time_pulses = -1;
00229 event->time_seconds = -1.0;
00230 event->track_number = -1;
00231
00232 return (event);
00233 }
00234
00242 smf_event_t *
00243 smf_event_new_from_pointer(void *midi_data, int len)
00244 {
00245 smf_event_t *event;
00246
00247 event = smf_event_new();
00248 if (event == NULL)
00249 return (NULL);
00250
00251 event->midi_buffer_length = len;
00252 event->midi_buffer = malloc(event->midi_buffer_length);
00253 if (event->midi_buffer == NULL) {
00254 g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno));
00255 smf_event_delete(event);
00256
00257 return (NULL);
00258 }
00259
00260 memcpy(event->midi_buffer, midi_data, len);
00261
00262 return (event);
00263 }
00264
00281 smf_event_t *
00282 smf_event_new_from_bytes(int first_byte, int second_byte, int third_byte)
00283 {
00284 int len;
00285
00286 smf_event_t *event;
00287
00288 event = smf_event_new();
00289 if (event == NULL)
00290 return (NULL);
00291
00292 if (first_byte < 0) {
00293 g_critical("First byte of MIDI message cannot be < 0");
00294 smf_event_delete(event);
00295
00296 return (NULL);
00297 }
00298
00299 if (first_byte > 255) {
00300 g_critical("smf_event_new_from_bytes: first byte is %d, which is larger than 255.", first_byte);
00301 return (NULL);
00302 }
00303
00304 if (!is_status_byte(first_byte)) {
00305 g_critical("smf_event_new_from_bytes: first byte is not a valid status byte.");
00306 return (NULL);
00307 }
00308
00309
00310 if (second_byte < 0)
00311 len = 1;
00312 else if (third_byte < 0)
00313 len = 2;
00314 else
00315 len = 3;
00316
00317 if (len > 1) {
00318 if (second_byte > 255) {
00319 g_critical("smf_event_new_from_bytes: second byte is %d, which is larger than 255.", second_byte);
00320 return (NULL);
00321 }
00322
00323 if (is_status_byte(second_byte)) {
00324 g_critical("smf_event_new_from_bytes: second byte cannot be a status byte.");
00325 return (NULL);
00326 }
00327 }
00328
00329 if (len > 2) {
00330 if (third_byte > 255) {
00331 g_critical("smf_event_new_from_bytes: third byte is %d, which is larger than 255.", third_byte);
00332 return (NULL);
00333 }
00334
00335 if (is_status_byte(third_byte)) {
00336 g_critical("smf_event_new_from_bytes: third byte cannot be a status byte.");
00337 return (NULL);
00338 }
00339 }
00340
00341 event->midi_buffer_length = len;
00342 event->midi_buffer = malloc(event->midi_buffer_length);
00343 if (event->midi_buffer == NULL) {
00344 g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno));
00345 smf_event_delete(event);
00346
00347 return (NULL);
00348 }
00349
00350 event->midi_buffer[0] = first_byte;
00351 if (len > 1)
00352 event->midi_buffer[1] = second_byte;
00353 if (len > 2)
00354 event->midi_buffer[2] = third_byte;
00355
00356 return (event);
00357 }
00358
00362 void
00363 smf_event_delete(smf_event_t *event)
00364 {
00365 if (event->track != NULL)
00366 smf_event_remove_from_track(event);
00367
00368 if (event->midi_buffer != NULL) {
00369 memset(event->midi_buffer, 0, event->midi_buffer_length);
00370 free(event->midi_buffer);
00371 }
00372
00373 memset(event, 0, sizeof(smf_event_t));
00374 free(event);
00375 }
00376
00380 static gint
00381 events_array_compare_function(gconstpointer aa, gconstpointer bb)
00382 {
00383 smf_event_t *a, *b;
00384
00385
00386
00387 a = (smf_event_t *)*(gpointer *)aa;
00388 b = (smf_event_t *)*(gpointer *)bb;
00389
00390 if (a->time_pulses < b->time_pulses)
00391 return (-1);
00392
00393 if (a->time_pulses > b->time_pulses)
00394 return (1);
00395
00396
00397
00398
00399
00400
00401
00402 if (a->event_number < b->event_number)
00403 return (-1);
00404
00405 if (a->event_number > b->event_number)
00406 return (1);
00407
00408 return (0);
00409 }
00410
00411
00412
00413
00414 static void
00415 remove_eot_if_before_pulses(smf_track_t *track, int pulses)
00416 {
00417 smf_event_t *event;
00418
00419 event = smf_track_get_last_event(track);
00420
00421 if (event == NULL)
00422 return;
00423
00424 if (!smf_event_is_eot(event))
00425 return;
00426
00427 if (event->time_pulses > pulses)
00428 return;
00429
00430 smf_event_remove_from_track(event);
00431 }
00432
00440 void
00441 smf_track_add_event(smf_track_t *track, smf_event_t *event)
00442 {
00443 int i, last_pulses = 0;
00444
00445 assert(track->smf != NULL);
00446 assert(event->track == NULL);
00447 assert(event->delta_time_pulses == -1);
00448 assert(event->time_pulses >= 0);
00449 assert(event->time_seconds >= 0.0);
00450
00451 remove_eot_if_before_pulses(track, event->time_pulses);
00452
00453 event->track = track;
00454 event->track_number = track->track_number;
00455
00456 if (track->number_of_events == 0) {
00457 assert(track->next_event_number == -1);
00458 track->next_event_number = 1;
00459 }
00460
00461 if (track->number_of_events > 0)
00462 last_pulses = smf_track_get_last_event(track)->time_pulses;
00463
00464 track->number_of_events++;
00465
00466
00467 if (last_pulses <= event->time_pulses) {
00468 event->delta_time_pulses = event->time_pulses - last_pulses;
00469 assert(event->delta_time_pulses >= 0);
00470 g_ptr_array_add(track->events_array, event);
00471 event->event_number = track->number_of_events;
00472
00473
00474 } else {
00475
00476 g_ptr_array_add(track->events_array, event);
00477 g_ptr_array_sort(track->events_array, events_array_compare_function);
00478
00479
00480 for (i = 1; i <= track->number_of_events; i++) {
00481 smf_event_t *tmp = smf_track_get_event_by_number(track, i);
00482 tmp->event_number = i;
00483
00484 if (tmp->delta_time_pulses != -1)
00485 continue;
00486
00487 if (i == 1) {
00488 tmp->delta_time_pulses = tmp->time_pulses;
00489 } else {
00490 tmp->delta_time_pulses = tmp->time_pulses -
00491 smf_track_get_event_by_number(track, i - 1)->time_pulses;
00492 assert(tmp->delta_time_pulses >= 0);
00493 }
00494 }
00495
00496
00497 if (event->event_number < track->number_of_events) {
00498 smf_event_t *next_event = smf_track_get_event_by_number(track, event->event_number + 1);
00499 assert(next_event);
00500 assert(next_event->time_pulses >= event->time_pulses);
00501 next_event->delta_time_pulses -= event->delta_time_pulses;
00502 assert(next_event->delta_time_pulses >= 0);
00503 }
00504 }
00505
00506 if (smf_event_is_tempo_change_or_time_signature(event)) {
00507 if (smf_event_is_last(event))
00508 maybe_add_to_tempo_map(event);
00509 else
00510 smf_create_tempo_map_and_compute_seconds(event->track->smf);
00511 }
00512 }
00513
00523 int
00524 smf_track_add_eot_delta_pulses(smf_track_t *track, int delta)
00525 {
00526 smf_event_t *event;
00527
00528 event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00);
00529 if (event == NULL)
00530 return (-1);
00531
00532 smf_track_add_event_delta_pulses(track, event, delta);
00533
00534 return (0);
00535 }
00536
00537 int
00538 smf_track_add_eot_pulses(smf_track_t *track, int pulses)
00539 {
00540 smf_event_t *event, *last_event;
00541
00542 last_event = smf_track_get_last_event(track);
00543 if (last_event != NULL) {
00544 if (last_event->time_pulses > pulses)
00545 return (-2);
00546 }
00547
00548 event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00);
00549 if (event == NULL)
00550 return (-3);
00551
00552 smf_track_add_event_pulses(track, event, pulses);
00553
00554 return (0);
00555 }
00556
00557 int
00558 smf_track_add_eot_seconds(smf_track_t *track, double seconds)
00559 {
00560 smf_event_t *event, *last_event;
00561
00562 last_event = smf_track_get_last_event(track);
00563 if (last_event != NULL) {
00564 if (last_event->time_seconds > seconds)
00565 return (-2);
00566 }
00567
00568 event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00);
00569 if (event == NULL)
00570 return (-1);
00571
00572 smf_track_add_event_seconds(track, event, seconds);
00573
00574 return (0);
00575 }
00576
00580 void
00581 smf_event_remove_from_track(smf_event_t *event)
00582 {
00583 int i, was_last;
00584 smf_event_t *tmp;
00585 smf_track_t *track;
00586
00587 assert(event->track != NULL);
00588 assert(event->track->smf != NULL);
00589
00590 track = event->track;
00591 was_last = smf_event_is_last(event);
00592
00593
00594 if (event->event_number < track->number_of_events) {
00595 tmp = smf_track_get_event_by_number(track, event->event_number + 1);
00596 assert(tmp);
00597 tmp->delta_time_pulses += event->delta_time_pulses;
00598 }
00599
00600 track->number_of_events--;
00601 g_ptr_array_remove(track->events_array, event);
00602
00603 if (track->number_of_events == 0)
00604 track->next_event_number = -1;
00605
00606
00607 for (i = event->event_number; i <= track->number_of_events; i++) {
00608 tmp = smf_track_get_event_by_number(track, i);
00609 tmp->event_number = i;
00610 }
00611
00612 if (smf_event_is_tempo_change_or_time_signature(event)) {
00613
00614 if (was_last)
00615 remove_last_tempo_with_pulses(event->track->smf, event->time_pulses);
00616 else
00617 smf_create_tempo_map_and_compute_seconds(track->smf);
00618 }
00619
00620 event->track = NULL;
00621 event->event_number = -1;
00622 event->delta_time_pulses = -1;
00623 event->time_pulses = -1;
00624 event->time_seconds = -1.0;
00625 }
00626
00630 int
00631 smf_event_is_tempo_change_or_time_signature(const smf_event_t *event)
00632 {
00633 if (!smf_event_is_metadata(event))
00634 return (0);
00635
00636 assert(event->midi_buffer_length >= 2);
00637
00638 if (event->midi_buffer[1] == 0x51 || event->midi_buffer[1] == 0x58)
00639 return (1);
00640
00641 return (0);
00642 }
00643
00651 int
00652 smf_set_format(smf_t *smf, int format)
00653 {
00654 assert(format == 0 || format == 1);
00655
00656 if (smf->number_of_tracks > 1 && format == 0) {
00657 g_critical("There is more than one track, cannot set format to 0.");
00658 return (-1);
00659 }
00660
00661 smf->format = format;
00662
00663 return (0);
00664 }
00665
00673 int
00674 smf_set_ppqn(smf_t *smf, int ppqn)
00675 {
00676 assert(ppqn > 0);
00677
00678 smf->ppqn = ppqn;
00679
00680 return (0);
00681 }
00682
00691 smf_event_t *
00692 smf_track_get_next_event(smf_track_t *track)
00693 {
00694 smf_event_t *event, *next_event;
00695
00696
00697 if (track->next_event_number == -1)
00698 return (NULL);
00699
00700 assert(track->next_event_number >= 1);
00701 assert(track->number_of_events > 0);
00702
00703 event = smf_track_get_event_by_number(track, track->next_event_number);
00704
00705 assert(event != NULL);
00706
00707
00708 if (track->next_event_number < track->number_of_events) {
00709 next_event = smf_track_get_event_by_number(track, track->next_event_number + 1);
00710 assert(next_event);
00711
00712 track->time_of_next_event = next_event->time_pulses;
00713 track->next_event_number++;
00714 } else {
00715 track->next_event_number = -1;
00716 }
00717
00718 return (event);
00719 }
00720
00726 static smf_event_t *
00727 smf_peek_next_event_from_track(smf_track_t *track)
00728 {
00729 smf_event_t *event;
00730
00731
00732 if (track->next_event_number == -1)
00733 return (NULL);
00734
00735 assert(track->next_event_number >= 1);
00736 assert(track->events_array->len != 0);
00737
00738 event = smf_track_get_event_by_number(track, track->next_event_number);
00739
00740 return (event);
00741 }
00742
00747 smf_track_t *
00748 smf_get_track_by_number(const smf_t *smf, int track_number)
00749 {
00750 smf_track_t *track;
00751
00752 assert(track_number >= 1);
00753
00754 if (track_number > smf->number_of_tracks)
00755 return (NULL);
00756
00757 track = (smf_track_t *)g_ptr_array_index(smf->tracks_array, track_number - 1);
00758
00759 assert(track);
00760
00761 return (track);
00762 }
00763
00768 smf_event_t *
00769 smf_track_get_event_by_number(const smf_track_t *track, int event_number)
00770 {
00771 smf_event_t *event;
00772
00773 assert(event_number >= 1);
00774
00775 if (event_number > track->number_of_events)
00776 return (NULL);
00777
00778 event = g_ptr_array_index(track->events_array, event_number - 1);
00779
00780 assert(event);
00781
00782 return (event);
00783 }
00784
00788 smf_event_t *
00789 smf_track_get_last_event(const smf_track_t *track)
00790 {
00791 smf_event_t *event;
00792
00793 if (track->number_of_events == 0)
00794 return (NULL);
00795
00796 event = smf_track_get_event_by_number(track, track->number_of_events);
00797
00798 return (event);
00799 }
00800
00806 smf_track_t *
00807 smf_find_track_with_next_event(smf_t *smf)
00808 {
00809 int i, min_time = 0;
00810 smf_track_t *track = NULL, *min_time_track = NULL;
00811
00812
00813 for (i = 1; i <= smf->number_of_tracks; i++) {
00814 track = smf_get_track_by_number(smf, i);
00815
00816 assert(track);
00817
00818
00819 if (track->next_event_number == -1)
00820 continue;
00821
00822 if (track->time_of_next_event < min_time || min_time_track == NULL) {
00823 min_time = track->time_of_next_event;
00824 min_time_track = track;
00825 }
00826 }
00827
00828 return (min_time_track);
00829 }
00830
00834 smf_event_t *
00835 smf_get_next_event(smf_t *smf)
00836 {
00837 smf_event_t *event;
00838 smf_track_t *track = smf_find_track_with_next_event(smf);
00839
00840 if (track == NULL) {
00841 #if 0
00842 g_debug("End of the song.");
00843 #endif
00844
00845 return (NULL);
00846 }
00847
00848 event = smf_track_get_next_event(track);
00849
00850 assert(event != NULL);
00851
00852 event->track->smf->last_seek_position = -1.0;
00853
00854 return (event);
00855 }
00856
00861 void
00862 smf_skip_next_event(smf_t *smf)
00863 {
00864 void *notused;
00865
00866 notused = smf_get_next_event(smf);
00867 }
00868
00873 smf_event_t *
00874 smf_peek_next_event(smf_t *smf)
00875 {
00876 smf_event_t *event;
00877 smf_track_t *track = smf_find_track_with_next_event(smf);
00878
00879 if (track == NULL) {
00880 #if 0
00881 g_debug("End of the song.");
00882 #endif
00883
00884 return (NULL);
00885 }
00886
00887 event = smf_peek_next_event_from_track(track);
00888
00889 assert(event != NULL);
00890
00891 return (event);
00892 }
00893
00898 void
00899 smf_rewind(smf_t *smf)
00900 {
00901 int i;
00902 smf_track_t *track = NULL;
00903 smf_event_t *event;
00904
00905 assert(smf);
00906
00907 smf->last_seek_position = 0.0;
00908
00909 for (i = 1; i <= smf->number_of_tracks; i++) {
00910 track = smf_get_track_by_number(smf, i);
00911
00912 assert(track != NULL);
00913
00914 if (track->number_of_events > 0) {
00915 track->next_event_number = 1;
00916 event = smf_peek_next_event_from_track(track);
00917 assert(event);
00918 track->time_of_next_event = event->time_pulses;
00919 } else {
00920 track->next_event_number = -1;
00921 track->time_of_next_event = 0;
00922 #if 0
00923 g_warning("Warning: empty track.");
00924 #endif
00925 }
00926 }
00927 }
00928
00933 int
00934 smf_seek_to_event(smf_t *smf, const smf_event_t *target)
00935 {
00936 smf_event_t *event;
00937
00938 smf_rewind(smf);
00939
00940 #if 0
00941 g_debug("Seeking to event %d, track %d.", target->event_number, target->track->track_number);
00942 #endif
00943
00944 for (;;) {
00945 event = smf_peek_next_event(smf);
00946
00947
00948 assert(event);
00949
00950 if (event != target)
00951 smf_skip_next_event(smf);
00952 else
00953 break;
00954 }
00955
00956 smf->last_seek_position = event->time_seconds;
00957
00958 return (0);
00959 }
00960
00965 int
00966 smf_seek_to_seconds(smf_t *smf, double seconds)
00967 {
00968 smf_event_t *event;
00969
00970 assert(seconds >= 0.0);
00971
00972 if (seconds == smf->last_seek_position) {
00973 #if 0
00974 g_debug("Avoiding seek to %f seconds.", seconds);
00975 #endif
00976 return (0);
00977 }
00978
00979 smf_rewind(smf);
00980
00981 #if 0
00982 g_debug("Seeking to %f seconds.", seconds);
00983 #endif
00984
00985 for (;;) {
00986 event = smf_peek_next_event(smf);
00987
00988 if (event == NULL) {
00989 g_critical("Trying to seek past the end of song.");
00990 return (-1);
00991 }
00992
00993 if (event->time_seconds < seconds)
00994 smf_skip_next_event(smf);
00995 else
00996 break;
00997 }
00998
00999 smf->last_seek_position = seconds;
01000
01001 return (0);
01002 }
01003
01008 int
01009 smf_seek_to_pulses(smf_t *smf, int pulses)
01010 {
01011 smf_event_t *event;
01012
01013 assert(pulses >= 0);
01014
01015 smf_rewind(smf);
01016
01017 #if 0
01018 g_debug("Seeking to %d pulses.", pulses);
01019 #endif
01020
01021 for (;;) {
01022 event = smf_peek_next_event(smf);
01023
01024 if (event == NULL) {
01025 g_critical("Trying to seek past the end of song.");
01026 return (-1);
01027 }
01028
01029 if (event->time_pulses < pulses)
01030 smf_skip_next_event(smf);
01031 else
01032 break;
01033 }
01034
01035 smf->last_seek_position = event->time_seconds;
01036
01037 return (0);
01038 }
01039
01043 int
01044 smf_get_length_pulses(const smf_t *smf)
01045 {
01046 int pulses = 0, i;
01047
01048 for (i = 1; i <= smf->number_of_tracks; i++) {
01049 smf_track_t *track;
01050 smf_event_t *event;
01051
01052 track = smf_get_track_by_number(smf, i);
01053 assert(track);
01054
01055 event = smf_track_get_last_event(track);
01056
01057 if (event == NULL)
01058 continue;
01059
01060 if (event->time_pulses > pulses)
01061 pulses = event->time_pulses;
01062 }
01063
01064 return (pulses);
01065 }
01066
01070 double
01071 smf_get_length_seconds(const smf_t *smf)
01072 {
01073 int i;
01074 double seconds = 0.0;
01075
01076 for (i = 1; i <= smf->number_of_tracks; i++) {
01077 smf_track_t *track;
01078 smf_event_t *event;
01079
01080 track = smf_get_track_by_number(smf, i);
01081 assert(track);
01082
01083 event = smf_track_get_last_event(track);
01084
01085 if (event == NULL)
01086 continue;
01087
01088 if (event->time_seconds > seconds)
01089 seconds = event->time_seconds;
01090 }
01091
01092 return (seconds);
01093 }
01094
01099 int
01100 smf_event_is_last(const smf_event_t *event)
01101 {
01102 if (smf_get_length_pulses(event->track->smf) <= event->time_pulses)
01103 return (1);
01104
01105 return (0);
01106 }
01107
01111 const char *
01112 smf_get_version(void)
01113 {
01114 return (SMF_VERSION);
01115 }
01116