Update Fluidsynth to v2.0.3
[ardour.git] / libs / fluidsynth / src / fluid_midi.c
1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License
7  * as published by the Free Software Foundation; either version 2.1 of
8  * the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA
19  */
20
21 #include "fluid_midi.h"
22 #include "fluid_sys.h"
23 #include "fluid_synth.h"
24 #include "fluid_settings.h"
25
26
27 static int fluid_midi_event_length(unsigned char event);
28 static int fluid_isasciistring(char *s);
29 static long fluid_getlength(unsigned char *s);
30
31
32 /* Read the entire contents of a file into memory, allocating enough memory
33  * for the file, and returning the length and the buffer.
34  * Note: This rewinds the file to the start before reading.
35  * Returns NULL if there was an error reading or allocating memory.
36  */
37 static char *fluid_file_read_full(fluid_file fp, size_t *length);
38 static void fluid_midi_event_set_sysex_LOCAL(fluid_midi_event_t *evt, int type, void *data, int size, int dynamic);
39 static void fluid_midi_event_get_sysex_LOCAL(fluid_midi_event_t *evt, void **data, int *size);
40 #define READ_FULL_INITIAL_BUFLEN 1024
41
42 static fluid_track_t *new_fluid_track(int num);
43 static void delete_fluid_track(fluid_track_t *track);
44 static int fluid_track_set_name(fluid_track_t *track, char *name);
45 static int fluid_track_add_event(fluid_track_t *track, fluid_midi_event_t *evt);
46 static fluid_midi_event_t *fluid_track_next_event(fluid_track_t *track);
47 static int fluid_track_get_duration(fluid_track_t *track);
48 static int fluid_track_reset(fluid_track_t *track);
49
50 static int fluid_track_send_events(fluid_track_t *track,
51                                    fluid_synth_t *synth,
52                                    fluid_player_t *player,
53                                    unsigned int ticks);
54
55
56 static int fluid_player_add_track(fluid_player_t *player, fluid_track_t *track);
57 static int fluid_player_callback(void *data, unsigned int msec);
58 static int fluid_player_reset(fluid_player_t *player);
59 static int fluid_player_load(fluid_player_t *player, fluid_playlist_item *item);
60 static void fluid_player_advancefile(fluid_player_t *player);
61 static void fluid_player_playlist_load(fluid_player_t *player, unsigned int msec);
62
63 static fluid_midi_file *new_fluid_midi_file(const char *buffer, size_t length);
64 static void delete_fluid_midi_file(fluid_midi_file *mf);
65 static int fluid_midi_file_read_mthd(fluid_midi_file *midifile);
66 static int fluid_midi_file_load_tracks(fluid_midi_file *midifile, fluid_player_t *player);
67 static int fluid_midi_file_read_track(fluid_midi_file *mf, fluid_player_t *player, int num);
68 static int fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track);
69 static int fluid_midi_file_read_varlen(fluid_midi_file *mf);
70 static int fluid_midi_file_getc(fluid_midi_file *mf);
71 static int fluid_midi_file_push(fluid_midi_file *mf, int c);
72 static int fluid_midi_file_read(fluid_midi_file *mf, void *buf, int len);
73 static int fluid_midi_file_skip(fluid_midi_file *mf, int len);
74 static int fluid_midi_file_eof(fluid_midi_file *mf);
75 static int fluid_midi_file_read_tracklen(fluid_midi_file *mf);
76 static int fluid_midi_file_eot(fluid_midi_file *mf);
77 static int fluid_midi_file_get_division(fluid_midi_file *midifile);
78
79 #if 0 // disable file I/O with Ardour
80 /***************************************************************
81  *
82  *                      MIDIFILE
83  */
84
85 /**
86  * Check if a file is a MIDI file.
87  * @param filename Path to the file to check
88  * @return TRUE if it could be a MIDI file, FALSE otherwise
89  *
90  * The current implementation only checks for the "MThd" header in the file.
91  * It is useful only to distinguish between SoundFont and MIDI files.
92  */
93 int fluid_is_midifile(const char *filename)
94 {
95     FILE    *fp = FLUID_FOPEN(filename, "rb");
96     uint32_t id;
97     int      retcode = FALSE;
98
99     do
100     {
101         if(fp == NULL)
102         {
103             return retcode;
104         }
105
106         if(FLUID_FREAD(&id, sizeof(id), 1, fp) != 1)
107         {
108             break;
109         }
110
111         retcode = (id == FLUID_FOURCC('M', 'T', 'h', 'd'));
112     }
113     while(0);
114
115     FLUID_FCLOSE(fp);
116
117     return retcode;
118 }
119
120 /**
121  * Return a new MIDI file handle for parsing an already-loaded MIDI file.
122  * @internal
123  * @param buffer Pointer to full contents of MIDI file (borrows the pointer).
124  *  The caller must not free buffer until after the fluid_midi_file is deleted.
125  * @param length Size of the buffer in bytes.
126  * @return New MIDI file handle or NULL on error.
127  */
128 fluid_midi_file *
129 new_fluid_midi_file(const char *buffer, size_t length)
130 {
131     fluid_midi_file *mf;
132
133     mf = FLUID_NEW(fluid_midi_file);
134
135     if(mf == NULL)
136     {
137         FLUID_LOG(FLUID_ERR, "Out of memory");
138         return NULL;
139     }
140
141     FLUID_MEMSET(mf, 0, sizeof(fluid_midi_file));
142
143     mf->c = -1;
144     mf->running_status = -1;
145
146     mf->buffer = buffer;
147     mf->buf_len = length;
148     mf->buf_pos = 0;
149     mf->eof = FALSE;
150
151     if(fluid_midi_file_read_mthd(mf) != FLUID_OK)
152     {
153         FLUID_FREE(mf);
154         return NULL;
155     }
156
157     return mf;
158 }
159
160 static char *
161 fluid_file_read_full(fluid_file fp, size_t *length)
162 {
163     size_t buflen;
164     char *buffer;
165     size_t n;
166
167     /* Work out the length of the file in advance */
168     if(FLUID_FSEEK(fp, 0, SEEK_END) != 0)
169     {
170         FLUID_LOG(FLUID_ERR, "File load: Could not seek within file");
171         return NULL;
172     }
173
174     buflen = ftell(fp);
175
176     if(FLUID_FSEEK(fp, 0, SEEK_SET) != 0)
177     {
178         FLUID_LOG(FLUID_ERR, "File load: Could not seek within file");
179         return NULL;
180     }
181
182     FLUID_LOG(FLUID_DBG, "File load: Allocating %d bytes", buflen);
183     buffer = FLUID_MALLOC(buflen);
184
185     if(buffer == NULL)
186     {
187         FLUID_LOG(FLUID_PANIC, "Out of memory");
188         return NULL;
189     }
190
191     n = FLUID_FREAD(buffer, 1, buflen, fp);
192
193     if(n != buflen)
194     {
195         FLUID_LOG(FLUID_ERR, "Only read %d bytes; expected %d", n,
196                   buflen);
197         FLUID_FREE(buffer);
198         return NULL;
199     };
200
201     *length = n;
202
203     return buffer;
204 }
205
206 /**
207  * Delete a MIDI file handle.
208  * @internal
209  * @param mf MIDI file handle to close and free.
210  */
211 void
212 delete_fluid_midi_file(fluid_midi_file *mf)
213 {
214     fluid_return_if_fail(mf != NULL);
215
216     FLUID_FREE(mf);
217 }
218
219 /*
220  * Gets the next byte in a MIDI file, taking into account previous running status.
221  *
222  * returns -1 if EOF or read error
223  */
224 int
225 fluid_midi_file_getc(fluid_midi_file *mf)
226 {
227     unsigned char c;
228
229     if(mf->c >= 0)
230     {
231         c = mf->c;
232         mf->c = -1;
233     }
234     else
235     {
236         if(mf->buf_pos >= mf->buf_len)
237         {
238             mf->eof = TRUE;
239             return -1;
240         }
241
242         c = mf->buffer[mf->buf_pos++];
243         mf->trackpos++;
244     }
245
246     return (int) c;
247 }
248
249 /*
250  * Saves a byte to be returned the next time fluid_midi_file_getc() is called,
251  * when it is necessary according to running status.
252  */
253 int
254 fluid_midi_file_push(fluid_midi_file *mf, int c)
255 {
256     mf->c = c;
257     return FLUID_OK;
258 }
259
260 /*
261  * fluid_midi_file_read
262  */
263 int
264 fluid_midi_file_read(fluid_midi_file *mf, void *buf, int len)
265 {
266     int num = len < mf->buf_len - mf->buf_pos
267               ? len : mf->buf_len - mf->buf_pos;
268
269     if(num != len)
270     {
271         mf->eof = TRUE;
272     }
273
274     if(num < 0)
275     {
276         num = 0;
277     }
278
279     /* Note: Read bytes, even if there aren't enough, but only increment
280      * trackpos if successful (emulates old behaviour of fluid_midi_file_read)
281      */
282     FLUID_MEMCPY(buf, mf->buffer + mf->buf_pos, num);
283     mf->buf_pos += num;
284
285     if(num == len)
286     {
287         mf->trackpos += num;
288     }
289
290 #if DEBUG
291     else
292     {
293         FLUID_LOG(FLUID_DBG, "Could not read the requested number of bytes");
294     }
295
296 #endif
297     return (num != len) ? FLUID_FAILED : FLUID_OK;
298 }
299
300 /*
301  * fluid_midi_file_skip
302  */
303 int
304 fluid_midi_file_skip(fluid_midi_file *mf, int skip)
305 {
306     int new_pos = mf->buf_pos + skip;
307
308     /* Mimic the behaviour of fseek: Error to seek past the start of file, but
309      * OK to seek past end (this just puts it into the EOF state). */
310     if(new_pos < 0)
311     {
312         FLUID_LOG(FLUID_ERR, "Failed to seek position in file");
313         return FLUID_FAILED;
314     }
315
316     /* Clear the EOF flag, even if moved past the end of the file (this is
317      * consistent with the behaviour of fseek). */
318     mf->eof = FALSE;
319     mf->buf_pos = new_pos;
320     return FLUID_OK;
321 }
322
323 /*
324  * fluid_midi_file_eof
325  */
326 int fluid_midi_file_eof(fluid_midi_file *mf)
327 {
328     /* Note: This does not simply test whether the file read pointer is past
329      * the end of the file. It mimics the behaviour of feof by actually
330      * testing the stateful EOF condition, which is set to TRUE if getc or
331      * fread have attempted to read past the end (but not if they have
332      * precisely reached the end), but reset to FALSE upon a successful seek.
333      */
334     return mf->eof;
335 }
336
337 /*
338  * fluid_midi_file_read_mthd
339  */
340 int
341 fluid_midi_file_read_mthd(fluid_midi_file *mf)
342 {
343     char mthd[14];
344
345     if(fluid_midi_file_read(mf, mthd, sizeof(mthd)) != FLUID_OK)
346     {
347         return FLUID_FAILED;
348     }
349
350     if((FLUID_STRNCMP(mthd, "MThd", 4) != 0) || (mthd[7] != 6)
351             || (mthd[9] > 2))
352     {
353         FLUID_LOG(FLUID_ERR,
354                   "Doesn't look like a MIDI file: invalid MThd header");
355         return FLUID_FAILED;
356     }
357
358     mf->type = mthd[9];
359     mf->ntracks = (unsigned) mthd[11];
360     mf->ntracks += (unsigned int)(mthd[10]) << 16;
361
362     if((signed char)mthd[12] < 0)
363     {
364         mf->uses_smpte = 1;
365         mf->smpte_fps = -(signed char)mthd[12];
366         mf->smpte_res = (unsigned) mthd[13];
367         FLUID_LOG(FLUID_ERR, "File uses SMPTE timing -- Not implemented yet");
368         return FLUID_FAILED;
369     }
370     else
371     {
372         mf->uses_smpte = 0;
373         mf->division = ((unsigned)mthd[12] << 8) | ((unsigned)mthd[13] & 0xff);
374         FLUID_LOG(FLUID_DBG, "Division=%d", mf->division);
375     }
376
377     return FLUID_OK;
378 }
379
380 /*
381  * fluid_midi_file_load_tracks
382  */
383 int
384 fluid_midi_file_load_tracks(fluid_midi_file *mf, fluid_player_t *player)
385 {
386     int i;
387
388     for(i = 0; i < mf->ntracks; i++)
389     {
390         if(fluid_midi_file_read_track(mf, player, i) != FLUID_OK)
391         {
392             return FLUID_FAILED;
393         }
394     }
395
396     return FLUID_OK;
397 }
398
399 /*
400  * fluid_isasciistring
401  */
402 int
403 fluid_isasciistring(char *s)
404 {
405     /* From ctype.h */
406 #define fluid_isascii(c)    (((c) & ~0x7f) == 0)
407
408     int i;
409     int len = (int) FLUID_STRLEN(s);
410
411     for(i = 0; i < len; i++)
412     {
413         if(!fluid_isascii(s[i]))
414         {
415             return 0;
416         }
417     }
418
419     return 1;
420
421 #undef fluid_isascii
422 }
423
424 /*
425  * fluid_getlength
426  */
427 long
428 fluid_getlength(unsigned char *s)
429 {
430     long i = 0;
431     i = s[3] | (s[2] << 8) | (s[1] << 16) | (s[0] << 24);
432     return i;
433 }
434
435 /*
436  * fluid_midi_file_read_tracklen
437  */
438 int
439 fluid_midi_file_read_tracklen(fluid_midi_file *mf)
440 {
441     unsigned char length[5];
442
443     if(fluid_midi_file_read(mf, length, 4) != FLUID_OK)
444     {
445         return FLUID_FAILED;
446     }
447
448     mf->tracklen = fluid_getlength(length);
449     mf->trackpos = 0;
450     mf->eot = 0;
451     return FLUID_OK;
452 }
453
454 /*
455  * fluid_midi_file_eot
456  */
457 int
458 fluid_midi_file_eot(fluid_midi_file *mf)
459 {
460 #if DEBUG
461
462     if(mf->trackpos > mf->tracklen)
463     {
464         printf("track overrun: %d > %d\n", mf->trackpos, mf->tracklen);
465     }
466
467 #endif
468     return mf->eot || (mf->trackpos >= mf->tracklen);
469 }
470
471 /*
472  * fluid_midi_file_read_track
473  */
474 int
475 fluid_midi_file_read_track(fluid_midi_file *mf, fluid_player_t *player, int num)
476 {
477     fluid_track_t *track;
478     unsigned char id[5], length[5];
479     int found_track = 0;
480     int skip;
481
482     if(fluid_midi_file_read(mf, id, 4) != FLUID_OK)
483     {
484         return FLUID_FAILED;
485     }
486
487     id[4] = '\0';
488     mf->dtime = 0;
489
490     while(!found_track)
491     {
492
493         if(fluid_isasciistring((char *) id) == 0)
494         {
495             FLUID_LOG(FLUID_ERR,
496                       "An non-ascii track header found, corrupt file");
497             return FLUID_FAILED;
498
499         }
500         else if(FLUID_STRCMP((char *) id, "MTrk") == 0)
501         {
502
503             found_track = 1;
504
505             if(fluid_midi_file_read_tracklen(mf) != FLUID_OK)
506             {
507                 return FLUID_FAILED;
508             }
509
510             track = new_fluid_track(num);
511
512             if(track == NULL)
513             {
514                 FLUID_LOG(FLUID_ERR, "Out of memory");
515                 return FLUID_FAILED;
516             }
517
518             while(!fluid_midi_file_eot(mf))
519             {
520                 if(fluid_midi_file_read_event(mf, track) != FLUID_OK)
521                 {
522                     delete_fluid_track(track);
523                     return FLUID_FAILED;
524                 }
525             }
526
527             /* Skip remaining track data, if any */
528             if(mf->trackpos < mf->tracklen)
529             {
530                 if(fluid_midi_file_skip(mf, mf->tracklen - mf->trackpos) != FLUID_OK)
531                 {
532                     delete_fluid_track(track);
533                     return FLUID_FAILED;
534                 }
535             }
536
537             if(fluid_player_add_track(player, track) != FLUID_OK)
538             {
539                 delete_fluid_track(track);
540                 return FLUID_FAILED;
541             }
542
543         }
544         else
545         {
546             found_track = 0;
547
548             if(fluid_midi_file_read(mf, length, 4) != FLUID_OK)
549             {
550                 return FLUID_FAILED;
551             }
552
553             skip = fluid_getlength(length);
554
555             /* fseek(mf->fp, skip, SEEK_CUR); */
556             if(fluid_midi_file_skip(mf, skip) != FLUID_OK)
557             {
558                 return FLUID_FAILED;
559             }
560         }
561     }
562
563     if(fluid_midi_file_eof(mf))
564     {
565         FLUID_LOG(FLUID_ERR, "Unexpected end of file");
566         return FLUID_FAILED;
567     }
568
569     return FLUID_OK;
570 }
571
572 /*
573  * fluid_midi_file_read_varlen
574  */
575 int
576 fluid_midi_file_read_varlen(fluid_midi_file *mf)
577 {
578     int i;
579     int c;
580     mf->varlen = 0;
581
582     for(i = 0;; i++)
583     {
584         if(i == 4)
585         {
586             FLUID_LOG(FLUID_ERR, "Invalid variable length number");
587             return FLUID_FAILED;
588         }
589
590         c = fluid_midi_file_getc(mf);
591
592         if(c < 0)
593         {
594             FLUID_LOG(FLUID_ERR, "Unexpected end of file");
595             return FLUID_FAILED;
596         }
597
598         if(c & 0x80)
599         {
600             mf->varlen |= (int)(c & 0x7F);
601             mf->varlen <<= 7;
602         }
603         else
604         {
605             mf->varlen += c;
606             break;
607         }
608     }
609
610     return FLUID_OK;
611 }
612
613 /*
614  * fluid_midi_file_read_event
615  */
616 int
617 fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track)
618 {
619     int status;
620     int type;
621     int tempo;
622     unsigned char *metadata = NULL;
623     unsigned char *dyn_buf = NULL;
624     unsigned char static_buf[256];
625     int nominator, denominator, clocks, notes;
626     fluid_midi_event_t *evt;
627     int channel = 0;
628     int param1 = 0;
629     int param2 = 0;
630     int size;
631
632     /* read the delta-time of the event */
633     if(fluid_midi_file_read_varlen(mf) != FLUID_OK)
634     {
635         return FLUID_FAILED;
636     }
637
638     mf->dtime += mf->varlen;
639
640     /* read the status byte */
641     status = fluid_midi_file_getc(mf);
642
643     if(status < 0)
644     {
645         FLUID_LOG(FLUID_ERR, "Unexpected end of file");
646         return FLUID_FAILED;
647     }
648
649     /* not a valid status byte: use the running status instead */
650     if((status & 0x80) == 0)
651     {
652         if((mf->running_status & 0x80) == 0)
653         {
654             FLUID_LOG(FLUID_ERR, "Undefined status and invalid running status");
655             return FLUID_FAILED;
656         }
657
658         fluid_midi_file_push(mf, status);
659         status = mf->running_status;
660     }
661
662     /* check what message we have */
663
664     mf->running_status = status;
665
666     if(status == MIDI_SYSEX)    /* system exclusif */
667     {
668         /* read the length of the message */
669         if(fluid_midi_file_read_varlen(mf) != FLUID_OK)
670         {
671             return FLUID_FAILED;
672         }
673
674         if(mf->varlen)
675         {
676             FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__,
677                       __LINE__, mf->varlen);
678             metadata = FLUID_MALLOC(mf->varlen + 1);
679
680             if(metadata == NULL)
681             {
682                 FLUID_LOG(FLUID_PANIC, "Out of memory");
683                 return FLUID_FAILED;
684             }
685
686             /* read the data of the message */
687             if(fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK)
688             {
689                 FLUID_FREE(metadata);
690                 return FLUID_FAILED;
691             }
692
693             evt = new_fluid_midi_event();
694
695             if(evt == NULL)
696             {
697                 FLUID_LOG(FLUID_ERR, "Out of memory");
698                 FLUID_FREE(metadata);
699                 return FLUID_FAILED;
700             }
701
702             evt->dtime = mf->dtime;
703             size = mf->varlen;
704
705             if(metadata[mf->varlen - 1] == MIDI_EOX)
706             {
707                 size--;
708             }
709
710             /* Add SYSEX event and indicate that its dynamically allocated and should be freed with event */
711             fluid_midi_event_set_sysex(evt, metadata, size, TRUE);
712             fluid_track_add_event(track, evt);
713             mf->dtime = 0;
714         }
715
716         return FLUID_OK;
717
718     }
719     else if(status == MIDI_META_EVENT)      /* meta events */
720     {
721
722         int result = FLUID_OK;
723
724         /* get the type of the meta message */
725         type = fluid_midi_file_getc(mf);
726
727         if(type < 0)
728         {
729             FLUID_LOG(FLUID_ERR, "Unexpected end of file");
730             return FLUID_FAILED;
731         }
732
733         /* get the length of the data part */
734         if(fluid_midi_file_read_varlen(mf) != FLUID_OK)
735         {
736             return FLUID_FAILED;
737         }
738
739         if(mf->varlen < 255)
740         {
741             metadata = &static_buf[0];
742         }
743         else
744         {
745             FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__,
746                       __LINE__, mf->varlen);
747             dyn_buf = FLUID_MALLOC(mf->varlen + 1);
748
749             if(dyn_buf == NULL)
750             {
751                 FLUID_LOG(FLUID_PANIC, "Out of memory");
752                 return FLUID_FAILED;
753             }
754
755             metadata = dyn_buf;
756         }
757
758         /* read the data */
759         if(mf->varlen)
760         {
761             if(fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK)
762             {
763                 if(dyn_buf)
764                 {
765                     FLUID_FREE(dyn_buf);
766                 }
767
768                 return FLUID_FAILED;
769             }
770         }
771
772         /* handle meta data */
773         switch(type)
774         {
775
776         case MIDI_COPYRIGHT:
777             metadata[mf->varlen] = 0;
778             break;
779
780         case MIDI_TRACK_NAME:
781             metadata[mf->varlen] = 0;
782             fluid_track_set_name(track, (char *) metadata);
783             break;
784
785         case MIDI_INST_NAME:
786             metadata[mf->varlen] = 0;
787             break;
788
789         case MIDI_LYRIC:
790         case MIDI_TEXT:
791         {
792             void *tmp;
793             int size = mf->varlen + 1;
794
795             /* NULL terminate strings for safety */
796             metadata[size - 1] = '\0';
797
798             evt = new_fluid_midi_event();
799
800             if(evt == NULL)
801             {
802                 FLUID_LOG(FLUID_ERR, "Out of memory");
803                 result = FLUID_FAILED;
804                 break;
805             }
806
807             evt->dtime = mf->dtime;
808
809             tmp = FLUID_MALLOC(size);
810
811             if(tmp == NULL)
812             {
813                 FLUID_LOG(FLUID_PANIC, "Out of memory");
814                 delete_fluid_midi_event(evt);
815                 evt = NULL;
816                 result = FLUID_FAILED;
817                 break;
818             }
819
820             FLUID_MEMCPY(tmp, metadata, size);
821
822             fluid_midi_event_set_sysex_LOCAL(evt, type, tmp, size, TRUE);
823             fluid_track_add_event(track, evt);
824             mf->dtime = 0;
825         }
826         break;
827
828         case MIDI_MARKER:
829             break;
830
831         case MIDI_CUE_POINT:
832             break; /* don't care much for text events */
833
834         case MIDI_EOT:
835             if(mf->varlen != 0)
836             {
837                 FLUID_LOG(FLUID_ERR, "Invalid length for EndOfTrack event");
838                 result = FLUID_FAILED;
839                 break;
840             }
841
842             mf->eot = 1;
843             evt = new_fluid_midi_event();
844
845             if(evt == NULL)
846             {
847                 FLUID_LOG(FLUID_ERR, "Out of memory");
848                 result = FLUID_FAILED;
849                 break;
850             }
851
852             evt->dtime = mf->dtime;
853             evt->type = MIDI_EOT;
854             fluid_track_add_event(track, evt);
855             mf->dtime = 0;
856             break;
857
858         case MIDI_SET_TEMPO:
859             if(mf->varlen != 3)
860             {
861                 FLUID_LOG(FLUID_ERR,
862                           "Invalid length for SetTempo meta event");
863                 result = FLUID_FAILED;
864                 break;
865             }
866
867             tempo = (metadata[0] << 16) + (metadata[1] << 8) + metadata[2];
868             evt = new_fluid_midi_event();
869
870             if(evt == NULL)
871             {
872                 FLUID_LOG(FLUID_ERR, "Out of memory");
873                 result = FLUID_FAILED;
874                 break;
875             }
876
877             evt->dtime = mf->dtime;
878             evt->type = MIDI_SET_TEMPO;
879             evt->channel = 0;
880             evt->param1 = tempo;
881             evt->param2 = 0;
882             fluid_track_add_event(track, evt);
883             mf->dtime = 0;
884             break;
885
886         case MIDI_SMPTE_OFFSET:
887             if(mf->varlen != 5)
888             {
889                 FLUID_LOG(FLUID_ERR,
890                           "Invalid length for SMPTE Offset meta event");
891                 result = FLUID_FAILED;
892                 break;
893             }
894
895             break; /* we don't use smtp */
896
897         case MIDI_TIME_SIGNATURE:
898             if(mf->varlen != 4)
899             {
900                 FLUID_LOG(FLUID_ERR,
901                           "Invalid length for TimeSignature meta event");
902                 result = FLUID_FAILED;
903                 break;
904             }
905
906             nominator = metadata[0];
907             denominator = pow(2.0, (double) metadata[1]);
908             clocks = metadata[2];
909             notes = metadata[3];
910
911             FLUID_LOG(FLUID_DBG,
912                       "signature=%d/%d, metronome=%d, 32nd-notes=%d",
913                       nominator, denominator, clocks, notes);
914
915             break;
916
917         case MIDI_KEY_SIGNATURE:
918             if(mf->varlen != 2)
919             {
920                 FLUID_LOG(FLUID_ERR,
921                           "Invalid length for KeySignature meta event");
922                 result = FLUID_FAILED;
923                 break;
924             }
925
926             /* We don't care about key signatures anyway */
927             /* sf = metadata[0];
928             mi = metadata[1]; */
929             break;
930
931         case MIDI_SEQUENCER_EVENT:
932             break;
933
934         default:
935             break;
936         }
937
938         if(dyn_buf)
939         {
940             FLUID_LOG(FLUID_DBG, "%s: %d: free metadata", __FILE__, __LINE__);
941             FLUID_FREE(dyn_buf);
942         }
943
944         return result;
945
946     }
947     else     /* channel messages */
948     {
949
950         type = status & 0xf0;
951         channel = status & 0x0f;
952
953         /* all channel message have at least 1 byte of associated data */
954         if((param1 = fluid_midi_file_getc(mf)) < 0)
955         {
956             FLUID_LOG(FLUID_ERR, "Unexpected end of file");
957             return FLUID_FAILED;
958         }
959
960         switch(type)
961         {
962
963         case NOTE_ON:
964             if((param2 = fluid_midi_file_getc(mf)) < 0)
965             {
966                 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
967                 return FLUID_FAILED;
968             }
969
970             break;
971
972         case NOTE_OFF:
973             if((param2 = fluid_midi_file_getc(mf)) < 0)
974             {
975                 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
976                 return FLUID_FAILED;
977             }
978
979             break;
980
981         case KEY_PRESSURE:
982             if((param2 = fluid_midi_file_getc(mf)) < 0)
983             {
984                 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
985                 return FLUID_FAILED;
986             }
987
988             break;
989
990         case CONTROL_CHANGE:
991             if((param2 = fluid_midi_file_getc(mf)) < 0)
992             {
993                 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
994                 return FLUID_FAILED;
995             }
996
997             break;
998
999         case PROGRAM_CHANGE:
1000             break;
1001
1002         case CHANNEL_PRESSURE:
1003             break;
1004
1005         case PITCH_BEND:
1006             if((param2 = fluid_midi_file_getc(mf)) < 0)
1007             {
1008                 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
1009                 return FLUID_FAILED;
1010             }
1011
1012             param1 = ((param2 & 0x7f) << 7) | (param1 & 0x7f);
1013             param2 = 0;
1014             break;
1015
1016         default:
1017             /* Can't possibly happen !? */
1018             FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event");
1019             return FLUID_FAILED;
1020         }
1021
1022         evt = new_fluid_midi_event();
1023
1024         if(evt == NULL)
1025         {
1026             FLUID_LOG(FLUID_ERR, "Out of memory");
1027             return FLUID_FAILED;
1028         }
1029
1030         evt->dtime = mf->dtime;
1031         evt->type = type;
1032         evt->channel = channel;
1033         evt->param1 = param1;
1034         evt->param2 = param2;
1035         fluid_track_add_event(track, evt);
1036         mf->dtime = 0;
1037     }
1038
1039     return FLUID_OK;
1040 }
1041
1042 /*
1043  * fluid_midi_file_get_division
1044  */
1045 int
1046 fluid_midi_file_get_division(fluid_midi_file *midifile)
1047 {
1048     return midifile->division;
1049 }
1050 #endif
1051
1052 /******************************************************
1053  *
1054  *     fluid_track_t
1055  */
1056
1057 /**
1058  * Create a MIDI event structure.
1059  * @return New MIDI event structure or NULL when out of memory.
1060  */
1061 fluid_midi_event_t *
1062 new_fluid_midi_event()
1063 {
1064     fluid_midi_event_t *evt;
1065     evt = FLUID_NEW(fluid_midi_event_t);
1066
1067     if(evt == NULL)
1068     {
1069         FLUID_LOG(FLUID_ERR, "Out of memory");
1070         return NULL;
1071     }
1072
1073     evt->dtime = 0;
1074     evt->type = 0;
1075     evt->channel = 0;
1076     evt->param1 = 0;
1077     evt->param2 = 0;
1078     evt->next = NULL;
1079     evt->paramptr = NULL;
1080     return evt;
1081 }
1082
1083 /**
1084  * Delete MIDI event structure.
1085  * @param evt MIDI event structure
1086  */
1087 void
1088 delete_fluid_midi_event(fluid_midi_event_t *evt)
1089 {
1090     fluid_midi_event_t *temp;
1091     fluid_return_if_fail(evt != NULL);
1092
1093     while(evt)
1094     {
1095         temp = evt->next;
1096
1097         /* Dynamic SYSEX event? - free (param2 indicates if dynamic) */
1098         if((evt->type == MIDI_SYSEX || (evt-> type == MIDI_TEXT) || (evt->type == MIDI_LYRIC)) &&
1099                 evt->paramptr && evt->param2)
1100         {
1101             FLUID_FREE(evt->paramptr);
1102         }
1103
1104         FLUID_FREE(evt);
1105         evt = temp;
1106     }
1107 }
1108
1109 /**
1110  * Get the event type field of a MIDI event structure.
1111  * @param evt MIDI event structure
1112  * @return Event type field (MIDI status byte without channel)
1113  */
1114 int
1115 fluid_midi_event_get_type(fluid_midi_event_t *evt)
1116 {
1117     return evt->type;
1118 }
1119
1120 /**
1121  * Set the event type field of a MIDI event structure.
1122  * @param evt MIDI event structure
1123  * @param type Event type field (MIDI status byte without channel)
1124  * @return Always returns #FLUID_OK
1125  */
1126 int
1127 fluid_midi_event_set_type(fluid_midi_event_t *evt, int type)
1128 {
1129     evt->type = type;
1130     return FLUID_OK;
1131 }
1132
1133 /**
1134  * Get the channel field of a MIDI event structure.
1135  * @param evt MIDI event structure
1136  * @return Channel field
1137  */
1138 int
1139 fluid_midi_event_get_channel(fluid_midi_event_t *evt)
1140 {
1141     return evt->channel;
1142 }
1143
1144 /**
1145  * Set the channel field of a MIDI event structure.
1146  * @param evt MIDI event structure
1147  * @param chan MIDI channel field
1148  * @return Always returns #FLUID_OK
1149  */
1150 int
1151 fluid_midi_event_set_channel(fluid_midi_event_t *evt, int chan)
1152 {
1153     evt->channel = chan;
1154     return FLUID_OK;
1155 }
1156
1157 /**
1158  * Get the key field of a MIDI event structure.
1159  * @param evt MIDI event structure
1160  * @return MIDI note number (0-127)
1161  */
1162 int
1163 fluid_midi_event_get_key(fluid_midi_event_t *evt)
1164 {
1165     return evt->param1;
1166 }
1167
1168 /**
1169  * Set the key field of a MIDI event structure.
1170  * @param evt MIDI event structure
1171  * @param v MIDI note number (0-127)
1172  * @return Always returns #FLUID_OK
1173  */
1174 int
1175 fluid_midi_event_set_key(fluid_midi_event_t *evt, int v)
1176 {
1177     evt->param1 = v;
1178     return FLUID_OK;
1179 }
1180
1181 /**
1182  * Get the velocity field of a MIDI event structure.
1183  * @param evt MIDI event structure
1184  * @return MIDI velocity number (0-127)
1185  */
1186 int
1187 fluid_midi_event_get_velocity(fluid_midi_event_t *evt)
1188 {
1189     return evt->param2;
1190 }
1191
1192 /**
1193  * Set the velocity field of a MIDI event structure.
1194  * @param evt MIDI event structure
1195  * @param v MIDI velocity value
1196  * @return Always returns #FLUID_OK
1197  */
1198 int
1199 fluid_midi_event_set_velocity(fluid_midi_event_t *evt, int v)
1200 {
1201     evt->param2 = v;
1202     return FLUID_OK;
1203 }
1204
1205 /**
1206  * Get the control number of a MIDI event structure.
1207  * @param evt MIDI event structure
1208  * @return MIDI control number
1209  */
1210 int
1211 fluid_midi_event_get_control(fluid_midi_event_t *evt)
1212 {
1213     return evt->param1;
1214 }
1215
1216 /**
1217  * Set the control field of a MIDI event structure.
1218  * @param evt MIDI event structure
1219  * @param v MIDI control number
1220  * @return Always returns #FLUID_OK
1221  */
1222 int
1223 fluid_midi_event_set_control(fluid_midi_event_t *evt, int v)
1224 {
1225     evt->param1 = v;
1226     return FLUID_OK;
1227 }
1228
1229 /**
1230  * Get the value field from a MIDI event structure.
1231  * @param evt MIDI event structure
1232  * @return Value field
1233  */
1234 int
1235 fluid_midi_event_get_value(fluid_midi_event_t *evt)
1236 {
1237     return evt->param2;
1238 }
1239
1240 /**
1241  * Set the value field of a MIDI event structure.
1242  * @param evt MIDI event structure
1243  * @param v Value to assign
1244  * @return Always returns #FLUID_OK
1245  */
1246 int
1247 fluid_midi_event_set_value(fluid_midi_event_t *evt, int v)
1248 {
1249     evt->param2 = v;
1250     return FLUID_OK;
1251 }
1252
1253 /**
1254  * Get the program field of a MIDI event structure.
1255  * @param evt MIDI event structure
1256  * @return MIDI program number (0-127)
1257  */
1258 int
1259 fluid_midi_event_get_program(fluid_midi_event_t *evt)
1260 {
1261     return evt->param1;
1262 }
1263
1264 /**
1265  * Set the program field of a MIDI event structure.
1266  * @param evt MIDI event structure
1267  * @param val MIDI program number (0-127)
1268  * @return Always returns #FLUID_OK
1269  */
1270 int
1271 fluid_midi_event_set_program(fluid_midi_event_t *evt, int val)
1272 {
1273     evt->param1 = val;
1274     return FLUID_OK;
1275 }
1276
1277 /**
1278  * Get the pitch field of a MIDI event structure.
1279  * @param evt MIDI event structure
1280  * @return Pitch value (14 bit value, 0-16383, 8192 is center)
1281  */
1282 int
1283 fluid_midi_event_get_pitch(fluid_midi_event_t *evt)
1284 {
1285     return evt->param1;
1286 }
1287
1288 /**
1289  * Set the pitch field of a MIDI event structure.
1290  * @param evt MIDI event structure
1291  * @param val Pitch value (14 bit value, 0-16383, 8192 is center)
1292  * @return Always returns FLUID_OK
1293  */
1294 int
1295 fluid_midi_event_set_pitch(fluid_midi_event_t *evt, int val)
1296 {
1297     evt->param1 = val;
1298     return FLUID_OK;
1299 }
1300
1301 /**
1302  * Assign sysex data to a MIDI event structure.
1303  * @param evt MIDI event structure
1304  * @param data Pointer to SYSEX data
1305  * @param size Size of SYSEX data in bytes
1306  * @param dynamic TRUE if the SYSEX data has been dynamically allocated and
1307  *   should be freed when the event is freed (only applies if event gets destroyed
1308  *   with delete_fluid_midi_event())
1309  * @return Always returns #FLUID_OK
1310  */
1311 int
1312 fluid_midi_event_set_sysex(fluid_midi_event_t *evt, void *data, int size, int dynamic)
1313 {
1314     fluid_midi_event_set_sysex_LOCAL(evt, MIDI_SYSEX, data, size, dynamic);
1315     return FLUID_OK;
1316 }
1317
1318 /**
1319  * Assign text data to a MIDI event structure.
1320  * @param evt MIDI event structure
1321  * @param data Pointer to text data
1322  * @param size Size of text data in bytes
1323  * @param dynamic TRUE if the data has been dynamically allocated and
1324  *   should be freed when the event is freed via delete_fluid_midi_event()
1325  * @return Always returns #FLUID_OK
1326  *
1327  * @since 2.0.0
1328  */
1329 int
1330 fluid_midi_event_set_text(fluid_midi_event_t *evt, void *data, int size, int dynamic)
1331 {
1332     fluid_midi_event_set_sysex_LOCAL(evt, MIDI_TEXT, data, size, dynamic);
1333     return FLUID_OK;
1334 }
1335
1336 /**
1337  * Get the text of a MIDI event structure.
1338  * @param evt MIDI event structure
1339  * @param data Pointer to return text data on.
1340  * @param size Pointer to return text size on.
1341  * @return Returns #FLUID_OK if \p data and \p size previously set by
1342  * fluid_midi_event_set_text() have been successfully retrieved.
1343  * Else #FLUID_FAILED is returned and \p data and \p size are not changed.
1344  * @since 2.0.3
1345  */
1346 int fluid_midi_event_get_text(fluid_midi_event_t *evt, void **data, int *size)
1347 {
1348     fluid_return_val_if_fail(evt != NULL, FLUID_FAILED);
1349     fluid_return_val_if_fail(evt->type == MIDI_TEXT, FLUID_FAILED);
1350
1351     fluid_midi_event_get_sysex_LOCAL(evt, data, size);
1352     return FLUID_OK;
1353 }
1354
1355 /**
1356  * Assign lyric data to a MIDI event structure.
1357  * @param evt MIDI event structure
1358  * @param data Pointer to lyric data
1359  * @param size Size of lyric data in bytes
1360  * @param dynamic TRUE if the data has been dynamically allocated and
1361  *   should be freed when the event is freed via delete_fluid_midi_event()
1362  * @return Always returns #FLUID_OK
1363  *
1364  * @since 2.0.0
1365  */
1366 int
1367 fluid_midi_event_set_lyrics(fluid_midi_event_t *evt, void *data, int size, int dynamic)
1368 {
1369     fluid_midi_event_set_sysex_LOCAL(evt, MIDI_LYRIC, data, size, dynamic);
1370     return FLUID_OK;
1371 }
1372
1373 /**
1374  * Get the lyric of a MIDI event structure.
1375  * @param evt MIDI event structure
1376  * @param data Pointer to return lyric data on.
1377  * @param size Pointer to return lyric size on.
1378  * @return Returns #FLUID_OK if \p data and \p size previously set by
1379  * fluid_midi_event_set_lyrics() have been successfully retrieved.
1380  * Else #FLUID_FAILED is returned and \p data and \p size are not changed.
1381  * @since 2.0.3
1382  */
1383 int fluid_midi_event_get_lyrics(fluid_midi_event_t *evt, void **data, int *size)
1384 {
1385     fluid_return_val_if_fail(evt != NULL, FLUID_FAILED);
1386     fluid_return_val_if_fail(evt->type == MIDI_LYRIC, FLUID_FAILED);
1387
1388     fluid_midi_event_get_sysex_LOCAL(evt, data, size);
1389     return FLUID_OK;
1390 }
1391
1392 static void fluid_midi_event_set_sysex_LOCAL(fluid_midi_event_t *evt, int type, void *data, int size, int dynamic)
1393 {
1394     evt->type = type;
1395     evt->paramptr = data;
1396     evt->param1 = size;
1397     evt->param2 = dynamic;
1398 }
1399
1400 static void fluid_midi_event_get_sysex_LOCAL(fluid_midi_event_t *evt, void **data, int *size)
1401 {
1402     if(data)
1403     {
1404         *data = evt->paramptr;
1405     }
1406
1407     if(size)
1408     {
1409         *size = evt->param1;
1410     }
1411 }
1412
1413 /******************************************************
1414  *
1415  *     fluid_track_t
1416  */
1417 #if 0 // disable fluid file player in Ardour
1418 /*
1419  * new_fluid_track
1420  */
1421 fluid_track_t *
1422 new_fluid_track(int num)
1423 {
1424     fluid_track_t *track;
1425     track = FLUID_NEW(fluid_track_t);
1426
1427     if(track == NULL)
1428     {
1429         return NULL;
1430     }
1431
1432     track->name = NULL;
1433     track->num = num;
1434     track->first = NULL;
1435     track->cur = NULL;
1436     track->last = NULL;
1437     track->ticks = 0;
1438     return track;
1439 }
1440
1441 /*
1442  * delete_fluid_track
1443  */
1444 void
1445 delete_fluid_track(fluid_track_t *track)
1446 {
1447     fluid_return_if_fail(track != NULL);
1448
1449     FLUID_FREE(track->name);
1450     delete_fluid_midi_event(track->first);
1451     FLUID_FREE(track);
1452 }
1453
1454 /*
1455  * fluid_track_set_name
1456  */
1457 int
1458 fluid_track_set_name(fluid_track_t *track, char *name)
1459 {
1460     int len;
1461
1462     if(track->name != NULL)
1463     {
1464         FLUID_FREE(track->name);
1465     }
1466
1467     if(name == NULL)
1468     {
1469         track->name = NULL;
1470         return FLUID_OK;
1471     }
1472
1473     len = FLUID_STRLEN(name);
1474     track->name = FLUID_MALLOC(len + 1);
1475
1476     if(track->name == NULL)
1477     {
1478         FLUID_LOG(FLUID_ERR, "Out of memory");
1479         return FLUID_FAILED;
1480     }
1481
1482     FLUID_STRCPY(track->name, name);
1483     return FLUID_OK;
1484 }
1485
1486 /*
1487  * fluid_track_get_duration
1488  */
1489 int
1490 fluid_track_get_duration(fluid_track_t *track)
1491 {
1492     int time = 0;
1493     fluid_midi_event_t *evt = track->first;
1494
1495     while(evt != NULL)
1496     {
1497         time += evt->dtime;
1498         evt = evt->next;
1499     }
1500
1501     return time;
1502 }
1503
1504 /*
1505  * fluid_track_add_event
1506  */
1507 int
1508 fluid_track_add_event(fluid_track_t *track, fluid_midi_event_t *evt)
1509 {
1510     evt->next = NULL;
1511
1512     if(track->first == NULL)
1513     {
1514         track->first = evt;
1515         track->cur = evt;
1516         track->last = evt;
1517     }
1518     else
1519     {
1520         track->last->next = evt;
1521         track->last = evt;
1522     }
1523
1524     return FLUID_OK;
1525 }
1526
1527 /*
1528  * fluid_track_next_event
1529  */
1530 fluid_midi_event_t *
1531 fluid_track_next_event(fluid_track_t *track)
1532 {
1533     if(track->cur != NULL)
1534     {
1535         track->cur = track->cur->next;
1536     }
1537
1538     return track->cur;
1539 }
1540
1541 /*
1542  * fluid_track_reset
1543  */
1544 int
1545 fluid_track_reset(fluid_track_t *track)
1546 {
1547     track->ticks = 0;
1548     track->cur = track->first;
1549     return FLUID_OK;
1550 }
1551
1552 /*
1553  * fluid_track_send_events
1554  */
1555 int
1556 fluid_track_send_events(fluid_track_t *track,
1557                         fluid_synth_t *synth,
1558                         fluid_player_t *player,
1559                         unsigned int ticks)
1560 {
1561     int status = FLUID_OK;
1562     fluid_midi_event_t *event;
1563     int seeking = player->seek_ticks >= 0;
1564
1565     if(seeking)
1566     {
1567         ticks = player->seek_ticks; /* update target ticks */
1568
1569         if(track->ticks > ticks)
1570         {
1571             fluid_track_reset(track);    /* reset track if seeking backwards */
1572         }
1573     }
1574
1575     while(1)
1576     {
1577
1578         event = track->cur;
1579
1580         if(event == NULL)
1581         {
1582             return status;
1583         }
1584
1585         /*              printf("track=%02d\tticks=%05u\ttrack=%05u\tdtime=%05u\tnext=%05u\n", */
1586         /*                     track->num, */
1587         /*                     ticks, */
1588         /*                     track->ticks, */
1589         /*                     event->dtime, */
1590         /*                     track->ticks + event->dtime); */
1591
1592         if(track->ticks + event->dtime > ticks)
1593         {
1594             return status;
1595         }
1596
1597         track->ticks += event->dtime;
1598
1599         if(!player || event->type == MIDI_EOT)
1600         {
1601         }
1602         else if(seeking && (event->type == NOTE_ON || event->type == NOTE_OFF))
1603         {
1604             /* skip on/off messages */
1605         }
1606         else
1607         {
1608             if(player->playback_callback)
1609             {
1610                 player->playback_callback(player->playback_userdata, event);
1611             }
1612         }
1613
1614         if(event->type == MIDI_SET_TEMPO)
1615         {
1616             fluid_player_set_midi_tempo(player, event->param1);
1617         }
1618
1619         fluid_track_next_event(track);
1620
1621     }
1622
1623     return status;
1624 }
1625
1626 /******************************************************
1627  *
1628  *     fluid_player
1629  */
1630 static void
1631 fluid_player_handle_reset_synth(void *data, const char *name, int value)
1632 {
1633     fluid_player_t *player = data;
1634     fluid_return_if_fail(player != NULL);
1635
1636     player->reset_synth_between_songs = value;
1637 }
1638
1639 /**
1640  * Create a new MIDI player.
1641  * @param synth Fluid synthesizer instance to create player for
1642  * @return New MIDI player instance or NULL on error (out of memory)
1643  */
1644 fluid_player_t *
1645 new_fluid_player(fluid_synth_t *synth)
1646 {
1647     int i;
1648     fluid_player_t *player;
1649     player = FLUID_NEW(fluid_player_t);
1650
1651     if(player == NULL)
1652     {
1653         FLUID_LOG(FLUID_ERR, "Out of memory");
1654         return NULL;
1655     }
1656
1657     player->status = FLUID_PLAYER_READY;
1658     player->loop = 1;
1659     player->ntracks = 0;
1660
1661     for(i = 0; i < MAX_NUMBER_OF_TRACKS; i++)
1662     {
1663         player->track[i] = NULL;
1664     }
1665
1666     player->synth = synth;
1667     player->system_timer = NULL;
1668     player->sample_timer = NULL;
1669     player->playlist = NULL;
1670     player->currentfile = NULL;
1671     player->division = 0;
1672     player->send_program_change = 1;
1673     player->miditempo = 480000;
1674     player->deltatime = 4.0;
1675     player->cur_msec = 0;
1676     player->cur_ticks = 0;
1677     player->seek_ticks = -1;
1678     fluid_player_set_playback_callback(player, fluid_synth_handle_midi_event, synth);
1679     player->use_system_timer = fluid_settings_str_equal(synth->settings,
1680                                "player.timing-source", "system");
1681
1682     fluid_settings_getint(synth->settings, "player.reset-synth", &i);
1683     fluid_player_handle_reset_synth(player, NULL, i);
1684
1685     fluid_settings_callback_int(synth->settings, "player.reset-synth",
1686                                 fluid_player_handle_reset_synth, player);
1687
1688     return player;
1689 }
1690
1691 /**
1692  * Delete a MIDI player instance.
1693  * @param player MIDI player instance
1694  */
1695 void
1696 delete_fluid_player(fluid_player_t *player)
1697 {
1698     fluid_list_t *q;
1699     fluid_playlist_item *pi;
1700
1701     fluid_return_if_fail(player != NULL);
1702
1703     fluid_player_stop(player);
1704     fluid_player_reset(player);
1705
1706     while(player->playlist != NULL)
1707     {
1708         q = player->playlist->next;
1709         pi = (fluid_playlist_item *) player->playlist->data;
1710         FLUID_FREE(pi->filename);
1711         FLUID_FREE(pi->buffer);
1712         FLUID_FREE(pi);
1713         delete1_fluid_list(player->playlist);
1714         player->playlist = q;
1715     }
1716
1717     FLUID_FREE(player);
1718 }
1719
1720 /**
1721  * Registers settings related to the MIDI player
1722  */
1723 void
1724 fluid_player_settings(fluid_settings_t *settings)
1725 {
1726     /* player.timing-source can be either "system" (use system timer)
1727      or "sample" (use timer based on number of written samples) */
1728     fluid_settings_register_str(settings, "player.timing-source", "sample", 0);
1729     fluid_settings_add_option(settings, "player.timing-source", "sample");
1730     fluid_settings_add_option(settings, "player.timing-source", "system");
1731
1732     /* Selects whether the player should reset the synth between songs, or not. */
1733     fluid_settings_register_int(settings, "player.reset-synth", 1, 0, 1, FLUID_HINT_TOGGLED);
1734 }
1735
1736
1737 int
1738 fluid_player_reset(fluid_player_t *player)
1739 {
1740     int i;
1741
1742     for(i = 0; i < MAX_NUMBER_OF_TRACKS; i++)
1743     {
1744         if(player->track[i] != NULL)
1745         {
1746             delete_fluid_track(player->track[i]);
1747             player->track[i] = NULL;
1748         }
1749     }
1750
1751     /*  player->current_file = NULL; */
1752     /*  player->status = FLUID_PLAYER_READY; */
1753     /*  player->loop = 1; */
1754     player->ntracks = 0;
1755     player->division = 0;
1756     player->send_program_change = 1;
1757     player->miditempo = 480000;
1758     player->deltatime = 4.0;
1759     return 0;
1760 }
1761
1762 /*
1763  * fluid_player_add_track
1764  */
1765 int
1766 fluid_player_add_track(fluid_player_t *player, fluid_track_t *track)
1767 {
1768     if(player->ntracks < MAX_NUMBER_OF_TRACKS)
1769     {
1770         player->track[player->ntracks++] = track;
1771         return FLUID_OK;
1772     }
1773     else
1774     {
1775         return FLUID_FAILED;
1776     }
1777 }
1778
1779 /**
1780  * Change the MIDI callback function. This is usually set to
1781  * fluid_synth_handle_midi_event, but can optionally be changed
1782  * to a user-defined function instead, for intercepting all MIDI
1783  * messages sent to the synth. You can also use a midi router as
1784  * the callback function to modify the MIDI messages before sending
1785  * them to the synth.
1786  * @param player MIDI player instance
1787  * @param handler Pointer to callback function
1788  * @param handler_data Parameter sent to the callback function
1789  * @returns FLUID_OK
1790  * @since 1.1.4
1791  */
1792 int
1793 fluid_player_set_playback_callback(fluid_player_t *player,
1794                                    handle_midi_event_func_t handler, void *handler_data)
1795 {
1796     player->playback_callback = handler;
1797     player->playback_userdata = handler_data;
1798     return FLUID_OK;
1799 }
1800
1801 /**
1802  * Add a MIDI file to a player queue.
1803  * @param player MIDI player instance
1804  * @param midifile File name of the MIDI file to add
1805  * @return #FLUID_OK or #FLUID_FAILED
1806  */
1807 int
1808 fluid_player_add(fluid_player_t *player, const char *midifile)
1809 {
1810     fluid_playlist_item *pi = FLUID_MALLOC(sizeof(fluid_playlist_item));
1811     char *f = FLUID_STRDUP(midifile);
1812
1813     if(!pi || !f)
1814     {
1815         FLUID_FREE(pi);
1816         FLUID_FREE(f);
1817         FLUID_LOG(FLUID_PANIC, "Out of memory");
1818         return FLUID_FAILED;
1819     }
1820
1821     pi->filename = f;
1822     pi->buffer = NULL;
1823     pi->buffer_len = 0;
1824     player->playlist = fluid_list_append(player->playlist, pi);
1825     return FLUID_OK;
1826 }
1827
1828 /**
1829  * Add a MIDI file to a player queue, from a buffer in memory.
1830  * @param player MIDI player instance
1831  * @param buffer Pointer to memory containing the bytes of a complete MIDI
1832  *   file. The data is copied, so the caller may free or modify it immediately
1833  *   without affecting the playlist.
1834  * @param len Length of the buffer, in bytes.
1835  * @return #FLUID_OK or #FLUID_FAILED
1836  */
1837 int
1838 fluid_player_add_mem(fluid_player_t *player, const void *buffer, size_t len)
1839 {
1840     /* Take a copy of the buffer, so the caller can free immediately. */
1841     fluid_playlist_item *pi = FLUID_MALLOC(sizeof(fluid_playlist_item));
1842     void *buf_copy = FLUID_MALLOC(len);
1843
1844     if(!pi || !buf_copy)
1845     {
1846         FLUID_FREE(pi);
1847         FLUID_FREE(buf_copy);
1848         FLUID_LOG(FLUID_PANIC, "Out of memory");
1849         return FLUID_FAILED;
1850     }
1851
1852     FLUID_MEMCPY(buf_copy, buffer, len);
1853     pi->filename = NULL;
1854     pi->buffer = buf_copy;
1855     pi->buffer_len = len;
1856     player->playlist = fluid_list_append(player->playlist, pi);
1857     return FLUID_OK;
1858 }
1859
1860 /*
1861  * fluid_player_load
1862  */
1863 int
1864 fluid_player_load(fluid_player_t *player, fluid_playlist_item *item)
1865 {
1866     fluid_midi_file *midifile;
1867     char *buffer;
1868     size_t buffer_length;
1869     int buffer_owned;
1870
1871     if(item->filename != NULL)
1872     {
1873         fluid_file fp;
1874         /* This file is specified by filename; load the file from disk */
1875         FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile %s", __FILE__, __LINE__,
1876                   item->filename);
1877         /* Read the entire contents of the file into the buffer */
1878         fp = FLUID_FOPEN(item->filename, "rb");
1879
1880         if(fp == NULL)
1881         {
1882             FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file");
1883             return FLUID_FAILED;
1884         }
1885
1886         buffer = fluid_file_read_full(fp, &buffer_length);
1887
1888         if(buffer == NULL)
1889         {
1890             FLUID_FCLOSE(fp);
1891             return FLUID_FAILED;
1892         }
1893
1894         buffer_owned = 1;
1895         FLUID_FCLOSE(fp);
1896     }
1897     else
1898     {
1899         /* This file is specified by a pre-loaded buffer; load from memory */
1900         FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile from memory (%p)",
1901                   __FILE__, __LINE__, item->buffer);
1902         buffer = (char *) item->buffer;
1903         buffer_length = item->buffer_len;
1904         /* Do not free the buffer (it is owned by the playlist) */
1905         buffer_owned = 0;
1906     }
1907
1908     midifile = new_fluid_midi_file(buffer, buffer_length);
1909
1910     if(midifile == NULL)
1911     {
1912         if(buffer_owned)
1913         {
1914             FLUID_FREE(buffer);
1915         }
1916
1917         return FLUID_FAILED;
1918     }
1919
1920     player->division = fluid_midi_file_get_division(midifile);
1921     fluid_player_set_midi_tempo(player, player->miditempo); // Update deltatime
1922     /*FLUID_LOG(FLUID_DBG, "quarter note division=%d\n", player->division); */
1923
1924     if(fluid_midi_file_load_tracks(midifile, player) != FLUID_OK)
1925     {
1926         if(buffer_owned)
1927         {
1928             FLUID_FREE(buffer);
1929         }
1930
1931         delete_fluid_midi_file(midifile);
1932         return FLUID_FAILED;
1933     }
1934
1935     delete_fluid_midi_file(midifile);
1936
1937     if(buffer_owned)
1938     {
1939         FLUID_FREE(buffer);
1940     }
1941
1942     return FLUID_OK;
1943 }
1944
1945 void
1946 fluid_player_advancefile(fluid_player_t *player)
1947 {
1948     if(player->playlist == NULL)
1949     {
1950         return; /* No files to play */
1951     }
1952
1953     if(player->currentfile != NULL)
1954     {
1955         player->currentfile = fluid_list_next(player->currentfile);
1956     }
1957
1958     if(player->currentfile == NULL)
1959     {
1960         if(player->loop == 0)
1961         {
1962             return; /* We're done playing */
1963         }
1964
1965         if(player->loop > 0)
1966         {
1967             player->loop--;
1968         }
1969
1970         player->currentfile = player->playlist;
1971     }
1972 }
1973
1974 void
1975 fluid_player_playlist_load(fluid_player_t *player, unsigned int msec)
1976 {
1977     fluid_playlist_item *current_playitem;
1978     int i;
1979
1980     do
1981     {
1982         fluid_player_advancefile(player);
1983
1984         if(player->currentfile == NULL)
1985         {
1986             /* Failed to find next song, probably since we're finished */
1987             player->status = FLUID_PLAYER_DONE;
1988             return;
1989         }
1990
1991         fluid_player_reset(player);
1992         current_playitem = (fluid_playlist_item *) player->currentfile->data;
1993     }
1994     while(fluid_player_load(player, current_playitem) != FLUID_OK);
1995
1996     /* Successfully loaded midi file */
1997
1998     player->begin_msec = msec;
1999     player->start_msec = msec;
2000     player->start_ticks = 0;
2001     player->cur_ticks = 0;
2002
2003     if(player->reset_synth_between_songs)
2004     {
2005         fluid_synth_system_reset(player->synth);
2006     }
2007
2008     for(i = 0; i < player->ntracks; i++)
2009     {
2010         if(player->track[i] != NULL)
2011         {
2012             fluid_track_reset(player->track[i]);
2013         }
2014     }
2015 }
2016
2017 /*
2018  * fluid_player_callback
2019  */
2020 int
2021 fluid_player_callback(void *data, unsigned int msec)
2022 {
2023     int i;
2024     int loadnextfile;
2025     int status = FLUID_PLAYER_DONE;
2026     fluid_player_t *player;
2027     fluid_synth_t *synth;
2028     player = (fluid_player_t *) data;
2029     synth = player->synth;
2030
2031     loadnextfile = player->currentfile == NULL ? 1 : 0;
2032
2033     do
2034     {
2035         if(loadnextfile)
2036         {
2037             loadnextfile = 0;
2038             fluid_player_playlist_load(player, msec);
2039
2040             if(player->currentfile == NULL)
2041             {
2042                 return 0;
2043             }
2044         }
2045
2046         player->cur_msec = msec;
2047         player->cur_ticks = (player->start_ticks
2048                              + (int)((double)(player->cur_msec - player->start_msec)
2049                                      / player->deltatime + 0.5)); /* 0.5 to average overall error when casting */
2050
2051         if(player->seek_ticks >= 0)
2052         {
2053             fluid_synth_all_sounds_off(synth, -1); /* avoid hanging notes */
2054         }
2055
2056         for(i = 0; i < player->ntracks; i++)
2057         {
2058             if(!fluid_track_eot(player->track[i]))
2059             {
2060                 status = FLUID_PLAYER_PLAYING;
2061
2062                 if(fluid_track_send_events(player->track[i], synth, player,
2063                                            player->cur_ticks) != FLUID_OK)
2064                 {
2065                     /* */
2066                 }
2067             }
2068         }
2069
2070         if(player->seek_ticks >= 0)
2071         {
2072             player->start_ticks = player->seek_ticks;   /* tick position of last tempo value (which is now) */
2073             player->cur_ticks = player->seek_ticks;
2074             player->begin_msec = msec;      /* only used to calculate the duration of playing */
2075             player->start_msec = msec;      /* should be the (synth)-time of the last tempo change */
2076             player->seek_ticks = -1;        /* clear seek_ticks */
2077         }
2078
2079         if(status == FLUID_PLAYER_DONE)
2080         {
2081             FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec", __FILE__,
2082                       __LINE__, (msec - player->begin_msec) / 1000.0);
2083             loadnextfile = 1;
2084         }
2085     }
2086     while(loadnextfile);
2087
2088     player->status = status;
2089
2090     return 1;
2091 }
2092
2093 /**
2094  * Activates play mode for a MIDI player if not already playing.
2095  * @param player MIDI player instance
2096  * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2097  */
2098 int
2099 fluid_player_play(fluid_player_t *player)
2100 {
2101     if(player->status == FLUID_PLAYER_PLAYING)
2102     {
2103         return FLUID_OK;
2104     }
2105
2106     if(player->playlist == NULL)
2107     {
2108         return FLUID_OK;
2109     }
2110
2111     player->status = FLUID_PLAYER_PLAYING;
2112
2113     if(player->use_system_timer)
2114     {
2115         player->system_timer = new_fluid_timer((int) player->deltatime,
2116                                                fluid_player_callback, (void *) player, TRUE, FALSE, TRUE);
2117
2118         if(player->system_timer == NULL)
2119         {
2120             return FLUID_FAILED;
2121         }
2122     }
2123     else
2124     {
2125         player->sample_timer = new_fluid_sample_timer(player->synth,
2126                                fluid_player_callback, (void *) player);
2127
2128         if(player->sample_timer == NULL)
2129         {
2130             return FLUID_FAILED;
2131         }
2132     }
2133
2134     return FLUID_OK;
2135 }
2136
2137 /**
2138  * Stops a MIDI player.
2139  * @param player MIDI player instance
2140  * @return Always returns #FLUID_OK
2141  */
2142 int
2143 fluid_player_stop(fluid_player_t *player)
2144 {
2145     if(player->system_timer != NULL)
2146     {
2147         delete_fluid_timer(player->system_timer);
2148     }
2149
2150     if(player->sample_timer != NULL)
2151     {
2152         delete_fluid_sample_timer(player->synth, player->sample_timer);
2153     }
2154
2155     player->status = FLUID_PLAYER_DONE;
2156     player->sample_timer = NULL;
2157     player->system_timer = NULL;
2158     return FLUID_OK;
2159 }
2160
2161 /**
2162  * Get MIDI player status.
2163  * @param player MIDI player instance
2164  * @return Player status (#fluid_player_status)
2165  * @since 1.1.0
2166  */
2167 int
2168 fluid_player_get_status(fluid_player_t *player)
2169 {
2170     return player->status;
2171 }
2172
2173 /**
2174  * Seek in the currently playing file.
2175  * @param player MIDI player instance
2176  * @param ticks the position to seek to in the current file
2177  * @return #FLUID_FAILED if ticks is negative or after the latest tick of the file,
2178  *   #FLUID_OK otherwise
2179  * @since 2.0.0
2180  *
2181  * The actual seek is performed during the player_callback.
2182  */
2183 int fluid_player_seek(fluid_player_t *player, int ticks)
2184 {
2185     if(ticks < 0 || ticks > fluid_player_get_total_ticks(player))
2186     {
2187         return FLUID_FAILED;
2188     }
2189
2190     player->seek_ticks = ticks;
2191     return FLUID_OK;
2192 }
2193
2194
2195 /**
2196  * Enable looping of a MIDI player
2197  * @param player MIDI player instance
2198  * @param loop Times left to loop the playlist. -1 means loop infinitely.
2199  * @return Always returns #FLUID_OK
2200  * @since 1.1.0
2201  *
2202  * For example, if you want to loop the playlist twice, set loop to 2
2203  * and call this function before you start the player.
2204  */
2205 int fluid_player_set_loop(fluid_player_t *player, int loop)
2206 {
2207     player->loop = loop;
2208     return FLUID_OK;
2209 }
2210
2211 /**
2212  * Set the tempo of a MIDI player.
2213  * @param player MIDI player instance
2214  * @param tempo Tempo to set playback speed to (in microseconds per quarter note, as per MIDI file spec)
2215  * @return Always returns #FLUID_OK
2216  */
2217 int fluid_player_set_midi_tempo(fluid_player_t *player, int tempo)
2218 {
2219     player->miditempo = tempo;
2220     player->deltatime = (double) tempo / player->division / 1000.0; /* in milliseconds */
2221     player->start_msec = player->cur_msec;
2222     player->start_ticks = player->cur_ticks;
2223
2224     FLUID_LOG(FLUID_DBG,
2225               "tempo=%d, tick time=%f msec, cur time=%d msec, cur tick=%d",
2226               tempo, player->deltatime, player->cur_msec, player->cur_ticks);
2227
2228     return FLUID_OK;
2229 }
2230
2231 /**
2232  * Set the tempo of a MIDI player in beats per minute.
2233  * @param player MIDI player instance
2234  * @param bpm Tempo in beats per minute
2235  * @return Always returns #FLUID_OK
2236  */
2237 int fluid_player_set_bpm(fluid_player_t *player, int bpm)
2238 {
2239     return fluid_player_set_midi_tempo(player, 60000000L / bpm);
2240 }
2241
2242 /**
2243  * Wait for a MIDI player to terminate (when done playing).
2244  * @param player MIDI player instance
2245  * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2246  */
2247 int
2248 fluid_player_join(fluid_player_t *player)
2249 {
2250     if(player->system_timer)
2251     {
2252         return fluid_timer_join(player->system_timer);
2253     }
2254     else if(player->sample_timer)
2255     {
2256         /* Busy-wait loop, since there's no thread to wait for... */
2257         while(player->status != FLUID_PLAYER_DONE)
2258         {
2259             fluid_msleep(10);
2260         }
2261     }
2262
2263     return FLUID_OK;
2264 }
2265
2266 /**
2267  * Get the number of tempo ticks passed.
2268  * @param player MIDI player instance
2269  * @return The number of tempo ticks passed
2270  * @since 1.1.7
2271  */
2272 int fluid_player_get_current_tick(fluid_player_t *player)
2273 {
2274     return player->cur_ticks;
2275 }
2276
2277 /**
2278  * Looks through all available MIDI tracks and gets the absolute tick of the very last event to play.
2279  * @param player MIDI player instance
2280  * @return Total tick count of the sequence
2281  * @since 1.1.7
2282  */
2283 int fluid_player_get_total_ticks(fluid_player_t *player)
2284 {
2285     int i;
2286     int maxTicks = 0;
2287
2288     for(i = 0; i < player->ntracks; i++)
2289     {
2290         if(player->track[i] != NULL)
2291         {
2292             int ticks = fluid_track_get_duration(player->track[i]);
2293
2294             if(ticks > maxTicks)
2295             {
2296                 maxTicks = ticks;
2297             }
2298         }
2299     }
2300
2301     return maxTicks;
2302 }
2303
2304 /**
2305  * Get the tempo of a MIDI player in beats per minute.
2306  * @param player MIDI player instance
2307  * @return MIDI player tempo in BPM
2308  * @since 1.1.7
2309  */
2310 int fluid_player_get_bpm(fluid_player_t *player)
2311 {
2312     return 60000000L / player->miditempo;
2313 }
2314
2315 /**
2316  * Get the tempo of a MIDI player.
2317  * @param player MIDI player instance
2318  * @return Tempo of the MIDI player (in microseconds per quarter note, as per MIDI file spec)
2319  * @since 1.1.7
2320  */
2321 int fluid_player_get_midi_tempo(fluid_player_t *player)
2322 {
2323     return player->miditempo;
2324 }
2325
2326 /************************************************************************
2327  *       MIDI PARSER
2328  *
2329  */
2330
2331 /*
2332  * new_fluid_midi_parser
2333  */
2334 fluid_midi_parser_t *
2335 new_fluid_midi_parser()
2336 {
2337     fluid_midi_parser_t *parser;
2338     parser = FLUID_NEW(fluid_midi_parser_t);
2339
2340     if(parser == NULL)
2341     {
2342         FLUID_LOG(FLUID_ERR, "Out of memory");
2343         return NULL;
2344     }
2345
2346     parser->status = 0; /* As long as the status is 0, the parser won't do anything -> no need to initialize all the fields. */
2347     return parser;
2348 }
2349
2350 /*
2351  * delete_fluid_midi_parser
2352  */
2353 void
2354 delete_fluid_midi_parser(fluid_midi_parser_t *parser)
2355 {
2356     fluid_return_if_fail(parser != NULL);
2357
2358     FLUID_FREE(parser);
2359 }
2360
2361 /**
2362  * Parse a MIDI stream one character at a time.
2363  * @param parser Parser instance
2364  * @param c Next character in MIDI stream
2365  * @return A parsed MIDI event or NULL if none.  Event is internal and should
2366  *   not be modified or freed and is only valid until next call to this function.
2367  * @internal Do not expose this function to the public API. It would allow downstream
2368  * apps to abuse fluidsynth as midi parser, e.g. feeding it with rawmidi and pull out
2369  * the needed midi information using the getter functions of fluid_midi_event_t.
2370  * This parser however is incomplete as it e.g. only provides a limited buffer to
2371  * store and process SYSEX data (i.e. doesnt allow arbitrary lengths)
2372  */
2373 fluid_midi_event_t *
2374 fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigned char c)
2375 {
2376     fluid_midi_event_t *event;
2377
2378     /* Real-time messages (0xF8-0xFF) can occur anywhere, even in the middle
2379      * of another message. */
2380     if(c >= 0xF8)
2381     {
2382         if(c == MIDI_SYSTEM_RESET)
2383         {
2384             parser->event.type = c;
2385             parser->status = 0; /* clear the status */
2386             return &parser->event;
2387         }
2388
2389         return NULL;
2390     }
2391
2392     /* Status byte? - If previous message not yet complete, it is discarded (re-sync). */
2393     if(c & 0x80)
2394     {
2395         /* Any status byte terminates SYSEX messages (not just 0xF7) */
2396         if(parser->status == MIDI_SYSEX && parser->nr_bytes > 0)
2397         {
2398             event = &parser->event;
2399             fluid_midi_event_set_sysex(event, parser->data, parser->nr_bytes,
2400                                        FALSE);
2401         }
2402         else
2403         {
2404             event = NULL;
2405         }
2406
2407         if(c < 0xF0)  /* Voice category message? */
2408         {
2409             parser->channel = c & 0x0F;
2410             parser->status = c & 0xF0;
2411
2412             /* The event consumes x bytes of data... (subtract 1 for the status byte) */
2413             parser->nr_bytes_total = fluid_midi_event_length(parser->status)
2414                                      - 1;
2415
2416             parser->nr_bytes = 0; /* 0  bytes read so far */
2417         }
2418         else if(c == MIDI_SYSEX)
2419         {
2420             parser->status = MIDI_SYSEX;
2421             parser->nr_bytes = 0;
2422         }
2423         else
2424         {
2425             parser->status = 0;    /* Discard other system messages (0xF1-0xF7) */
2426         }
2427
2428         return event; /* Return SYSEX event or NULL */
2429     }
2430
2431     /* Data/parameter byte */
2432
2433     /* Discard data bytes for events we don't care about */
2434     if(parser->status == 0)
2435     {
2436         return NULL;
2437     }
2438
2439     /* Max data size exceeded? (SYSEX messages only really) */
2440     if(parser->nr_bytes == FLUID_MIDI_PARSER_MAX_DATA_SIZE)
2441     {
2442         parser->status = 0; /* Discard the rest of the message */
2443         return NULL;
2444     }
2445
2446     /* Store next byte */
2447     parser->data[parser->nr_bytes++] = c;
2448
2449     /* Do we still need more data to get this event complete? */
2450     if(parser->status == MIDI_SYSEX || parser->nr_bytes < parser->nr_bytes_total)
2451     {
2452         return NULL;
2453     }
2454
2455     /* Event is complete, return it.
2456      * Running status byte MIDI feature is also handled here. */
2457     parser->event.type = parser->status;
2458     parser->event.channel = parser->channel;
2459     parser->nr_bytes = 0; /* Reset data size, in case there are additional running status messages */
2460
2461     switch(parser->status)
2462     {
2463     case NOTE_OFF:
2464     case NOTE_ON:
2465     case KEY_PRESSURE:
2466     case CONTROL_CHANGE:
2467     case PROGRAM_CHANGE:
2468     case CHANNEL_PRESSURE:
2469         parser->event.param1 = parser->data[0]; /* For example key number */
2470         parser->event.param2 = parser->data[1]; /* For example velocity */
2471         break;
2472
2473     case PITCH_BEND:
2474         /* Pitch-bend is transmitted with 14-bit precision. */
2475         parser->event.param1 = (parser->data[1] << 7) | parser->data[0];
2476         break;
2477
2478     default: /* Unlikely */
2479         return NULL;
2480     }
2481
2482     return &parser->event;
2483 }
2484
2485 /* Purpose:
2486  * Returns the length of a MIDI message. */
2487 static int
2488 fluid_midi_event_length(unsigned char event)
2489 {
2490     switch(event & 0xF0)
2491     {
2492     case NOTE_OFF:
2493     case NOTE_ON:
2494     case KEY_PRESSURE:
2495     case CONTROL_CHANGE:
2496     case PITCH_BEND:
2497         return 3;
2498
2499     case PROGRAM_CHANGE:
2500     case CHANNEL_PRESSURE:
2501         return 2;
2502     }
2503
2504     switch(event)
2505     {
2506     case MIDI_TIME_CODE:
2507     case MIDI_SONG_SELECT:
2508     case 0xF4:
2509     case 0xF5:
2510         return 2;
2511
2512     case MIDI_TUNE_REQUEST:
2513         return 1;
2514
2515     case MIDI_SONG_POSITION:
2516         return 3;
2517     }
2518
2519     return 1;
2520 }
2521 #endif