1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *      By Shawn Hargreaves,
11  *      1 Salisbury Road,
12  *      Market Drayton,
13  *      Shropshire,
14  *      England, TF9 1AJ.
15  *
16  *      The core MIDI file player.
17  *
18  *      Pause and seek functions by George Foot.
19  *
20  *      See readme.txt for copyright information.
21  */
22 
23 
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <limits.h>
28 
29 #include "allegro.h"
30 #include "internal.h"
31 
32 
33 /* maximum number of layers in a single voice */
34 #define MIDI_LAYERS  4
35 
36 
37 typedef struct MIDI_TRACK                       /* a track in the MIDI file */
38 {
39    unsigned char *pos;                          /* position in track data */
40    long timer;                                  /* time until next event */
41    unsigned char running_status;                /* last MIDI event */
42 } MIDI_TRACK;
43 
44 
45 typedef struct MIDI_CHANNEL                     /* a MIDI channel */
46 {
47    int patch;                                   /* current sound */
48    int volume;                                  /* volume controller */
49    int pan;                                     /* pan position */
50    int pitch_bend;                              /* pitch bend position */
51    int new_volume;                              /* cached volume change */
52    int new_pitch_bend;                          /* cached pitch bend */
53    int note[128][MIDI_LAYERS];                  /* status of each note */
54 } MIDI_CHANNEL;
55 
56 
57 typedef struct MIDI_VOICE                       /* a voice on the soundcard */
58 {
59    int channel;                                 /* MIDI channel */
60    int note;                                    /* note (-1 = off) */
61    int volume;                                  /* note velocity */
62    long time;                                   /* when note was triggered */
63 } MIDI_VOICE;
64 
65 
66 typedef struct WAITING_NOTE                     /* a stored note-on request */
67 {
68    int channel;
69    int note;
70    int volume;
71 } WAITING_NOTE;
72 
73 
74 typedef struct PATCH_TABLE                      /* GM -> external synth */
75 {
76    int bank1;                                   /* controller #0 */
77    int bank2;                                   /* controller #32 */
78    int prog;                                    /* program change */
79    int pitch;                                   /* pitch shift */
80 } PATCH_TABLE;
81 
82 
83 volatile long midi_pos = -1;                    /* position in MIDI file */
84 static long midi_pos_counter;                   /* delta for midi_pos */
85 
86 volatile long _midi_tick = 0;                   /* counter for killing notes */
87 
88 static void midi_player();                      /* core MIDI player routine */
89 static void prepare_to_play(MIDI *midi);
90 static void midi_lock_mem();
91 
92 static MIDI *midifile = NULL;                   /* the file that is playing */
93 
94 static int midi_loop = 0;                       /* repeat at eof? */
95 
96 long midi_loop_start = -1;                      /* where to loop back to */
97 long midi_loop_end = -1;                        /* loop at this position */
98 
99 static int midi_semaphore = 0;                  /* reentrancy flag */
100 static int midi_loaded_patches = FALSE;         /* loaded entire patch set? */
101 
102 static int midi_timer_speed;                    /* midi_player's timer speed */
103 static int midi_pos_speed;                      /* MIDI delta -> midi_pos */
104 static int midi_speed;                          /* MIDI delta -> timer */
105 static int midi_new_speed;                      /* for tempo change events */
106 
107 static int old_midi_volume = -1;                /* stored global volume */
108 
109 static int midi_alloc_channel;                  /* so _midi_allocate_voice */
110 static int midi_alloc_note;                     /* knows which note the */
111 static int midi_alloc_vol;                      /* sound is associated with */
112 
113 static MIDI_TRACK midi_track[MIDI_TRACKS];      /* the active tracks */
114 static MIDI_VOICE midi_voice[MIDI_VOICES];      /* synth voice status */
115 static MIDI_CHANNEL midi_channel[16];           /* MIDI channel info */
116 static WAITING_NOTE midi_waiting[MIDI_VOICES];  /* notes still to be played */
117 static PATCH_TABLE patch_table[128];            /* GM -> external synth */
118 
119 static int midi_seeking;                        /* set during seeks */
120 static int midi_looping;                        /* set during loops */
121 
122 /* hook functions */
123 void (*midi_msg_callback)(int msg, int byte1, int byte2) = NULL;
124 void (*midi_meta_callback)(int type, unsigned char *data, int length) = NULL;
125 void (*midi_sysex_callback)(unsigned char *data, int length) = NULL;
126 
127 
128 
129 /* lock_midi:
130  *  Locks a MIDI file into physical memory. Pretty important, since they
131  *  are mostly accessed inside interrupt handlers.
132  */
lock_midi(MIDI * midi)133 void lock_midi(MIDI *midi)
134 {
135    int c;
136 
137    _go32_dpmi_lock_data(midi, sizeof(MIDI));
138 
139    for (c=0; c<MIDI_TRACKS; c++)
140       if (midi->track[c].data)
141 	 _go32_dpmi_lock_data(midi->track[c].data, midi->track[c].len);
142 }
143 
144 
145 
146 /* load_midi:
147  *  Loads a standard MIDI file, returning a pointer to a MIDI structure,
148  *  or NULL on error.
149  */
load_midi(char * filename)150 MIDI *load_midi(char *filename)
151 {
152    int trashtmp;
153    int c;
154    char buf[256];
155    long data;
156    PACKFILE *fp;
157    MIDI *midi;
158    int num_tracks;
159 
160    fp = pack_fopen(filename, F_READ);        /* open the file */
161    if (!fp)
162       return NULL;
163 
164    midi = malloc(sizeof(MIDI));              /* get some memory */
165    if (!midi) {
166       pack_fclose(fp);
167       return NULL;
168    }
169 
170    for (c=0; c<MIDI_TRACKS; c++) {
171       midi->track[c].data = NULL;
172       midi->track[c].len = 0;
173    }
174 
175    pack_fread(buf, 4, fp);                   /* read midi header */
176    if (memcmp(buf, "MThd", 4))
177       goto err;
178 
179    trashtmp=pack_mgetl(fp);                           /* skip header chunk length */
180 
181    data = pack_mgetw(fp);                    /* MIDI file type */
182    if ((data != 0) && (data != 1))
183       goto err;
184 
185    num_tracks = pack_mgetw(fp);              /* number of tracks */
186    if ((num_tracks < 1) || (num_tracks > MIDI_TRACKS))
187       goto err;
188 
189    data = pack_mgetw(fp);                    /* beat divisions */
190    midi->divisions = ABS(data);
191 
192    for (c=0; c<num_tracks; c++) {            /* read each track */
193       pack_fread(buf, 4, fp);                /* read track header */
194       if (memcmp(buf, "MTrk", 4))
195 	 goto err;
196 
197       data = pack_mgetl(fp);                 /* length of track chunk */
198       midi->track[c].len = data;
199 
200       midi->track[c].data = malloc(data);    /* allocate memory */
201       if (!midi->track[c].data)
202 	 goto err;
203 					     /* finally, read track data */
204       if (pack_fread(midi->track[c].data, data, fp) != data)
205 	 goto err;
206    }
207 
208    pack_fclose(fp);
209    lock_midi(midi);
210    return midi;
211 
212    /* oh dear... */
213    err:
214    pack_fclose(fp);
215    destroy_midi(midi);
216    return NULL;
217 }
218 
219 
220 
221 /* destroy_midi:
222  *  Frees the memory being used by a MIDI file.
223  */
destroy_midi(MIDI * midi)224 void destroy_midi(MIDI *midi)
225 {
226    int c;
227 
228    if (midi == midifile)
229       stop_midi();
230 
231    if (midi) {
232       for (c=0; c<MIDI_TRACKS; c++) {
233 	 if (midi->track[c].data) {
234 	    _unlock_dpmi_data(midi->track[c].data, midi->track[c].len);
235 	    free(midi->track[c].data);
236 	 }
237       }
238       _unlock_dpmi_data(midi, sizeof(MIDI));
239       free(midi);
240    }
241 }
242 
243 
244 
245 /* parse_var_len:
246  *  The MIDI file format is a strange thing. Time offsets are only 32 bits,
247  *  yet they are compressed in a weird variable length format. This routine
248  *  reads a variable length integer from a MIDI data stream. It returns the
249  *  number read, and alters the data pointer according to the number of
250  *  bytes it used.
251  */
parse_var_len(unsigned char ** data)252 static unsigned long parse_var_len(unsigned char **data)
253 {
254    unsigned long val = **data & 0x7F;
255 
256    while (**data & 0x80) {
257       (*data)++;
258       val <<= 7;
259       val += (**data & 0x7F);
260    }
261 
262    (*data)++;
263    return val;
264 }
265 
266 static END_OF_FUNCTION(parse_var_len);
267 
268 
269 
270 /* global_volume_fix:
271  *  Converts a note volume, adjusting it according to the global
272  *  _midi_volume variable.
273  */
global_volume_fix(int vol)274 static inline int global_volume_fix(int vol)
275 {
276    if (_midi_volume >= 0)
277       return (vol * _midi_volume) / 256;
278 
279    return vol;
280 }
281 
282 
283 
284 /* sort_out_volume:
285  *  Converts a note volume, adjusting it according to the channel volume
286  *  and the global _midi_volume variable.
287  */
sort_out_volume(int c,int vol)288 static inline int sort_out_volume(int c, int vol)
289 {
290    return global_volume_fix((vol * midi_channel[c].volume) / 128);
291 }
292 
293 
294 
295 /* raw_program_change:
296  *  Sends a program change message to a device capable of handling raw
297  *  MIDI data, using patch mapping tables. Assumes that midi_driver->raw_midi
298  *  isn't NULL, so check before calling it!
299  */
raw_program_change(int channel,int patch)300 static void raw_program_change(int channel, int patch)
301 {
302    if (channel != 9) {
303       /* bank change #1 */
304       if (patch_table[patch].bank1 >= 0) {
305 	 midi_driver->raw_midi(0xB0+channel);
306 	 midi_driver->raw_midi(0);
307 	 midi_driver->raw_midi(patch_table[patch].bank1);
308       }
309 
310       /* bank change #2 */
311       if (patch_table[patch].bank2 >= 0) {
312 	 midi_driver->raw_midi(0xB0+channel);
313 	 midi_driver->raw_midi(32);
314 	 midi_driver->raw_midi(patch_table[patch].bank2);
315       }
316 
317       /* program change */
318       midi_driver->raw_midi(0xC0+channel);
319       midi_driver->raw_midi(patch_table[patch].prog);
320 
321       /* update volume */
322       midi_driver->raw_midi(0xB0+channel);
323       midi_driver->raw_midi(7);
324       midi_driver->raw_midi(global_volume_fix(midi_channel[channel].volume-1));
325    }
326 }
327 
328 static END_OF_FUNCTION(raw_program_change);
329 
330 
331 
332 /* midi_note_off:
333  *  Processes a MIDI note-off event.
334  */
midi_note_off(int channel,int note)335 static void midi_note_off(int channel, int note)
336 {
337    int done = FALSE;
338    int voice, layer;
339    int c;
340 
341    /* can we send raw MIDI data? */
342    if (midi_driver->raw_midi) {
343       if (channel != 9)
344 	 note += patch_table[midi_channel[channel].patch].pitch;
345 
346       midi_driver->raw_midi(0x80+channel);
347       midi_driver->raw_midi(note);
348       midi_driver->raw_midi(0);
349       return;
350    }
351 
352    /* oh well, have to do it the long way... */
353    for (layer=0; layer<MIDI_LAYERS; layer++) {
354       voice = midi_channel[channel].note[note][layer];
355       if (voice >= 0) {
356 	 midi_driver->key_off(voice + midi_driver->basevoice);
357 	 midi_voice[voice].note = -1;
358 	 midi_voice[voice].time = _midi_tick;
359 	 midi_channel[channel].note[note][layer] = -1;
360 	 done = TRUE;
361       }
362    }
363 
364    /* if the note isn't playing, it must still be in the waiting room */
365    if (!done) {
366       for (c=0; c<MIDI_VOICES; c++) {
367 	 if ((midi_waiting[c].channel == channel) &&
368 	     (midi_waiting[c].note == note)) {
369 	    midi_waiting[c].note = -1;
370 	    break;
371 	 }
372       }
373    }
374 }
375 
376 static END_OF_FUNCTION(midi_note_off);
377 
378 
379 
380 /* sort_out_pitch_bend:
381  *  MIDI pitch bend range is + or - two semitones. The low-level soundcard
382  *  drivers can only handle bends up to +1 semitone. This routine converts
383  *  pitch bends from MIDI format to our own format.
384  */
sort_out_pitch_bend(int * bend,int * note)385 static inline void sort_out_pitch_bend(int *bend, int *note)
386 {
387    if (*bend == 0x2000) {
388       *bend = 0;
389       return;
390    }
391 
392    (*bend) -= 0x2000;
393 
394    while (*bend < 0) {
395       (*note)--;
396       (*bend) += 0x1000;
397    }
398 
399    while (*bend >= 0x1000) {
400       (*note)++;
401       (*bend) -= 0x1000;
402    }
403 }
404 
405 
406 
407 /* _midi_allocate_voice:
408  *  Allocates a MIDI voice in the range min-max (inclusive). This is
409  *  intended to be called by the key_on() handlers in the MIDI driver,
410  *  and shouldn't be used by any other code.
411  */
_midi_allocate_voice(int min,int max)412 int _midi_allocate_voice(int min, int max)
413 {
414    int c;
415    int layer;
416    int voice = -1;
417    int best_time = LONG_MAX;
418 
419    if (min < 0)
420       min = 0;
421 
422    if (max < 0)
423       max = midi_driver->voices-1;
424 
425    /* which layer can we use? */
426    for (layer=0; layer<MIDI_LAYERS; layer++)
427       if (midi_channel[midi_alloc_channel].note[midi_alloc_note][layer] < 0)
428 	 break;
429 
430    if (layer >= MIDI_LAYERS)
431       return -1;
432 
433    /* find a free voice */
434    for (c=min; c<=max; c++) {
435       if ((midi_voice[c].note < 0) &&
436 	  (midi_voice[c].time < best_time) &&
437 	  ((c < midi_driver->xmin) || (c > midi_driver->xmax))) {
438 	 voice = c;
439 	 best_time = midi_voice[c].time;
440       }
441    }
442 
443    /* if there are no free voices, kill a note to make room */
444    if (voice < 0) {
445       voice = -1;
446       best_time = LONG_MAX;
447       for (c=min; c<=max; c++) {
448 	 if ((midi_voice[c].time < best_time) &&
449 	     ((c < midi_driver->xmin) || (c > midi_driver->xmax))) {
450 	    voice = c;
451 	    best_time = midi_voice[c].time;
452 	 }
453       }
454       if (voice >= 0)
455 	 midi_note_off(midi_voice[voice].channel, midi_voice[voice].note);
456       else
457 	 return -1;
458    }
459 
460    /* ok, we got it... */
461    midi_voice[voice].channel = midi_alloc_channel;
462    midi_voice[voice].note = midi_alloc_note;
463    midi_voice[voice].volume = midi_alloc_vol;
464    midi_voice[voice].time = _midi_tick;
465    midi_channel[midi_alloc_channel].note[midi_alloc_note][layer] = voice;
466 
467    return voice + midi_driver->basevoice;
468 }
469 
470 END_OF_FUNCTION(_midi_allocate_voice);
471 
472 
473 
474 /* midi_note_on:
475  *  Processes a MIDI note-on event. Tries to find a free soundcard voice,
476  *  and if it can't either cuts off an existing note, or if 'polite' is
477  *  set, just stores the channel, note and volume in the waiting list.
478  */
midi_note_on(int channel,int note,int vol,int polite)479 static void midi_note_on(int channel, int note, int vol, int polite)
480 {
481    int c, layer, inst, bend, corrected_note;
482 
483    /* it's easy if the driver can handle raw MIDI data */
484    if (midi_driver->raw_midi) {
485       if (channel != 9)
486 	 note += patch_table[midi_channel[channel].patch].pitch;
487 
488       midi_driver->raw_midi(0x90+channel);
489       midi_driver->raw_midi(note);
490       midi_driver->raw_midi(vol);
491       return;
492    }
493 
494    /* if the note is already on, turn it off */
495    for (layer=0; layer<MIDI_LAYERS; layer++) {
496       if (midi_channel[channel].note[note][layer] >= 0) {
497 	 midi_note_off(channel, note);
498 	 return;
499       }
500    }
501 
502    /* if zero volume and the note isn't playing, we can just ignore it */
503    if (vol == 0)
504       return;
505 
506    if (channel != 9) {
507       /* are there any free voices? */
508       for (c=0; c<midi_driver->voices; c++)
509 	 if ((midi_voice[c].note < 0) &&
510 	     ((c < midi_driver->xmin) || (c > midi_driver->xmax)))
511 	    break;
512 
513       /* if there are no free voices, remember the note for later */
514       if ((c >= midi_driver->voices) && (polite)) {
515 	 for (c=0; c<MIDI_VOICES; c++) {
516 	    if (midi_waiting[c].note < 0) {
517 	       midi_waiting[c].channel = channel;
518 	       midi_waiting[c].note = note;
519 	       midi_waiting[c].volume = vol;
520 	       break;
521 	    }
522 	 }
523 	 return;
524       }
525    }
526 
527    /* drum sound? */
528    if (channel == 9) {
529       inst = 128+note;
530       corrected_note = 60;
531       bend = 0;
532    }
533    else {
534       inst = midi_channel[channel].patch;
535       corrected_note = note;
536       bend = midi_channel[channel].pitch_bend;
537       sort_out_pitch_bend(&bend, &corrected_note);
538    }
539 
540    /* play the note */
541    midi_alloc_channel = channel;
542    midi_alloc_note = note;
543    midi_alloc_vol = vol;
544 
545    midi_driver->key_on(inst, corrected_note, bend,
546 		       sort_out_volume(channel, vol),
547 		       midi_channel[channel].pan);
548 }
549 
550 static END_OF_FUNCTION(midi_note_on);
551 
552 
553 
554 /* all_notes_off:
555  *  Turns off all active notes.
556  */
all_notes_off(int channel)557 static void all_notes_off(int channel)
558 {
559    if (midi_driver->raw_midi) {
560       midi_driver->raw_midi(0xB0+channel);
561       midi_driver->raw_midi(123);
562       midi_driver->raw_midi(0);
563       return;
564    }
565    else {
566       int note, layer;
567 
568       for (note=0; note<128; note++)
569 	 for (layer=0; layer<MIDI_LAYERS; layer++)
570 	    if (midi_channel[channel].note[note][layer] >= 0)
571 	       midi_note_off(channel, note);
572    }
573 }
574 
575 static END_OF_FUNCTION(all_notes_off);
576 
577 
578 
579 /* reset_controllers:
580  *  Resets volume, pan, pitch bend, etc, to default positions.
581  */
reset_controllers(int channel)582 static void reset_controllers(int channel)
583 {
584    midi_channel[channel].new_volume = 128;
585    midi_channel[channel].new_pitch_bend = 0x2000;
586 
587    switch (channel % 3) {
588       case 0:  midi_channel[channel].pan = ((channel/3) & 1) ? 60 : 68; break;
589       case 1:  midi_channel[channel].pan = 104; break;
590       case 2:  midi_channel[channel].pan = 24; break;
591    }
592 
593    if (midi_driver->raw_midi) {
594       midi_driver->raw_midi(0xB0+channel);
595       midi_driver->raw_midi(10);
596       midi_driver->raw_midi(midi_channel[channel].pan);
597    }
598 }
599 
600 static END_OF_FUNCTION(reset_controllers);
601 
602 
603 
604 /* update_controllers:
605  *  Checks cached controller information and updates active voices.
606  */
update_controllers()607 static void update_controllers()
608 {
609    int c, c2;
610 
611    for (c=0; c<16; c++) {
612       /* check for volume controller change */
613       if ((midi_channel[c].volume != midi_channel[c].new_volume) ||
614 	  (old_midi_volume != _midi_volume)) {
615 	 midi_channel[c].volume = midi_channel[c].new_volume;
616 	 if (midi_driver->raw_midi) {
617 	    midi_driver->raw_midi(0xB0+c);
618 	    midi_driver->raw_midi(7);
619 	    midi_driver->raw_midi(global_volume_fix(midi_channel[c].volume-1));
620 	 }
621 	 else {
622 	    for (c2=0; c2<MIDI_VOICES; c2++) {
623 	       if ((midi_voice[c2].channel == c) &&
624 		  (midi_voice[c2].note >= 0)) {
625 		  int vol = sort_out_volume(c, midi_voice[c2].volume);
626 		  midi_driver->set_volume(c2 + midi_driver->basevoice, vol);
627 	       }
628 	    }
629 	 }
630       }
631 
632       /* check for pitch bend change */
633       if (midi_channel[c].pitch_bend != midi_channel[c].new_pitch_bend) {
634 	 midi_channel[c].pitch_bend = midi_channel[c].new_pitch_bend;
635 	 if (midi_driver->raw_midi) {
636 	    midi_driver->raw_midi(0xE0+c);
637 	    midi_driver->raw_midi(midi_channel[c].pitch_bend & 0x7F);
638 	    midi_driver->raw_midi(midi_channel[c].pitch_bend >> 7);
639 	 }
640 	 else {
641 	    for (c2=0; c2<MIDI_VOICES; c2++) {
642 	       if ((midi_voice[c2].channel == c) &&
643 		  (midi_voice[c2].note >= 0)) {
644 		  int bend = midi_channel[c].pitch_bend;
645 		  int note = midi_voice[c2].note;
646 		  sort_out_pitch_bend(&bend, &note);
647 		  midi_driver->set_pitch(c2 + midi_driver->basevoice, note, bend);
648 	       }
649 	    }
650 	 }
651       }
652    }
653 
654    old_midi_volume = _midi_volume;
655 }
656 
657 static END_OF_FUNCTION(update_controllers);
658 
659 
660 
661 /* process_controller:
662  *  Deals with a MIDI controller message on the specified channel.
663  */
process_controller(int channel,int ctrl,int data)664 static void process_controller(int channel, int ctrl, int data)
665 {
666    switch (ctrl) {
667 
668       case 7:                                   /* main volume */
669 	 midi_channel[channel].new_volume = data+1;
670 	 break;
671 
672       case 10:                                  /* pan */
673 	 midi_channel[channel].pan = data;
674 	 if (midi_driver->raw_midi) {
675 	    midi_driver->raw_midi(0xB0+channel);
676 	    midi_driver->raw_midi(10);
677 	    midi_driver->raw_midi(data);
678 	 }
679 	 break;
680 
681       case 121:                                 /* reset all controllers */
682 	 reset_controllers(channel);
683 	 break;
684 
685       case 123:                                 /* all notes off */
686       case 124:                                 /* omni mode off */
687       case 125:                                 /* omni mode on */
688       case 126:                                 /* poly mode off */
689       case 127:                                 /* poly mode on */
690 	 all_notes_off(channel);
691 	 break;
692    }
693 }
694 
695 static END_OF_FUNCTION(process_controller);
696 
697 
698 
699 /* process_meta_event:
700  *  Processes the next meta-event on the specified track.
701  */
process_meta_event(unsigned char ** pos,long * timer)702 static void process_meta_event(unsigned char **pos, long *timer)
703 {
704    unsigned char metatype = *((*pos)++);
705    long length = parse_var_len(pos);
706    long tempo;
707 
708    if (midi_meta_callback)
709       midi_meta_callback(metatype, *pos, length);
710 
711    if (metatype == 0x2F) {                      /* end of track */
712       *pos = NULL;
713       *timer = LONG_MAX;
714       return;
715    }
716 
717    if (metatype == 0x51) {                      /* tempo change */
718       tempo = (*pos)[0] * 0x10000L + (*pos)[1] * 0x100 + (*pos)[2];
719       midi_new_speed = (tempo/1000) * (TIMERS_PER_SECOND/1000);
720       midi_new_speed /= midifile->divisions;
721    }
722 
723    (*pos) += length;
724 }
725 
726 static END_OF_FUNCTION(process_meta_event);
727 
728 
729 
730 /* process_midi_event:
731  *  Processes the next MIDI event on the specified track.
732  */
process_midi_event(unsigned char ** pos,unsigned char * running_status,long * timer)733 static void process_midi_event(unsigned char **pos, unsigned char *running_status, long *timer)
734 {
735    unsigned char byte1, byte2;
736    int channel;
737    unsigned char event;
738    long l;
739 
740    event = *((*pos)++);
741 
742    if (event & 0x80) {                          /* regular message */
743       /* no running status for sysex and meta-events! */
744       if ((event != 0xF0) && (event != 0xF7) && (event != 0xFF))
745 	 *running_status = event;
746       byte1 = (*pos)[0];
747       byte2 = (*pos)[1];
748    }
749    else {                                       /* use running status */
750       byte1 = event;
751       byte2 = (*pos)[0];
752       event = *running_status;
753       (*pos)--;
754    }
755 
756    /* program callback? */
757    if ((midi_msg_callback) &&
758        (event != 0xF0) && (event != 0xF7) && (event != 0xFF))
759       midi_msg_callback(event, byte1, byte2);
760 
761    channel = event & 0x0F;
762 
763    switch (event>>4) {
764 
765       case 0x08:                                /* note off */
766 	 midi_note_off(channel, byte1);
767 	 (*pos) += 2;
768 	 break;
769 
770       case 0x09:                                /* note on */
771 	 midi_note_on(channel, byte1, byte2, 1);
772 	 (*pos) += 2;
773 	 break;
774 
775       case 0x0A:                                /* note aftertouch */
776 	 (*pos) += 2;
777 	 break;
778 
779       case 0x0B:                                /* control change */
780 	 process_controller(channel, byte1, byte2);
781 	 (*pos) += 2;
782 	 break;
783 
784       case 0x0C:                                /* program change */
785 	 midi_channel[channel].patch = byte1;
786 	 if (midi_driver->raw_midi)
787 	    raw_program_change(channel, byte1);
788 	 (*pos) += 1;
789 	 break;
790 
791       case 0x0D:                                /* channel aftertouch */
792 	 (*pos) += 1;
793 	 break;
794 
795       case 0x0E:                                /* pitch bend */
796 	 midi_channel[channel].new_pitch_bend = byte1 + (byte2<<7);
797 	 (*pos) += 2;
798 	 break;
799 
800       case 0x0F:                                /* special event */
801 	 switch (event) {
802 	    case 0xF0:                          /* sysex */
803 	    case 0xF7:
804 	       l = parse_var_len(pos);
805 	       if (midi_sysex_callback)
806 		  midi_sysex_callback(*pos, l);
807 	       (*pos) += l;
808 	       break;
809 
810 	    case 0xF2:                          /* song position */
811 	       (*pos) += 2;
812 	       break;
813 
814 	    case 0xF3:                          /* song select */
815 	       (*pos)++;
816 	       break;
817 
818 	    case 0xFF:                          /* meta-event */
819 	       process_meta_event(pos, timer);
820 	       break;
821 
822 	    default:
823 	       /* the other special events don't have any data bytes,
824 		  so we don't need to bother skipping past them */
825 	       break;
826 	 }
827 	 break;
828 
829       default:
830 	 /* something has gone badly wrong if we ever get to here */
831 	 break;
832    }
833 }
834 
835 static END_OF_FUNCTION(process_midi_event);
836 
837 
838 
839 /* midi_player:
840  *  The core MIDI player: to be used as a timer callback.
841  */
midi_player()842 static void midi_player()
843 {
844    int c;
845    long l;
846    int active;
847 
848    if (!midifile)
849       return;
850 
851    if (midi_semaphore) {
852       midi_timer_speed += BPS_TO_TIMER(40);
853       install_int_ex(midi_player, BPS_TO_TIMER(40));
854       return;
855    }
856 
857    midi_semaphore = TRUE;
858    _midi_tick++;
859 
860    do_it_all_again:
861 
862    for (c=0; c<MIDI_VOICES; c++)
863       midi_waiting[c].note = -1;
864 
865    /* deal with each track in turn... */
866    for (c=0; c<MIDI_TRACKS; c++) {
867       if (midi_track[c].pos) {
868 	 midi_track[c].timer -= midi_timer_speed;
869 
870 	 /* while events are waiting, process them */
871 	 while (midi_track[c].timer <= 0) {
872 	    process_midi_event(&midi_track[c].pos,
873 			       &midi_track[c].running_status,
874 			       &midi_track[c].timer);
875 
876 	    /* read next time offset */
877 	    if (midi_track[c].pos) {
878 	       l = parse_var_len(&midi_track[c].pos);
879 	       l *= midi_speed;
880 	       midi_track[c].timer += l;
881 	    }
882 	 }
883       }
884    }
885 
886    /* update global position value */
887    midi_pos_counter -= midi_timer_speed;
888    while (midi_pos_counter <= 0) {
889       midi_pos_counter += midi_pos_speed;
890       midi_pos++;
891    }
892 
893    /* tempo change? */
894    if (midi_new_speed > 0) {
895       for (c=0; c<MIDI_TRACKS; c++) {
896 	 if (midi_track[c].pos) {
897 	    midi_track[c].timer /= midi_speed;
898 	    midi_track[c].timer *= midi_new_speed;
899 	 }
900       }
901       midi_pos_counter /= midi_speed;
902       midi_pos_counter *= midi_new_speed;
903 
904       midi_speed = midi_new_speed;
905       midi_pos_speed = midi_new_speed * midifile->divisions;
906       midi_new_speed = -1;
907    }
908 
909    /* figure out how long until we need to be called again */
910    active = 0;
911    midi_timer_speed = LONG_MAX;
912    for (c=0; c<MIDI_TRACKS; c++) {
913       if (midi_track[c].pos) {
914 	 active = 1;
915 	 if (midi_track[c].timer < midi_timer_speed)
916 	    midi_timer_speed = midi_track[c].timer;
917       }
918    }
919 
920    /* end of the music? */
921    if ((!active) || ((midi_loop_end > 0) && (midi_pos >= midi_loop_end))) {
922       if ((midi_loop) && (!midi_looping)) {
923 	 if (midi_loop_start > 0) {
924 	    remove_int(midi_player);
925 	    midi_semaphore = FALSE;
926 	    midi_looping = TRUE;
927 	    if (midi_seek(midi_loop_start) != 0) {
928 	       midi_looping = FALSE;
929 	       stop_midi();
930 	       return;
931 	    }
932 	    midi_looping = FALSE;
933 	    midi_semaphore = TRUE;
934 	    goto do_it_all_again;
935 	 }
936 	 else {
937 	    for (c=0; c<16; c++)
938 	       all_notes_off(c);
939 	    prepare_to_play(midifile);
940 	    goto do_it_all_again;
941 	 }
942       }
943       else {
944 	 stop_midi();
945 	 midi_semaphore = FALSE;
946 	 return;
947       }
948    }
949 
950    /* reprogram the timer */
951    if (midi_timer_speed < BPS_TO_TIMER(40))
952       midi_timer_speed = BPS_TO_TIMER(40);
953 
954    if (!midi_seeking)
955       install_int_ex(midi_player, midi_timer_speed);
956 
957    /* controller changes are cached and only processed here, so we can
958       condense streams of controller data into just a few voice updates */
959    update_controllers();
960 
961    /* and deal with any notes that are still waiting to be played */
962    for (c=0; c<MIDI_VOICES; c++)
963       if (midi_waiting[c].note >= 0)
964 	 midi_note_on(midi_waiting[c].channel, midi_waiting[c].note,
965 		      midi_waiting[c].volume, 0);
966 
967    midi_semaphore = FALSE;
968 }
969 
970 static END_OF_FUNCTION(midi_player);
971 
972 
973 
974 /* midi_init:
975  *  Sets up the MIDI player ready for use. Returns non-zero on failure.
976  */
midi_init()977 static int midi_init()
978 {
979    int c, c2, c3;
980    int argc;
981    char **argv;
982    char buf[16];
983 
984    midi_loaded_patches = FALSE;
985 
986    midi_lock_mem();
987 
988    for (c=0; c<16; c++) {
989       midi_channel[c].volume = 128;
990       midi_channel[c].pitch_bend = 0x2000;
991 
992       for (c2=0; c2<128; c2++)
993 	 for (c3=0; c3<MIDI_LAYERS; c3++)
994 	    midi_channel[c].note[c2][c3] = -1;
995    }
996 
997    for (c=0; c<MIDI_VOICES; c++) {
998       midi_voice[c].note = -1;
999       midi_voice[c].time = 0;
1000    }
1001 
1002    for (c=0; c<128; c++) {
1003       sprintf(buf, "p%d", c+1);
1004       argv = get_config_argv("midimap", buf, &argc);
1005 
1006       if ((argv) && (argc == 4)) {
1007 	 patch_table[c].bank1 = atoi(argv[0]);
1008 	 patch_table[c].bank2 = atoi(argv[1]);
1009 	 patch_table[c].prog  = atoi(argv[2]);
1010 	 patch_table[c].pitch = atoi(argv[3]);
1011       }
1012       else {
1013 	 patch_table[c].bank1 = -1;
1014 	 patch_table[c].bank2 = -1;
1015 	 patch_table[c].prog = c;
1016 	 patch_table[c].pitch = 0;
1017       }
1018    }
1019 
1020 /*	 register_datafile_object(DAT_MIDI, NULL, (void (*)(void *))destroy_midi);*/
1021 
1022    return 0;
1023 }
1024 
1025 
1026 
1027 /* midi_exit:
1028  *  Turns off all active notes and removes the timer handler.
1029  */
midi_exit()1030 static void midi_exit()
1031 {
1032    stop_midi();
1033 }
1034 
1035 
1036 
1037 /* load_patches:
1038  *  Scans through a MIDI file and identifies which patches it uses, passing
1039  *  them to the soundcard driver so it can load whatever samples are
1040  *  neccessary.
1041  */
load_patches(MIDI * midi)1042 static int load_patches(MIDI *midi)
1043 {
1044    char patches[128], drums[128];
1045    unsigned char *p, *end;
1046    unsigned char running_status, event;
1047    long l;
1048    int c;
1049 
1050    for (c=0; c<128; c++)                        /* initialise to unused */
1051       patches[c] = drums[c] = FALSE;
1052 
1053    patches[0] = TRUE;                           /* always load the piano */
1054 
1055    for (c=0; c<MIDI_TRACKS; c++) {              /* for each track... */
1056       p = midi->track[c].data;
1057       end = p + midi->track[c].len;
1058       running_status = 0;
1059 
1060       while (p < end) {                         /* work through data stream */
1061 	 event = *p;
1062 	 if (event & 0x80) {                    /* regular message */
1063 	    p++;
1064 	    if ((event != 0xF0) && (event != 0xF7) && (event != 0xFF))
1065 	       running_status = event;
1066 	 }
1067 	 else                                   /* use running status */
1068 	    event = running_status;
1069 
1070 	 switch (event>>4) {
1071 
1072 	    case 0x0C:                          /* program change! */
1073 	       patches[*p] = TRUE;
1074 	       p++;
1075 	       break;
1076 
1077 	    case 0x09:                          /* note on, is it a drum? */
1078 	       if ((event & 0x0F) == 9)
1079 		  drums[*p] = TRUE;
1080 	       p += 2;
1081 	       break;
1082 
1083 	    case 0x08:                          /* note off */
1084 	    case 0x0A:                          /* note aftertouch */
1085 	    case 0x0B:                          /* control change */
1086 	    case 0x0E:                          /* pitch bend */
1087 	       p += 2;
1088 	       break;
1089 
1090 	    case 0x0D:                          /* channel aftertouch */
1091 	       p += 1;
1092 	       break;
1093 
1094 	    case 0x0F:                          /* special event */
1095 	       switch (event) {
1096 		  case 0xF0:                    /* sysex */
1097 		  case 0xF7:
1098 		     l = parse_var_len(&p);
1099 		     p += l;
1100 		     break;
1101 
1102 		  case 0xF2:                    /* song position */
1103 		     p += 2;
1104 		     break;
1105 
1106 		  case 0xF3:                    /* song select */
1107 		     p++;
1108 		     break;
1109 
1110 		  case 0xFF:                    /* meta-event */
1111 		     p++;
1112 		     l = parse_var_len(&p);
1113 		     p += l;
1114 		     break;
1115 
1116 		  default:
1117 		     /* the other special events don't have any data bytes,
1118 			so we don't need to bother skipping past them */
1119 		     break;
1120 	       }
1121 	       break;
1122 
1123 	    default:
1124 	       /* something has gone badly wrong if we ever get to here */
1125 	       break;
1126 	 }
1127 
1128 	 if (p < end)                           /* skip time offset */
1129 	    parse_var_len(&p);
1130       }
1131    }
1132 
1133    /* tell the driver to do its stuff */
1134    return midi_driver->load_patches(patches, drums);
1135 }
1136 
1137 
1138 
1139 /* prepare_to_play:
1140  *  Sets up all the global variables needed to play the specified file.
1141  */
prepare_to_play(MIDI * midi)1142 static void prepare_to_play(MIDI *midi)
1143 {
1144    int c;
1145 
1146    for (c=0; c<16; c++)
1147       reset_controllers(c);
1148 
1149    update_controllers();
1150 
1151    midifile = midi;
1152    midi_pos = 0;
1153    midi_pos_counter = 0;
1154    midi_speed = TIMERS_PER_SECOND / 2 / midifile->divisions;   /* 120 bpm */
1155    midi_new_speed = -1;
1156    midi_pos_speed = midi_speed * midifile->divisions;
1157    midi_timer_speed = 0;
1158    midi_seeking = 0;
1159    midi_looping = 0;
1160 
1161    for (c=0; c<16; c++) {
1162       midi_channel[c].patch = 0;
1163       if (midi_driver->raw_midi)
1164 	 raw_program_change(c, 0);
1165    }
1166 
1167    for (c=0; c<MIDI_TRACKS; c++) {
1168       if (midi->track[c].data) {
1169 	 midi_track[c].pos = midi->track[c].data;
1170 	 midi_track[c].timer = parse_var_len(&midi_track[c].pos);
1171 	 midi_track[c].timer *= midi_speed;
1172       }
1173       else {
1174 	 midi_track[c].pos = NULL;
1175 	 midi_track[c].timer = LONG_MAX;
1176       }
1177       midi_track[c].running_status = 0;
1178    }
1179 }
1180 
1181 static END_OF_FUNCTION(prepare_to_play);
1182 
1183 
1184 
1185 /* play_midi:
1186  *  Starts playing the specified MIDI file. If loop is set, the MIDI file
1187  *  will be repeated until replaced with something else, otherwise it will
1188  *  stop at the end of the file. Passing a NULL MIDI file will stop whatever
1189  *  music is currently playing: allegro.h defines the macro stop_midi() to
1190  *  be play_midi(NULL, FALSE); Returns non-zero if an error occurs (this
1191  *  may happen if a patch-caching wavetable driver is unable to load the
1192  *  required samples).
1193  */
play_midi(MIDI * midi,int loop)1194 int play_midi(MIDI *midi, int loop)
1195 {
1196    int c;
1197 
1198    remove_int(midi_player);
1199 
1200    for (c=0; c<16; c++)
1201       all_notes_off(c);
1202 
1203    if (midi) {
1204       if (!midi_loaded_patches)
1205 	 if (load_patches(midi) != 0)
1206 	    return -1;
1207 
1208       midi_loop = loop;
1209       midi_loop_start = -1;
1210       midi_loop_end = -1;
1211 
1212       prepare_to_play(midi);
1213 
1214       /* arbitrary speed, midi_player() will adjust it */
1215       install_int(midi_player, 20);
1216    }
1217    else {
1218       midifile = NULL;
1219       midi_pos = -1;
1220    }
1221 
1222    return 0;
1223 }
1224 
1225 END_OF_FUNCTION(play_midi);
1226 
1227 
1228 
1229 /* play_looped_midi:
1230  *  Like play_midi(), but the file loops from the specified end position
1231  *  back to the specified start position (the end position can be -1 to
1232  *  indicate the end of the file).
1233  */
play_looped_midi(MIDI * midi,int loop_start,int loop_end)1234 int play_looped_midi(MIDI *midi, int loop_start, int loop_end)
1235 {
1236    if (play_midi(midi, TRUE) != 0)
1237       return -1;
1238 
1239    midi_loop_start = loop_start;
1240    midi_loop_end = loop_end;
1241 
1242    return 0;
1243 }
1244 
1245 
1246 
1247 /* stop_midi:
1248  *  Stops whatever MIDI file is currently playing.
1249  */
stop_midi()1250 void stop_midi()
1251 {
1252    play_midi(NULL, FALSE);
1253 }
1254 
1255 END_OF_FUNCTION(stop_midi);
1256 
1257 
1258 
1259 /* midi_pause:
1260  *  Pauses the currently playing MIDI file.
1261  */
midi_pause()1262 void midi_pause()
1263 {
1264    int c;
1265 
1266    if (!midifile)
1267       return;
1268 
1269    remove_int(midi_player);
1270 
1271    for (c=0; c<16; c++)
1272       all_notes_off(c);
1273 }
1274 
1275 END_OF_FUNCTION(midi_pause);
1276 
1277 
1278 
1279 /* midi_resume:
1280  *  Resumes playing a paused MIDI file.
1281  */
midi_resume()1282 void midi_resume()
1283 {
1284    if (!midifile)
1285       return;
1286 
1287    install_int_ex(midi_player, midi_timer_speed);
1288 }
1289 
1290 END_OF_FUNCTION(midi_resume);
1291 
1292 
1293 
1294 /* midi_seek:
1295  *  Seeks to the given midi_pos in the current MIDI file. If the target
1296  *  is earlier in the file than the current midi_pos it seeks from the
1297  *  beginning; otherwise it seeks from the current position. Returns zero
1298  *  if successful, non-zero if it hit the end of the file (1 means it
1299  *  stopped playing, 2 means it looped back to the start).
1300  */
midi_seek(int target)1301 int midi_seek(int target)
1302 {
1303    int old_midi_loop;
1304    MIDI *old_midifile;
1305    MIDI_DRIVER *old_driver;
1306    int old_patch[16];
1307    int old_volume[16];
1308    int old_pan[16];
1309    int old_pitch_bend[16];
1310    int c;
1311 
1312    if (!midifile)
1313       return -1;
1314 
1315    /* first stop the player */
1316    midi_pause();
1317 
1318    /* store current settings */
1319    for (c=0; c<16; c++) {
1320       old_patch[c] = midi_channel[c].patch;
1321       old_volume[c] = midi_channel[c].volume;
1322       old_pan[c] = midi_channel[c].pan;
1323       old_pitch_bend[c] = midi_channel[c].pitch_bend;
1324    }
1325 
1326    /* save some variables and give temporary values */
1327    old_driver = midi_driver;
1328    midi_driver = &midi_none;
1329    old_midi_loop = midi_loop;
1330    midi_loop = 0;
1331    old_midifile = midifile;
1332 
1333    /* set flag to tell midi_player not to reinstall itself */
1334    midi_seeking = 1;
1335 
1336    /* are we seeking backwards? If so, skip back to the start of the file */
1337    if (target <= midi_pos)
1338       prepare_to_play(midifile);
1339 
1340    /* now sit back and let midi_player get to the position */
1341    while ((midi_pos < target) && (midi_pos != -1)) {
1342       int mmpc = midi_pos_counter;
1343       int mmp = midi_pos;
1344 
1345       mmpc -= midi_timer_speed;
1346       while (mmpc <= 0) {
1347 	 mmpc += midi_pos_speed;
1348 	 mmp++;
1349       }
1350 
1351       if (mmp >= target)
1352 	 break;
1353 
1354       midi_player();
1355    }
1356 
1357    /* restore previously saved variables */
1358    midi_loop = old_midi_loop;
1359    midi_driver = old_driver;
1360    midi_seeking = 0;
1361 
1362    if (midi_pos != -1) {
1363       /* refresh the driver with any changed parameters */
1364       if (midi_driver->raw_midi) {
1365 	 for (c=0; c<16; c++) {
1366 	    /* program change (this sets the volume as well) */
1367 	    if ((midi_channel[c].patch != old_patch[c]) ||
1368 		(midi_channel[c].volume != old_volume[c]))
1369 	       raw_program_change(c, midi_channel[c].patch);
1370 
1371 	    /* pan */
1372 	    if (midi_channel[c].pan != old_pan[c]) {
1373 	       midi_driver->raw_midi(0xB0+c);
1374 	       midi_driver->raw_midi(10);
1375 	       midi_driver->raw_midi(midi_channel[c].pan);
1376 	    }
1377 
1378 	    /* pitch bend */
1379 	    if (midi_channel[c].pitch_bend != old_pitch_bend[c]) {
1380 	       midi_driver->raw_midi(0xE0+c);
1381 	       midi_driver->raw_midi(midi_channel[c].pitch_bend & 0x7F);
1382 	       midi_driver->raw_midi(midi_channel[c].pitch_bend >> 7);
1383 	    }
1384 	 }
1385       }
1386 
1387       /* if we didn't hit the end of the file, continue playing */
1388       if (!midi_looping)
1389 	 install_int(midi_player, 20);
1390 
1391       return 0;
1392    }
1393 
1394    if ((midi_loop) && (!midi_looping)) {  /* was file was looped? */
1395       prepare_to_play(old_midifile);
1396       install_int(midi_player, 20);
1397       return 2;                           /* seek past EOF => file restarted */
1398    }
1399 
1400    return 1;                              /* seek past EOF => file stopped */
1401 }
1402 
1403 END_OF_FUNCTION(midi_seek);
1404 
1405 
1406 
1407 /* midi_out:
1408  *  Inserts MIDI command bytes into the output stream, in realtime.
1409  */
midi_out(unsigned char * data,int length)1410 void midi_out(unsigned char *data, int length)
1411 {
1412    unsigned char *pos = data;
1413    unsigned char running_status = 0;
1414    long timer = 0;
1415 
1416    midi_semaphore = TRUE;
1417    _midi_tick++;
1418 
1419    while (pos < data+length)
1420       process_midi_event(&pos, &running_status, &timer);
1421 
1422    midi_semaphore = FALSE;
1423 }
1424 
1425 
1426 
1427 /* load_midi_patches:
1428  *  Tells the MIDI driver to preload the entire sample set.
1429  */
load_midi_patches()1430 int load_midi_patches()
1431 {
1432    char patches[128], drums[128];
1433    int c, ret;
1434 
1435    for (c=0; c<128; c++)
1436       patches[c] = drums[c] = TRUE;
1437 
1438    midi_semaphore = TRUE;
1439    ret = midi_driver->load_patches(patches, drums);
1440    midi_semaphore = FALSE;
1441 
1442    midi_loaded_patches = TRUE;
1443 
1444    return ret;
1445 }
1446 
1447 
1448 
1449 /* midi_lock_mem:
1450  *  Locks all the memory that the midi player touches inside the timer
1451  *  interrupt handler (which is most of it).
1452  */
midi_lock_mem()1453 static void midi_lock_mem()
1454 {
1455    LOCK_VARIABLE(midi_pos);
1456    LOCK_VARIABLE(midi_pos_counter);
1457    LOCK_VARIABLE(_midi_tick);
1458    LOCK_VARIABLE(midifile);
1459    LOCK_VARIABLE(midi_semaphore);
1460    LOCK_VARIABLE(midi_loop);
1461    LOCK_VARIABLE(midi_loop_start);
1462    LOCK_VARIABLE(midi_loop_end);
1463    LOCK_VARIABLE(midi_timer_speed);
1464    LOCK_VARIABLE(midi_pos_speed);
1465    LOCK_VARIABLE(midi_speed);
1466    LOCK_VARIABLE(midi_new_speed);
1467    LOCK_VARIABLE(old_midi_volume);
1468    LOCK_VARIABLE(midi_alloc_channel);
1469    LOCK_VARIABLE(midi_alloc_note);
1470    LOCK_VARIABLE(midi_alloc_vol);
1471    LOCK_VARIABLE(midi_track);
1472    LOCK_VARIABLE(midi_voice);
1473    LOCK_VARIABLE(midi_channel);
1474    LOCK_VARIABLE(midi_waiting);
1475    LOCK_VARIABLE(patch_table);
1476    LOCK_VARIABLE(midi_msg_callback);
1477    LOCK_VARIABLE(midi_meta_callback);
1478    LOCK_VARIABLE(midi_sysex_callback);
1479    LOCK_VARIABLE(midi_seeking);
1480    LOCK_VARIABLE(midi_looping);
1481    LOCK_FUNCTION(parse_var_len);
1482    LOCK_FUNCTION(raw_program_change);
1483    LOCK_FUNCTION(midi_note_off);
1484    LOCK_FUNCTION(_midi_allocate_voice);
1485    LOCK_FUNCTION(midi_note_on);
1486    LOCK_FUNCTION(all_notes_off);
1487    LOCK_FUNCTION(reset_controllers);
1488    LOCK_FUNCTION(update_controllers);
1489    LOCK_FUNCTION(process_controller);
1490    LOCK_FUNCTION(process_meta_event);
1491    LOCK_FUNCTION(process_midi_event);
1492    LOCK_FUNCTION(midi_player);
1493    LOCK_FUNCTION(prepare_to_play);
1494    LOCK_FUNCTION(play_midi);
1495    LOCK_FUNCTION(stop_midi);
1496    LOCK_FUNCTION(midi_pause);
1497    LOCK_FUNCTION(midi_resume);
1498    LOCK_FUNCTION(midi_seek);
1499 }
1500 
1501 
1502 
1503 /* midi_constructor:
1504  *  Register my functions with the code in sound.c.
1505  */
1506 static void midi_constructor() __attribute__ ((constructor));
midi_constructor()1507 static void midi_constructor()
1508 {
1509    _midi_init = midi_init;
1510    _midi_exit = midi_exit;
1511 }
1512 
1513