1ee3dd24cb62010e5588d4cbec388ba10d249cb7
[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 Library General Public License
7  * as published by the Free Software Foundation; either version 2 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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library 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
29 /* Read the entire contents of a file into memory, allocating enough memory
30  * for the file, and returning the length and the buffer.
31  * Note: This rewinds the file to the start before reading.
32  * Returns NULL if there was an error reading or allocating memory.
33  */
34 static char* fluid_file_read_full(fluid_file fp, size_t* length);
35 #define READ_FULL_INITIAL_BUFLEN 1024
36
37
38 /***************************************************************
39  *
40  *                      MIDIFILE
41  */
42
43 /**
44  * Return a new MIDI file handle for parsing an already-loaded MIDI file.
45  * @internal
46  * @param buffer Pointer to full contents of MIDI file (borrows the pointer).
47  *  The caller must not free buffer until after the fluid_midi_file is deleted.
48  * @param length Size of the buffer in bytes.
49  * @return New MIDI file handle or NULL on error.
50  */
51 fluid_midi_file *
52 new_fluid_midi_file(const char* buffer, size_t length)
53 {
54     fluid_midi_file *mf;
55
56     mf = FLUID_NEW(fluid_midi_file);
57     if (mf == NULL) {
58         FLUID_LOG(FLUID_ERR, "Out of memory");
59         return NULL;
60     }
61     FLUID_MEMSET(mf, 0, sizeof(fluid_midi_file));
62
63     mf->c = -1;
64     mf->running_status = -1;
65
66     mf->buffer = buffer;
67     mf->buf_len = length;
68     mf->buf_pos = 0;
69     mf->eof = FALSE;
70
71     if (fluid_midi_file_read_mthd(mf) != FLUID_OK) {
72         FLUID_FREE(mf);
73         return NULL;
74     }
75     return mf;
76 }
77
78 static char*
79 fluid_file_read_full(fluid_file fp, size_t* length)
80 {
81     size_t buflen;
82     char* buffer;
83     size_t n;
84     /* Work out the length of the file in advance */
85     if (FLUID_FSEEK(fp, 0, SEEK_END) != 0)
86     {
87         FLUID_LOG(FLUID_ERR, "File load: Could not seek within file");
88         return NULL;
89     }
90     buflen = ftell(fp);
91     if (FLUID_FSEEK(fp, 0, SEEK_SET) != 0)
92     {
93         FLUID_LOG(FLUID_ERR, "File load: Could not seek within file");
94         return NULL;
95     }
96     FLUID_LOG(FLUID_DBG, "File load: Allocating %d bytes", buflen);
97     buffer = FLUID_MALLOC(buflen);
98     if (buffer == NULL) {
99         FLUID_LOG(FLUID_PANIC, "Out of memory");
100         return NULL;
101     }
102     n = FLUID_FREAD(buffer, 1, buflen, fp);
103     if (n != buflen) {
104         FLUID_LOG(FLUID_ERR, "Only read %d bytes; expected %d", n,
105                   buflen);
106         FLUID_FREE(buffer);
107         return NULL;
108     };
109     *length = n;
110     return buffer;
111 }
112
113 /**
114  * Delete a MIDI file handle.
115  * @internal
116  * @param mf MIDI file handle to close and free.
117  */
118 void
119 delete_fluid_midi_file (fluid_midi_file *mf)
120 {
121     if (mf == NULL) {
122         return;
123     }
124     FLUID_FREE(mf);
125     return;
126 }
127
128 /*
129  * Gets the next byte in a MIDI file, taking into account previous running status.
130  *
131  * returns FLUID_FAILED if EOF or read error
132  */
133 int
134 fluid_midi_file_getc (fluid_midi_file *mf)
135 {
136     unsigned char c;
137     if (mf->c >= 0) {
138         c = mf->c;
139         mf->c = -1;
140     } else {
141         if (mf->buf_pos >= mf->buf_len) {
142             mf->eof = TRUE;
143             return FLUID_FAILED;
144         }
145         c = mf->buffer[mf->buf_pos++];
146         mf->trackpos++;
147     }
148     return (int) c;
149 }
150
151 /*
152  * Saves a byte to be returned the next time fluid_midi_file_getc() is called,
153  * when it is necessary according to running status.
154  */
155 int
156 fluid_midi_file_push(fluid_midi_file *mf, int c)
157 {
158     mf->c = c;
159     return FLUID_OK;
160 }
161
162 /*
163  * fluid_midi_file_read
164  */
165 int
166 fluid_midi_file_read(fluid_midi_file *mf, void *buf, int len)
167 {
168     int num = len < mf->buf_len - mf->buf_pos
169         ? len : mf->buf_len - mf->buf_pos;
170     if (num != len) {
171         mf->eof = TRUE;
172     }
173     if (num < 0) {
174         num = 0;
175     }
176     /* Note: Read bytes, even if there aren't enough, but only increment
177      * trackpos if successful (emulates old behaviour of fluid_midi_file_read)
178      */
179     FLUID_MEMCPY(buf, mf->buffer+mf->buf_pos, num);
180     mf->buf_pos += num;
181     if (num == len)
182         mf->trackpos += num;
183 #if DEBUG
184     else
185         FLUID_LOG(FLUID_DBG, "Could not read the requested number of bytes");
186 #endif
187     return (num != len) ? FLUID_FAILED : FLUID_OK;
188 }
189
190 /*
191  * fluid_midi_file_skip
192  */
193 int
194 fluid_midi_file_skip (fluid_midi_file *mf, int skip)
195 {
196     int new_pos = mf->buf_pos + skip;
197     /* Mimic the behaviour of fseek: Error to seek past the start of file, but
198      * OK to seek past end (this just puts it into the EOF state). */
199     if (new_pos < 0) {
200         FLUID_LOG(FLUID_ERR, "Failed to seek position in file");
201         return FLUID_FAILED;
202     }
203     /* Clear the EOF flag, even if moved past the end of the file (this is
204      * consistent with the behaviour of fseek). */
205     mf->eof = FALSE;
206     mf->buf_pos = new_pos;
207     return FLUID_OK;
208 }
209
210 /*
211  * fluid_midi_file_eof
212  */
213 int fluid_midi_file_eof(fluid_midi_file* mf)
214 {
215         /* Note: This does not simply test whether the file read pointer is past
216          * the end of the file. It mimics the behaviour of feof by actually
217          * testing the stateful EOF condition, which is set to TRUE if getc or
218          * fread have attempted to read past the end (but not if they have
219          * precisely reached the end), but reset to FALSE upon a successful seek.
220          */
221         return mf->eof;
222 }
223
224 /*
225  * fluid_midi_file_read_mthd
226  */
227 int
228 fluid_midi_file_read_mthd(fluid_midi_file *mf)
229 {
230     char mthd[15];
231     if (fluid_midi_file_read(mf, mthd, 14) != FLUID_OK) {
232         return FLUID_FAILED;
233     }
234     if ((FLUID_STRNCMP(mthd, "MThd", 4) != 0) || (mthd[7] != 6)
235             || (mthd[9] > 2)) {
236         FLUID_LOG(FLUID_ERR,
237                 "Doesn't look like a MIDI file: invalid MThd header");
238         return FLUID_FAILED;
239     }
240     mf->type = mthd[9];
241     mf->ntracks = (unsigned) mthd[11];
242     mf->ntracks += (unsigned int) (mthd[10]) << 16;
243     if ((mthd[12]) < 0) {
244         mf->uses_smpte = 1;
245         mf->smpte_fps = -mthd[12];
246         mf->smpte_res = (unsigned) mthd[13];
247         FLUID_LOG(FLUID_ERR, "File uses SMPTE timing -- Not implemented yet");
248         return FLUID_FAILED;
249     } else {
250         mf->uses_smpte = 0;
251         mf->division = (mthd[12] << 8) | (mthd[13] & 0xff);
252         FLUID_LOG(FLUID_DBG, "Division=%d", mf->division);
253     }
254     return FLUID_OK;
255 }
256
257 /*
258  * fluid_midi_file_load_tracks
259  */
260 int
261 fluid_midi_file_load_tracks(fluid_midi_file *mf, fluid_player_t *player)
262 {
263     int i;
264     for (i = 0; i < mf->ntracks; i++) {
265         if (fluid_midi_file_read_track(mf, player, i) != FLUID_OK) {
266             return FLUID_FAILED;
267         }
268     }
269     return FLUID_OK;
270 }
271
272 /*
273  * fluid_isasciistring
274  */
275 int
276 fluid_isasciistring(char *s)
277 {
278     int i;
279     int len = (int) FLUID_STRLEN(s);
280     for (i = 0; i < len; i++) {
281         if (!fluid_isascii(s[i])) {
282             return 0;
283         }
284     }
285     return 1;
286 }
287
288 /*
289  * fluid_getlength
290  */
291 long
292 fluid_getlength(unsigned char *s)
293 {
294     long i = 0;
295     i = s[3] | (s[2] << 8) | (s[1] << 16) | (s[0] << 24);
296     return i;
297 }
298
299 /*
300  * fluid_midi_file_read_tracklen
301  */
302 int
303 fluid_midi_file_read_tracklen(fluid_midi_file *mf)
304 {
305     unsigned char length[5];
306     if (fluid_midi_file_read(mf, length, 4) != FLUID_OK) {
307         return FLUID_FAILED;
308     }
309     mf->tracklen = fluid_getlength(length);
310     mf->trackpos = 0;
311     mf->eot = 0;
312     return FLUID_OK;
313 }
314
315 /*
316  * fluid_midi_file_eot
317  */
318 int
319 fluid_midi_file_eot(fluid_midi_file *mf)
320 {
321 #if DEBUG
322     if (mf->trackpos > mf->tracklen) {
323         printf("track overrun: %d > %d\n", mf->trackpos, mf->tracklen);
324     }
325 #endif
326     return mf->eot || (mf->trackpos >= mf->tracklen);
327 }
328
329 /*
330  * fluid_midi_file_read_track
331  */
332 int
333 fluid_midi_file_read_track(fluid_midi_file *mf, fluid_player_t *player, int num)
334 {
335     fluid_track_t *track;
336     unsigned char id[5], length[5];
337     int found_track = 0;
338     int skip;
339
340     if (fluid_midi_file_read(mf, id, 4) != FLUID_OK) {
341         return FLUID_FAILED;
342     }
343     id[4] = '\0';
344     mf->dtime = 0;
345
346     while (!found_track) {
347
348         if (fluid_isasciistring((char *) id) == 0) {
349             FLUID_LOG(FLUID_ERR,
350                     "An non-ascii track header found, corrupt file");
351             return FLUID_FAILED;
352
353         } else if (strcmp((char *) id, "MTrk") == 0) {
354
355             found_track = 1;
356
357             if (fluid_midi_file_read_tracklen(mf) != FLUID_OK) {
358                 return FLUID_FAILED;
359             }
360
361             track = new_fluid_track(num);
362             if (track == NULL) {
363                 FLUID_LOG(FLUID_ERR, "Out of memory");
364                 return FLUID_FAILED;
365             }
366
367             while (!fluid_midi_file_eot(mf)) {
368                 if (fluid_midi_file_read_event(mf, track) != FLUID_OK) {
369                     delete_fluid_track(track);
370                     return FLUID_FAILED;
371                 }
372             }
373
374             /* Skip remaining track data, if any */
375             if (mf->trackpos < mf->tracklen)
376                 fluid_midi_file_skip(mf, mf->tracklen - mf->trackpos);
377
378             fluid_player_add_track(player, track);
379
380         } else {
381             found_track = 0;
382             if (fluid_midi_file_read(mf, length, 4) != FLUID_OK) {
383                 return FLUID_FAILED;
384             }
385             skip = fluid_getlength(length);
386             /* fseek(mf->fp, skip, SEEK_CUR); */
387             if (fluid_midi_file_skip(mf, skip) != FLUID_OK) {
388                 return FLUID_FAILED;
389             }
390         }
391     }
392     if (fluid_midi_file_eof(mf)) {
393         FLUID_LOG(FLUID_ERR, "Unexpected end of file");
394         return FLUID_FAILED;
395     }
396     return FLUID_OK;
397 }
398
399 /*
400  * fluid_midi_file_read_varlen
401  */
402 int
403 fluid_midi_file_read_varlen(fluid_midi_file *mf)
404 {
405     int i;
406     int c;
407     mf->varlen = 0;
408     for (i = 0;; i++) {
409         if (i == 4) {
410             FLUID_LOG(FLUID_ERR, "Invalid variable length number");
411             return FLUID_FAILED;
412         }
413         c = fluid_midi_file_getc(mf);
414         if (c < 0) {
415             FLUID_LOG(FLUID_ERR, "Unexpected end of file");
416             return FLUID_FAILED;
417         }
418         if (c & 0x80) {
419             mf->varlen |= (int) (c & 0x7F);
420             mf->varlen <<= 7;
421         } else {
422             mf->varlen += c;
423             break;
424         }
425     }
426     return FLUID_OK;
427 }
428
429 /*
430  * fluid_midi_file_read_event
431  */
432 int
433 fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track)
434 {
435     int status;
436     int type;
437     int tempo;
438     unsigned char *metadata = NULL;
439     unsigned char *dyn_buf = NULL;
440     unsigned char static_buf[256];
441     int nominator, denominator, clocks, notes;
442     fluid_midi_event_t *evt;
443     int channel = 0;
444     int param1 = 0;
445     int param2 = 0;
446     int size;
447
448     /* read the delta-time of the event */
449     if (fluid_midi_file_read_varlen(mf) != FLUID_OK) {
450         return FLUID_FAILED;
451     }
452     mf->dtime += mf->varlen;
453
454     /* read the status byte */
455     status = fluid_midi_file_getc(mf);
456     if (status < 0) {
457         FLUID_LOG(FLUID_ERR, "Unexpected end of file");
458         return FLUID_FAILED;
459     }
460
461     /* not a valid status byte: use the running status instead */
462     if ((status & 0x80) == 0) {
463         if ((mf->running_status & 0x80) == 0) {
464             FLUID_LOG(FLUID_ERR, "Undefined status and invalid running status");
465             return FLUID_FAILED;
466         }
467         fluid_midi_file_push(mf, status);
468         status = mf->running_status;
469     }
470
471     /* check what message we have */
472
473     mf->running_status = status;
474
475     if ((status == MIDI_SYSEX)) { /* system exclusif */
476         /* read the length of the message */
477         if (fluid_midi_file_read_varlen(mf) != FLUID_OK) {
478             return FLUID_FAILED;
479         }
480
481         if (mf->varlen) {
482             FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__,
483                     __LINE__, mf->varlen);
484             metadata = FLUID_MALLOC(mf->varlen + 1);
485
486             if (metadata == NULL) {
487                 FLUID_LOG(FLUID_PANIC, "Out of memory");
488                 return FLUID_FAILED;
489             }
490
491             /* read the data of the message */
492             if (fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK) {
493                 FLUID_FREE (metadata);
494                 return FLUID_FAILED;
495             }
496
497             evt = new_fluid_midi_event();
498             if (evt == NULL) {
499                 FLUID_LOG(FLUID_ERR, "Out of memory");
500                 FLUID_FREE (metadata);
501                 return FLUID_FAILED;
502             }
503
504             evt->dtime = mf->dtime;
505             size = mf->varlen;
506
507             if (metadata[mf->varlen - 1] == MIDI_EOX)
508                 size--;
509
510             /* Add SYSEX event and indicate that its dynamically allocated and should be freed with event */
511             fluid_midi_event_set_sysex(evt, metadata, size, TRUE);
512             fluid_track_add_event(track, evt);
513             mf->dtime = 0;
514         }
515
516         return FLUID_OK;
517
518     } else if (status == MIDI_META_EVENT) { /* meta events */
519
520         int result = FLUID_OK;
521
522         /* get the type of the meta message */
523         type = fluid_midi_file_getc(mf);
524         if (type < 0) {
525             FLUID_LOG(FLUID_ERR, "Unexpected end of file");
526             return FLUID_FAILED;
527         }
528
529         /* get the length of the data part */
530         if (fluid_midi_file_read_varlen(mf) != FLUID_OK) {
531             return FLUID_FAILED;
532         }
533
534         if (mf->varlen < 255) {
535             metadata = &static_buf[0];
536         } else {
537             FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__,
538                     __LINE__, mf->varlen);
539             dyn_buf = FLUID_MALLOC(mf->varlen + 1);
540             if (dyn_buf == NULL) {
541                 FLUID_LOG(FLUID_PANIC, "Out of memory");
542                 return FLUID_FAILED;
543             }
544             metadata = dyn_buf;
545         }
546
547         /* read the data */
548         if (mf->varlen) {
549             if (fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK) {
550                 if (dyn_buf) {
551                     FLUID_FREE(dyn_buf);
552                 }
553                 return FLUID_FAILED;
554             }
555         }
556
557         /* handle meta data */
558         switch (type) {
559
560             case MIDI_COPYRIGHT:
561                 metadata[mf->varlen] = 0;
562                 break;
563
564             case MIDI_TRACK_NAME:
565                 metadata[mf->varlen] = 0;
566                 fluid_track_set_name(track, (char *) metadata);
567                 break;
568
569             case MIDI_INST_NAME:
570                 metadata[mf->varlen] = 0;
571                 break;
572
573             case MIDI_LYRIC:
574                 break;
575
576             case MIDI_MARKER:
577                 break;
578
579             case MIDI_CUE_POINT:
580                 break; /* don't care much for text events */
581
582             case MIDI_EOT:
583                 if (mf->varlen != 0) {
584                     FLUID_LOG(FLUID_ERR, "Invalid length for EndOfTrack event");
585                     result = FLUID_FAILED;
586                     break;
587                 }
588                 mf->eot = 1;
589                 evt = new_fluid_midi_event();
590                 if (evt == NULL) {
591                     FLUID_LOG(FLUID_ERR, "Out of memory");
592                     result = FLUID_FAILED;
593                     break;
594                 }
595                 evt->dtime = mf->dtime;
596                 evt->type = MIDI_EOT;
597                 fluid_track_add_event(track, evt);
598                 mf->dtime = 0;
599                 break;
600
601             case MIDI_SET_TEMPO:
602                 if (mf->varlen != 3) {
603                     FLUID_LOG(FLUID_ERR,
604                             "Invalid length for SetTempo meta event");
605                     result = FLUID_FAILED;
606                     break;
607                 }
608                 tempo = (metadata[0] << 16) + (metadata[1] << 8) + metadata[2];
609                 evt = new_fluid_midi_event();
610                 if (evt == NULL) {
611                     FLUID_LOG(FLUID_ERR, "Out of memory");
612                     result = FLUID_FAILED;
613                     break;
614                 }
615                 evt->dtime = mf->dtime;
616                 evt->type = MIDI_SET_TEMPO;
617                 evt->channel = 0;
618                 evt->param1 = tempo;
619                 evt->param2 = 0;
620                 fluid_track_add_event(track, evt);
621                 mf->dtime = 0;
622                 break;
623
624             case MIDI_SMPTE_OFFSET:
625                 if (mf->varlen != 5) {
626                     FLUID_LOG(FLUID_ERR,
627                             "Invalid length for SMPTE Offset meta event");
628                     result = FLUID_FAILED;
629                     break;
630                 }
631                 break; /* we don't use smtp */
632
633             case MIDI_TIME_SIGNATURE:
634                 if (mf->varlen != 4) {
635                     FLUID_LOG(FLUID_ERR,
636                             "Invalid length for TimeSignature meta event");
637                     result = FLUID_FAILED;
638                     break;
639                 }
640                 nominator = metadata[0];
641                 denominator = pow(2.0, (double) metadata[1]);
642                 clocks = metadata[2];
643                 notes = metadata[3];
644
645                 FLUID_LOG(FLUID_DBG,
646                         "signature=%d/%d, metronome=%d, 32nd-notes=%d",
647                         nominator, denominator, clocks, notes);
648
649                 break;
650
651             case MIDI_KEY_SIGNATURE:
652                 if (mf->varlen != 2) {
653                     FLUID_LOG(FLUID_ERR,
654                             "Invalid length for KeySignature meta event");
655                     result = FLUID_FAILED;
656                     break;
657                 }
658                 /* We don't care about key signatures anyway */
659                 /* sf = metadata[0];
660                 mi = metadata[1]; */
661                 break;
662
663             case MIDI_SEQUENCER_EVENT:
664                 break;
665
666             default:
667                 break;
668         }
669
670         if (dyn_buf) {
671             FLUID_LOG(FLUID_DBG, "%s: %d: free metadata", __FILE__, __LINE__);
672             FLUID_FREE(dyn_buf);
673         }
674
675         return result;
676
677     } else { /* channel messages */
678
679         type = status & 0xf0;
680         channel = status & 0x0f;
681
682         /* all channel message have at least 1 byte of associated data */
683         if ((param1 = fluid_midi_file_getc(mf)) < 0) {
684             FLUID_LOG(FLUID_ERR, "Unexpected end of file");
685             return FLUID_FAILED;
686         }
687
688         switch (type) {
689
690             case NOTE_ON:
691                 if ((param2 = fluid_midi_file_getc(mf)) < 0) {
692                     FLUID_LOG(FLUID_ERR, "Unexpected end of file");
693                     return FLUID_FAILED;
694                 }
695                 break;
696
697             case NOTE_OFF:
698                 if ((param2 = fluid_midi_file_getc(mf)) < 0) {
699                     FLUID_LOG(FLUID_ERR, "Unexpected end of file");
700                     return FLUID_FAILED;
701                 }
702                 break;
703
704             case KEY_PRESSURE:
705                 if ((param2 = fluid_midi_file_getc(mf)) < 0) {
706                     FLUID_LOG(FLUID_ERR, "Unexpected end of file");
707                     return FLUID_FAILED;
708                 }
709                 break;
710
711             case CONTROL_CHANGE:
712                 if ((param2 = fluid_midi_file_getc(mf)) < 0) {
713                     FLUID_LOG(FLUID_ERR, "Unexpected end of file");
714                     return FLUID_FAILED;
715                 }
716                 break;
717
718             case PROGRAM_CHANGE:
719                 break;
720
721             case CHANNEL_PRESSURE:
722                 break;
723
724             case PITCH_BEND:
725                 if ((param2 = fluid_midi_file_getc(mf)) < 0) {
726                     FLUID_LOG(FLUID_ERR, "Unexpected end of file");
727                     return FLUID_FAILED;
728                 }
729
730                 param1 = ((param2 & 0x7f) << 7) | (param1 & 0x7f);
731                 param2 = 0;
732                 break;
733
734             default:
735                 /* Can't possibly happen !? */
736                 FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event");
737                 return FLUID_FAILED;
738         }
739         evt = new_fluid_midi_event();
740         if (evt == NULL) {
741             FLUID_LOG(FLUID_ERR, "Out of memory");
742             return FLUID_FAILED;
743         }
744         evt->dtime = mf->dtime;
745         evt->type = type;
746         evt->channel = channel;
747         evt->param1 = param1;
748         evt->param2 = param2;
749         fluid_track_add_event(track, evt);
750         mf->dtime = 0;
751     }
752     return FLUID_OK;
753 }
754
755 /*
756  * fluid_midi_file_get_division
757  */
758 int
759 fluid_midi_file_get_division(fluid_midi_file *midifile)
760 {
761     return midifile->division;
762 }
763
764 /******************************************************
765  *
766  *     fluid_track_t
767  */
768
769 /**
770  * Create a MIDI event structure.
771  * @return New MIDI event structure or NULL when out of memory.
772  */
773 fluid_midi_event_t *
774 new_fluid_midi_event ()
775 {
776     fluid_midi_event_t* evt;
777     evt = FLUID_NEW(fluid_midi_event_t);
778     if (evt == NULL) {
779         FLUID_LOG(FLUID_ERR, "Out of memory");
780         return NULL;
781     }
782     evt->dtime = 0;
783     evt->type = 0;
784     evt->channel = 0;
785     evt->param1 = 0;
786     evt->param2 = 0;
787     evt->next = NULL;
788     evt->paramptr = NULL;
789     return evt;
790 }
791
792 /**
793  * Delete MIDI event structure.
794  * @param evt MIDI event structure
795  * @return Always returns #FLUID_OK
796  */
797 int
798 delete_fluid_midi_event(fluid_midi_event_t *evt)
799 {
800     fluid_midi_event_t *temp;
801
802     while (evt) {
803         temp = evt->next;
804
805         /* Dynamic SYSEX event? - free (param2 indicates if dynamic) */
806         if (evt->type == MIDI_SYSEX && evt->paramptr && evt->param2)
807             FLUID_FREE (evt->paramptr);
808
809         FLUID_FREE(evt);
810         evt = temp;
811     }
812     return FLUID_OK;
813 }
814
815 /**
816  * Get the event type field of a MIDI event structure.
817  * @param evt MIDI event structure
818  * @return Event type field (MIDI status byte without channel)
819  */
820 int
821 fluid_midi_event_get_type(fluid_midi_event_t *evt)
822 {
823     return evt->type;
824 }
825
826 /**
827  * Set the event type field of a MIDI event structure.
828  * @param evt MIDI event structure
829  * @param type Event type field (MIDI status byte without channel)
830  * @return Always returns #FLUID_OK
831  */
832 int
833 fluid_midi_event_set_type(fluid_midi_event_t *evt, int type)
834 {
835     evt->type = type;
836     return FLUID_OK;
837 }
838
839 /**
840  * Get the channel field of a MIDI event structure.
841  * @param evt MIDI event structure
842  * @return Channel field
843  */
844 int
845 fluid_midi_event_get_channel(fluid_midi_event_t *evt)
846 {
847     return evt->channel;
848 }
849
850 /**
851  * Set the channel field of a MIDI event structure.
852  * @param evt MIDI event structure
853  * @param chan MIDI channel field
854  * @return Always returns #FLUID_OK
855  */
856 int
857 fluid_midi_event_set_channel(fluid_midi_event_t *evt, int chan)
858 {
859     evt->channel = chan;
860     return FLUID_OK;
861 }
862
863 /**
864  * Get the key field of a MIDI event structure.
865  * @param evt MIDI event structure
866  * @return MIDI note number (0-127)
867  */
868 int
869 fluid_midi_event_get_key(fluid_midi_event_t *evt)
870 {
871     return evt->param1;
872 }
873
874 /**
875  * Set the key field of a MIDI event structure.
876  * @param evt MIDI event structure
877  * @param v MIDI note number (0-127)
878  * @return Always returns #FLUID_OK
879  */
880 int
881 fluid_midi_event_set_key(fluid_midi_event_t *evt, int v)
882 {
883     evt->param1 = v;
884     return FLUID_OK;
885 }
886
887 /**
888  * Get the velocity field of a MIDI event structure.
889  * @param evt MIDI event structure
890  * @return MIDI velocity number (0-127)
891  */
892 int
893 fluid_midi_event_get_velocity(fluid_midi_event_t *evt)
894 {
895     return evt->param2;
896 }
897
898 /**
899  * Set the velocity field of a MIDI event structure.
900  * @param evt MIDI event structure
901  * @param v MIDI velocity value
902  * @return Always returns #FLUID_OK
903  */
904 int
905 fluid_midi_event_set_velocity(fluid_midi_event_t *evt, int v)
906 {
907     evt->param2 = v;
908     return FLUID_OK;
909 }
910
911 /**
912  * Get the control number of a MIDI event structure.
913  * @param evt MIDI event structure
914  * @return MIDI control number
915  */
916 int
917 fluid_midi_event_get_control(fluid_midi_event_t *evt)
918 {
919     return evt->param1;
920 }
921
922 /**
923  * Set the control field of a MIDI event structure.
924  * @param evt MIDI event structure
925  * @param v MIDI control number
926  * @return Always returns #FLUID_OK
927  */
928 int
929 fluid_midi_event_set_control(fluid_midi_event_t *evt, int v)
930 {
931     evt->param1 = v;
932     return FLUID_OK;
933 }
934
935 /**
936  * Get the value field from a MIDI event structure.
937  * @param evt MIDI event structure
938  * @return Value field
939  */
940 int
941 fluid_midi_event_get_value(fluid_midi_event_t *evt)
942 {
943     return evt->param2;
944 }
945
946 /**
947  * Set the value field of a MIDI event structure.
948  * @param evt MIDI event structure
949  * @param v Value to assign
950  * @return Always returns #FLUID_OK
951  */
952 int
953 fluid_midi_event_set_value(fluid_midi_event_t *evt, int v)
954 {
955     evt->param2 = v;
956     return FLUID_OK;
957 }
958
959 /**
960  * Get the program field of a MIDI event structure.
961  * @param evt MIDI event structure
962  * @return MIDI program number (0-127)
963  */
964 int
965 fluid_midi_event_get_program(fluid_midi_event_t *evt)
966 {
967     return evt->param1;
968 }
969
970 /**
971  * Set the program field of a MIDI event structure.
972  * @param evt MIDI event structure
973  * @param val MIDI program number (0-127)
974  * @return Always returns #FLUID_OK
975  */
976 int
977 fluid_midi_event_set_program(fluid_midi_event_t *evt, int val)
978 {
979     evt->param1 = val;
980     return FLUID_OK;
981 }
982
983 /**
984  * Get the pitch field of a MIDI event structure.
985  * @param evt MIDI event structure
986  * @return Pitch value (14 bit value, 0-16383, 8192 is center)
987  */
988 int
989 fluid_midi_event_get_pitch(fluid_midi_event_t *evt)
990 {
991     return evt->param1;
992 }
993
994 /**
995  * Set the pitch field of a MIDI event structure.
996  * @param evt MIDI event structure
997  * @param val Pitch value (14 bit value, 0-16383, 8192 is center)
998  * @return Always returns FLUID_OK
999  */
1000 int
1001 fluid_midi_event_set_pitch(fluid_midi_event_t *evt, int val)
1002 {
1003     evt->param1 = val;
1004     return FLUID_OK;
1005 }
1006
1007 /**
1008  * Assign sysex data to a MIDI event structure.
1009  * @param evt MIDI event structure
1010  * @param data Pointer to SYSEX data
1011  * @param size Size of SYSEX data
1012  * @param dynamic TRUE if the SYSEX data has been dynamically allocated and
1013  *   should be freed when the event is freed (only applies if event gets destroyed
1014  *   with delete_fluid_midi_event())
1015  * @return Always returns #FLUID_OK
1016  *
1017  * NOTE: Unlike the other event assignment functions, this one sets evt->type.
1018  */
1019 int
1020 fluid_midi_event_set_sysex(fluid_midi_event_t *evt, void *data, int size, int dynamic)
1021 {
1022     evt->type = MIDI_SYSEX;
1023     evt->paramptr = data;
1024     evt->param1 = size;
1025     evt->param2 = dynamic;
1026     return FLUID_OK;
1027 }
1028
1029 /******************************************************
1030  *
1031  *     fluid_track_t
1032  */
1033
1034 /*
1035  * new_fluid_track
1036  */
1037 fluid_track_t *
1038 new_fluid_track(int num)
1039 {
1040     fluid_track_t *track;
1041     track = FLUID_NEW(fluid_track_t);
1042     if (track == NULL) {
1043         return NULL;
1044     }
1045     track->name = NULL;
1046     track->num = num;
1047     track->first = NULL;
1048     track->cur = NULL;
1049     track->last = NULL;
1050     track->ticks = 0;
1051     return track;
1052 }
1053
1054 /*
1055  * delete_fluid_track
1056  */
1057 int
1058 delete_fluid_track(fluid_track_t *track)
1059 {
1060     if (track->name != NULL) {
1061         FLUID_FREE(track->name);
1062     }
1063     if (track->first != NULL) {
1064         delete_fluid_midi_event(track->first);
1065     }
1066     FLUID_FREE(track);
1067     return FLUID_OK;
1068 }
1069
1070 /*
1071  * fluid_track_set_name
1072  */
1073 int
1074 fluid_track_set_name(fluid_track_t *track, char *name)
1075 {
1076     int len;
1077     if (track->name != NULL) {
1078         FLUID_FREE(track->name);
1079     }
1080     if (name == NULL) {
1081         track->name = NULL;
1082         return FLUID_OK;
1083     }
1084     len = FLUID_STRLEN(name);
1085     track->name = FLUID_MALLOC(len + 1);
1086     if (track->name == NULL) {
1087         FLUID_LOG(FLUID_ERR, "Out of memory");
1088         return FLUID_FAILED;
1089     }
1090     FLUID_STRCPY(track->name, name);
1091     return FLUID_OK;
1092 }
1093
1094 /*
1095  * fluid_track_get_name
1096  */
1097 char *
1098 fluid_track_get_name(fluid_track_t *track)
1099 {
1100     return track->name;
1101 }
1102
1103 /*
1104  * fluid_track_get_duration
1105  */
1106 int
1107 fluid_track_get_duration(fluid_track_t *track)
1108 {
1109     int time = 0;
1110     fluid_midi_event_t *evt = track->first;
1111     while (evt != NULL) {
1112         time += evt->dtime;
1113         evt = evt->next;
1114     }
1115     return time;
1116 }
1117
1118 #if 0
1119 /*
1120  * fluid_track_count_events
1121  */
1122 static int
1123 fluid_track_count_events(fluid_track_t *track, int *on, int *off)
1124 {
1125     fluid_midi_event_t *evt = track->first;
1126     while (evt != NULL) {
1127         if (evt->type == NOTE_ON) {
1128             (*on)++;
1129         } else if (evt->type == NOTE_OFF) {
1130             (*off)++;
1131         }
1132         evt = evt->next;
1133     }
1134     return FLUID_OK;
1135 }
1136 #endif
1137
1138 /*
1139  * fluid_track_add_event
1140  */
1141 int
1142 fluid_track_add_event(fluid_track_t *track, fluid_midi_event_t *evt)
1143 {
1144     evt->next = NULL;
1145     if (track->first == NULL) {
1146         track->first = evt;
1147         track->cur = evt;
1148         track->last = evt;
1149     } else {
1150         track->last->next = evt;
1151         track->last = evt;
1152     }
1153     return FLUID_OK;
1154 }
1155
1156 /*
1157  * fluid_track_first_event
1158  */
1159 fluid_midi_event_t *
1160 fluid_track_first_event(fluid_track_t *track)
1161 {
1162     track->cur = track->first;
1163     return track->cur;
1164 }
1165
1166 /*
1167  * fluid_track_next_event
1168  */
1169 fluid_midi_event_t *
1170 fluid_track_next_event(fluid_track_t *track)
1171 {
1172     if (track->cur != NULL) {
1173         track->cur = track->cur->next;
1174     }
1175     return track->cur;
1176 }
1177
1178 /*
1179  * fluid_track_reset
1180  */
1181 int
1182 fluid_track_reset(fluid_track_t *track)
1183 {
1184     track->ticks = 0;
1185     track->cur = track->first;
1186     return FLUID_OK;
1187 }
1188
1189 /*
1190  * fluid_track_send_events
1191  */
1192 int
1193 fluid_track_send_events(fluid_track_t *track,
1194                         fluid_synth_t *synth,
1195                         fluid_player_t *player,
1196                         unsigned int ticks)
1197 {
1198     int status = FLUID_OK;
1199     fluid_midi_event_t *event;
1200
1201     while (1) {
1202
1203         event = track->cur;
1204         if (event == NULL) {
1205             return status;
1206         }
1207
1208         /*              printf("track=%02d\tticks=%05u\ttrack=%05u\tdtime=%05u\tnext=%05u\n", */
1209         /*                     track->num, */
1210         /*                     ticks, */
1211         /*                     track->ticks, */
1212         /*                     event->dtime, */
1213         /*                     track->ticks + event->dtime); */
1214
1215         if (track->ticks + event->dtime > ticks) {
1216             return status;
1217         }
1218
1219         track->ticks += event->dtime;
1220
1221         if (!player || event->type == MIDI_EOT) {
1222         }
1223         else if (event->type == MIDI_SET_TEMPO) {
1224             fluid_player_set_midi_tempo(player, event->param1);
1225         }
1226         else {
1227             if (player->playback_callback)
1228                 player->playback_callback(player->playback_userdata, event);
1229         }
1230
1231         fluid_track_next_event(track);
1232
1233     }
1234     return status;
1235 }
1236
1237 /******************************************************
1238  *
1239  *     fluid_player
1240  */
1241
1242 /**
1243  * Create a new MIDI player.
1244  * @param synth Fluid synthesizer instance to create player for
1245  * @return New MIDI player instance or NULL on error (out of memory)
1246  */
1247 fluid_player_t *
1248 new_fluid_player(fluid_synth_t *synth)
1249 {
1250     int i;
1251     fluid_player_t *player;
1252     player = FLUID_NEW(fluid_player_t);
1253     if (player == NULL) {
1254         FLUID_LOG(FLUID_ERR, "Out of memory");
1255         return NULL;
1256     }
1257     player->status = FLUID_PLAYER_READY;
1258     player->loop = 1;
1259     player->ntracks = 0;
1260     for (i = 0; i < MAX_NUMBER_OF_TRACKS; i++) {
1261         player->track[i] = NULL;
1262     }
1263     player->synth = synth;
1264     player->system_timer = NULL;
1265     player->sample_timer = NULL;
1266     player->playlist = NULL;
1267     player->currentfile = NULL;
1268     player->division = 0;
1269     player->send_program_change = 1;
1270     player->miditempo = 480000;
1271     player->deltatime = 4.0;
1272     player->cur_msec = 0;
1273     player->cur_ticks = 0;
1274     fluid_player_set_playback_callback(player, fluid_synth_handle_midi_event, synth);
1275
1276     player->use_system_timer = fluid_settings_str_equal(synth->settings,
1277             "player.timing-source", "system");
1278
1279     fluid_settings_getint(synth->settings, "player.reset-synth", &i);
1280     player->reset_synth_between_songs = i;
1281
1282     return player;
1283 }
1284
1285 /**
1286  * Delete a MIDI player instance.
1287  * @param player MIDI player instance
1288  * @return Always returns #FLUID_OK
1289  */
1290 int
1291 delete_fluid_player(fluid_player_t *player)
1292 {
1293     fluid_list_t *q;
1294     fluid_playlist_item* pi;
1295
1296     if (player == NULL) {
1297         return FLUID_OK;
1298     }
1299     fluid_player_stop(player);
1300     fluid_player_reset(player);
1301
1302     while (player->playlist != NULL) {
1303         q = player->playlist->next;
1304         pi = (fluid_playlist_item*) player->playlist->data;
1305         FLUID_FREE(pi->filename);
1306         FLUID_FREE(pi->buffer);
1307         FLUID_FREE(pi);
1308         delete1_fluid_list(player->playlist);
1309         player->playlist = q;
1310     }
1311
1312     FLUID_FREE(player);
1313     return FLUID_OK;
1314 }
1315
1316 /**
1317  * Registers settings related to the MIDI player
1318  */
1319 void
1320 fluid_player_settings(fluid_settings_t *settings)
1321 {
1322     /* player.timing-source can be either "system" (use system timer)
1323      or "sample" (use timer based on number of written samples) */
1324     fluid_settings_register_str(settings, "player.timing-source", "sample", 0,
1325             NULL, NULL);
1326     fluid_settings_add_option(settings, "player.timing-source", "sample");
1327     fluid_settings_add_option(settings, "player.timing-source", "system");
1328
1329     /* Selects whether the player should reset the synth between songs, or not. */
1330     fluid_settings_register_int(settings, "player.reset-synth", 1, 0, 1,
1331             FLUID_HINT_TOGGLED, NULL, NULL);
1332 }
1333
1334
1335 int
1336 fluid_player_reset(fluid_player_t *player)
1337 {
1338     int i;
1339
1340     for (i = 0; i < MAX_NUMBER_OF_TRACKS; i++) {
1341         if (player->track[i] != NULL) {
1342             delete_fluid_track(player->track[i]);
1343             player->track[i] = NULL;
1344         }
1345     }
1346     /*  player->current_file = NULL; */
1347     /*  player->status = FLUID_PLAYER_READY; */
1348     /*  player->loop = 1; */
1349     player->ntracks = 0;
1350     player->division = 0;
1351     player->send_program_change = 1;
1352     player->miditempo = 480000;
1353     player->deltatime = 4.0;
1354     return 0;
1355 }
1356
1357 /*
1358  * fluid_player_add_track
1359  */
1360 int
1361 fluid_player_add_track(fluid_player_t *player, fluid_track_t *track)
1362 {
1363     if (player->ntracks < MAX_NUMBER_OF_TRACKS) {
1364         player->track[player->ntracks++] = track;
1365         return FLUID_OK;
1366     } else {
1367         return FLUID_FAILED;
1368     }
1369 }
1370
1371 /*
1372  * fluid_player_count_tracks
1373  */
1374 int
1375 fluid_player_count_tracks(fluid_player_t *player)
1376 {
1377     return player->ntracks;
1378 }
1379
1380 /*
1381  * fluid_player_get_track
1382  */
1383 fluid_track_t *
1384 fluid_player_get_track(fluid_player_t *player, int i)
1385 {
1386     if ((i >= 0) && (i < MAX_NUMBER_OF_TRACKS)) {
1387         return player->track[i];
1388     } else {
1389         return NULL;
1390     }
1391 }
1392
1393 /**
1394  * Change the MIDI callback function. This is usually set to 
1395  * fluid_synth_handle_midi_event, but can optionally be changed
1396  * to a user-defined function instead, for intercepting all MIDI
1397  * messages sent to the synth. You can also use a midi router as 
1398  * the callback function to modify the MIDI messages before sending
1399  * them to the synth. 
1400  * @param player MIDI player instance
1401  * @param handler Pointer to callback function
1402  * @param handler_data Parameter sent to the callback function
1403  * @returns FLUID_OK
1404  * @since 1.1.4
1405  */
1406 int 
1407 fluid_player_set_playback_callback(fluid_player_t* player, 
1408     handle_midi_event_func_t handler, void* handler_data)
1409 {
1410     player->playback_callback = handler;
1411     player->playback_userdata = handler_data;
1412     return FLUID_OK;
1413 }
1414
1415 /**
1416  * Add a MIDI file to a player queue.
1417  * @param player MIDI player instance
1418  * @param midifile File name of the MIDI file to add
1419  * @return #FLUID_OK or #FLUID_FAILED
1420  */
1421 int
1422 fluid_player_add(fluid_player_t *player, const char *midifile)
1423 {
1424     fluid_playlist_item *pi = FLUID_MALLOC(sizeof(fluid_playlist_item));
1425     char* f = FLUID_STRDUP(midifile);
1426     if (!pi || !f) {
1427         FLUID_FREE(pi);
1428         FLUID_FREE(f);
1429         FLUID_LOG(FLUID_PANIC, "Out of memory");
1430         return FLUID_FAILED;
1431     }
1432
1433     pi->filename = f;
1434     pi->buffer = NULL;
1435     pi->buffer_len = 0;
1436     player->playlist = fluid_list_append(player->playlist, pi);
1437     return FLUID_OK;
1438 }
1439
1440 /**
1441  * Add a MIDI file to a player queue, from a buffer in memory.
1442  * @param player MIDI player instance
1443  * @param buffer Pointer to memory containing the bytes of a complete MIDI
1444  *   file. The data is copied, so the caller may free or modify it immediately
1445  *   without affecting the playlist.
1446  * @param len Length of the buffer, in bytes.
1447  * @return #FLUID_OK or #FLUID_FAILED
1448  */
1449 int
1450 fluid_player_add_mem(fluid_player_t* player, const void *buffer, size_t len)
1451 {
1452     /* Take a copy of the buffer, so the caller can free immediately. */
1453     fluid_playlist_item *pi = FLUID_MALLOC(sizeof(fluid_playlist_item));
1454     void *buf_copy = FLUID_MALLOC(len);
1455     if (!pi || !buf_copy) {
1456         FLUID_FREE(pi);
1457         FLUID_FREE(buf_copy);
1458         FLUID_LOG(FLUID_PANIC, "Out of memory");
1459         return FLUID_FAILED;
1460     }
1461
1462     FLUID_MEMCPY(buf_copy, buffer, len);
1463     pi->filename = NULL;
1464     pi->buffer = buf_copy;
1465     pi->buffer_len = len;
1466     player->playlist = fluid_list_append(player->playlist, pi);
1467     return FLUID_OK;
1468 }
1469
1470 /*
1471  * fluid_player_load
1472  */
1473 int
1474 fluid_player_load(fluid_player_t *player, fluid_playlist_item *item)
1475 {
1476     fluid_midi_file *midifile;
1477     char* buffer;
1478     size_t buffer_length;
1479     int buffer_owned;
1480
1481     if (item->filename != NULL)
1482     {
1483         fluid_file fp;
1484         /* This file is specified by filename; load the file from disk */
1485         FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile %s", __FILE__, __LINE__,
1486                 item->filename);
1487         /* Read the entire contents of the file into the buffer */
1488         fp = FLUID_FOPEN(item->filename, "rb");
1489         if (fp == NULL) {
1490             FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file");
1491             return FLUID_FAILED;
1492         }
1493         buffer = fluid_file_read_full(fp, &buffer_length);
1494         if (buffer == NULL)
1495         {
1496             FLUID_FCLOSE(fp);
1497             return FLUID_FAILED;
1498         }
1499         buffer_owned = 1;
1500         FLUID_FCLOSE(fp);
1501     }
1502     else
1503     {
1504         /* This file is specified by a pre-loaded buffer; load from memory */
1505         FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile from memory (%p)",
1506                 __FILE__, __LINE__, item->buffer);
1507         buffer = (char *) item->buffer;
1508         buffer_length = item->buffer_len;
1509         /* Do not free the buffer (it is owned by the playlist) */
1510         buffer_owned = 0;
1511     }
1512
1513     midifile = new_fluid_midi_file(buffer, buffer_length);
1514     if (midifile == NULL) {
1515         if (buffer_owned) {
1516             FLUID_FREE(buffer);
1517         }
1518         return FLUID_FAILED;
1519     }
1520     player->division = fluid_midi_file_get_division(midifile);
1521     fluid_player_set_midi_tempo(player, player->miditempo); // Update deltatime
1522     /*FLUID_LOG(FLUID_DBG, "quarter note division=%d\n", player->division); */
1523
1524     if (fluid_midi_file_load_tracks(midifile, player) != FLUID_OK) {
1525         if (buffer_owned) {
1526             FLUID_FREE(buffer);
1527         }
1528         delete_fluid_midi_file(midifile);
1529         return FLUID_FAILED;
1530     }
1531     delete_fluid_midi_file(midifile);
1532     if (buffer_owned) {
1533         FLUID_FREE(buffer);
1534     }
1535     return FLUID_OK;
1536 }
1537
1538 static void
1539 fluid_player_advancefile(fluid_player_t *player)
1540 {
1541     if (player->playlist == NULL) {
1542         return; /* No files to play */
1543     }
1544     if (player->currentfile != NULL) {
1545         player->currentfile = fluid_list_next(player->currentfile);
1546     }
1547     if (player->currentfile == NULL) {
1548         if (player->loop == 0) {
1549             return; /* We're done playing */
1550         }
1551         if (player->loop > 0) {
1552             player->loop--;
1553         }
1554         player->currentfile = player->playlist;
1555     }
1556 }
1557
1558 static void
1559 fluid_player_playlist_load(fluid_player_t *player, unsigned int msec)
1560 {
1561     fluid_playlist_item* current_playitem;
1562     int i;
1563
1564     do {
1565         fluid_player_advancefile(player);
1566         if (player->currentfile == NULL) {
1567             /* Failed to find next song, probably since we're finished */
1568             player->status = FLUID_PLAYER_DONE;
1569             return;
1570         }
1571
1572         fluid_player_reset(player);
1573         current_playitem = (fluid_playlist_item *) player->currentfile->data;
1574     } while (fluid_player_load(player, current_playitem) != FLUID_OK);
1575
1576     /* Successfully loaded midi file */
1577
1578     player->begin_msec = msec;
1579     player->start_msec = msec;
1580     player->start_ticks = 0;
1581     player->cur_ticks = 0;
1582
1583     if (player->reset_synth_between_songs) {
1584         fluid_synth_system_reset(player->synth);
1585     }
1586
1587     for (i = 0; i < player->ntracks; i++) {
1588         if (player->track[i] != NULL) {
1589             fluid_track_reset(player->track[i]);
1590         }
1591     }
1592 }
1593
1594
1595 /*
1596  * fluid_player_callback
1597  */
1598 int
1599 fluid_player_callback(void *data, unsigned int msec)
1600 {
1601     int i;
1602     int loadnextfile;
1603     int status = FLUID_PLAYER_DONE;
1604     fluid_player_t *player;
1605     fluid_synth_t *synth;
1606     player = (fluid_player_t *) data;
1607     synth = player->synth;
1608
1609     loadnextfile = player->currentfile == NULL ? 1 : 0;
1610     do {
1611         if (loadnextfile) {
1612             loadnextfile = 0;
1613             fluid_player_playlist_load(player, msec);
1614             if (player->currentfile == NULL) {
1615                 return 0;
1616             }
1617         }
1618
1619         player->cur_msec = msec;
1620         player->cur_ticks = (player->start_ticks
1621                 + (int) ((double) (player->cur_msec - player->start_msec)
1622                         / player->deltatime));
1623
1624         for (i = 0; i < player->ntracks; i++) {
1625             if (!fluid_track_eot(player->track[i])) {
1626                 status = FLUID_PLAYER_PLAYING;
1627                 if (fluid_track_send_events(player->track[i], synth, player,
1628                         player->cur_ticks) != FLUID_OK) {
1629                     /* */
1630                 }
1631             }
1632         }
1633
1634         if (status == FLUID_PLAYER_DONE) {
1635             FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec", __FILE__,
1636                     __LINE__, (msec - player->begin_msec) / 1000.0);
1637             loadnextfile = 1;
1638         }
1639     } while (loadnextfile);
1640
1641     player->status = status;
1642
1643     return 1;
1644 }
1645
1646 /**
1647  * Activates play mode for a MIDI player if not already playing.
1648  * @param player MIDI player instance
1649  * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1650  */
1651 int
1652 fluid_player_play(fluid_player_t *player)
1653 {
1654     if (player->status == FLUID_PLAYER_PLAYING) {
1655         return FLUID_OK;
1656     }
1657
1658     if (player->playlist == NULL) {
1659         return FLUID_OK;
1660     }
1661
1662     player->status = FLUID_PLAYER_PLAYING;
1663
1664     if (player->use_system_timer) {
1665         player->system_timer = new_fluid_timer((int) player->deltatime,
1666                 fluid_player_callback, (void *) player, TRUE, FALSE, TRUE);
1667         if (player->system_timer == NULL) {
1668             return FLUID_FAILED;
1669         }
1670     } else {
1671         player->sample_timer = new_fluid_sample_timer(player->synth,
1672                 fluid_player_callback, (void *) player);
1673
1674         if (player->sample_timer == NULL) {
1675             return FLUID_FAILED;
1676         }
1677     }
1678     return FLUID_OK;
1679 }
1680
1681 /**
1682  * Stops a MIDI player.
1683  * @param player MIDI player instance
1684  * @return Always returns #FLUID_OK
1685  */
1686 int
1687 fluid_player_stop(fluid_player_t *player)
1688 {
1689     if (player->system_timer != NULL) {
1690         delete_fluid_timer(player->system_timer);
1691     }
1692     if (player->sample_timer != NULL) {
1693         delete_fluid_sample_timer(player->synth, player->sample_timer);
1694     }
1695     player->status = FLUID_PLAYER_DONE;
1696     player->sample_timer = NULL;
1697     player->system_timer = NULL;
1698     return FLUID_OK;
1699 }
1700
1701 /**
1702  * Get MIDI player status.
1703  * @param player MIDI player instance
1704  * @return Player status (#fluid_player_status)
1705  * @since 1.1.0
1706  */
1707 int
1708 fluid_player_get_status(fluid_player_t *player)
1709 {
1710     return player->status;
1711 }
1712
1713 /**
1714  * Enable looping of a MIDI player 
1715  * @param player MIDI player instance
1716  * @param loop Times left to loop the playlist. -1 means loop infinitely.
1717  * @return Always returns #FLUID_OK
1718  * @since 1.1.0
1719  *
1720  * For example, if you want to loop the playlist twice, set loop to 2 
1721  * and call this function before you start the player.
1722  */
1723 int fluid_player_set_loop(fluid_player_t *player, int loop)
1724 {
1725     player->loop = loop;
1726     return FLUID_OK;
1727 }
1728
1729 /**
1730  * Set the tempo of a MIDI player.
1731  * @param player MIDI player instance
1732  * @param tempo Tempo to set playback speed to (in microseconds per quarter note, as per MIDI file spec)
1733  * @return Always returns #FLUID_OK
1734  */
1735 int fluid_player_set_midi_tempo(fluid_player_t *player, int tempo)
1736 {
1737     player->miditempo = tempo;
1738     player->deltatime = (double) tempo / player->division / 1000.0; /* in milliseconds */
1739     player->start_msec = player->cur_msec;
1740     player->start_ticks = player->cur_ticks;
1741
1742     FLUID_LOG(FLUID_DBG,
1743             "tempo=%d, tick time=%f msec, cur time=%d msec, cur tick=%d",
1744             tempo, player->deltatime, player->cur_msec, player->cur_ticks);
1745
1746     return FLUID_OK;
1747 }
1748
1749 /**
1750  * Set the tempo of a MIDI player in beats per minute.
1751  * @param player MIDI player instance
1752  * @param bpm Tempo in beats per minute
1753  * @return Always returns #FLUID_OK
1754  */
1755 int
1756 fluid_player_set_bpm(fluid_player_t *player, int bpm)
1757 {
1758     return fluid_player_set_midi_tempo(player, (int) ((double) 60 * 1e6 / bpm));
1759 }
1760
1761 /**
1762  * Wait for a MIDI player to terminate (when done playing).
1763  * @param player MIDI player instance
1764  * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1765  */
1766 int
1767 fluid_player_join(fluid_player_t *player)
1768 {
1769     if (player->system_timer) {
1770         return fluid_timer_join(player->system_timer);
1771     } else if (player->sample_timer) {
1772         /* Busy-wait loop, since there's no thread to wait for... */
1773         while (player->status != FLUID_PLAYER_DONE) {
1774 #if defined(WIN32)
1775             Sleep(10);
1776 #else
1777             usleep(10000);
1778 #endif
1779         }
1780     }
1781     return FLUID_OK;
1782 }
1783
1784 /************************************************************************
1785  *       MIDI PARSER
1786  *
1787  */
1788
1789 /*
1790  * new_fluid_midi_parser
1791  */
1792 fluid_midi_parser_t *
1793 new_fluid_midi_parser ()
1794 {
1795     fluid_midi_parser_t *parser;
1796     parser = FLUID_NEW(fluid_midi_parser_t);
1797     if (parser == NULL) {
1798         FLUID_LOG(FLUID_ERR, "Out of memory");
1799         return NULL;
1800     }
1801     parser->status = 0; /* As long as the status is 0, the parser won't do anything -> no need to initialize all the fields. */
1802     return parser;
1803 }
1804
1805 /*
1806  * delete_fluid_midi_parser
1807  */
1808 int
1809 delete_fluid_midi_parser(fluid_midi_parser_t *parser)
1810 {
1811     FLUID_FREE(parser);
1812     return FLUID_OK;
1813 }
1814
1815 /**
1816  * Parse a MIDI stream one character at a time.
1817  * @param parser Parser instance
1818  * @param c Next character in MIDI stream
1819  * @return A parsed MIDI event or NULL if none.  Event is internal and should
1820  *   not be modified or freed and is only valid until next call to this function.
1821  */
1822 fluid_midi_event_t *
1823 fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigned char c)
1824 {
1825     fluid_midi_event_t *event;
1826
1827     /* Real-time messages (0xF8-0xFF) can occur anywhere, even in the middle
1828      * of another message. */
1829     if (c >= 0xF8) {
1830         if (c == MIDI_SYSTEM_RESET) {
1831             parser->event.type = c;
1832             parser->status = 0; /* clear the status */
1833             return &parser->event;
1834         }
1835
1836         return NULL;
1837     }
1838
1839     /* Status byte? - If previous message not yet complete, it is discarded (re-sync). */
1840     if (c & 0x80) {
1841         /* Any status byte terminates SYSEX messages (not just 0xF7) */
1842         if (parser->status == MIDI_SYSEX && parser->nr_bytes > 0) {
1843             event = &parser->event;
1844             fluid_midi_event_set_sysex(event, parser->data, parser->nr_bytes,
1845                     FALSE);
1846         } else
1847             event = NULL;
1848
1849         if (c < 0xF0) /* Voice category message? */
1850         {
1851             parser->channel = c & 0x0F;
1852             parser->status = c & 0xF0;
1853
1854             /* The event consumes x bytes of data... (subtract 1 for the status byte) */
1855             parser->nr_bytes_total = fluid_midi_event_length(parser->status)
1856                     - 1;
1857
1858             parser->nr_bytes = 0; /* 0  bytes read so far */
1859         } else if (c == MIDI_SYSEX) {
1860             parser->status = MIDI_SYSEX;
1861             parser->nr_bytes = 0;
1862         } else
1863             parser->status = 0; /* Discard other system messages (0xF1-0xF7) */
1864
1865         return event; /* Return SYSEX event or NULL */
1866     }
1867
1868     /* Data/parameter byte */
1869
1870     /* Discard data bytes for events we don't care about */
1871     if (parser->status == 0)
1872         return NULL;
1873
1874     /* Max data size exceeded? (SYSEX messages only really) */
1875     if (parser->nr_bytes == FLUID_MIDI_PARSER_MAX_DATA_SIZE) {
1876         parser->status = 0; /* Discard the rest of the message */
1877         return NULL;
1878     }
1879
1880     /* Store next byte */
1881     parser->data[parser->nr_bytes++] = c;
1882
1883     /* Do we still need more data to get this event complete? */
1884     if (parser->nr_bytes < parser->nr_bytes_total)
1885         return NULL;
1886
1887     /* Event is complete, return it.
1888      * Running status byte MIDI feature is also handled here. */
1889     parser->event.type = parser->status;
1890     parser->event.channel = parser->channel;
1891     parser->nr_bytes = 0; /* Reset data size, in case there are additional running status messages */
1892
1893     switch (parser->status) {
1894         case NOTE_OFF:
1895         case NOTE_ON:
1896         case KEY_PRESSURE:
1897         case CONTROL_CHANGE:
1898         case PROGRAM_CHANGE:
1899         case CHANNEL_PRESSURE:
1900             parser->event.param1 = parser->data[0]; /* For example key number */
1901             parser->event.param2 = parser->data[1]; /* For example velocity */
1902             break;
1903         case PITCH_BEND:
1904             /* Pitch-bend is transmitted with 14-bit precision. */
1905             parser->event.param1 = (parser->data[1] << 7) | parser->data[0];
1906             break;
1907         default: /* Unlikely */
1908             return NULL;
1909     }
1910
1911     return &parser->event;
1912 }
1913
1914 /* Purpose:
1915  * Returns the length of a MIDI message. */
1916 static int
1917 fluid_midi_event_length(unsigned char event)
1918 {
1919     switch (event & 0xF0) {
1920         case NOTE_OFF:
1921         case NOTE_ON:
1922         case KEY_PRESSURE:
1923         case CONTROL_CHANGE:
1924         case PITCH_BEND:
1925             return 3;
1926         case PROGRAM_CHANGE:
1927         case CHANNEL_PRESSURE:
1928             return 2;
1929     }
1930     switch (event) {
1931         case MIDI_TIME_CODE:
1932         case MIDI_SONG_SELECT:
1933         case 0xF4:
1934         case 0xF5:
1935             return 2;
1936         case MIDI_TUNE_REQUEST:
1937             return 1;
1938         case MIDI_SONG_POSITION:
1939             return 3;
1940     }
1941     return 1;
1942 }