1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License
7  * as published by the Free Software Foundation; either version 2.1 of
8  * the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA
19  */
20 
21 
22 /*
23  2002 : API design by Peter Hanappe and Antoine Schmitt
24  August 2002 : Implementation by Antoine Schmitt as@gratin.org
25                as part of the infiniteCD author project
26                http://www.infiniteCD.org/
27  Oct4.2002 : AS : corrected bug in heap allocation, that caused a crash during sequencer free.
28 */
29 
30 
31 #include "fluid_event.h"
32 #include "fluidsynth_priv.h"
33 
34 /***************************************************************
35  *
36  *                           SEQUENCER EVENTS
37  */
38 
39 /* Event alloc/free */
40 
41 void
fluid_event_clear(fluid_event_t * evt)42 fluid_event_clear(fluid_event_t *evt)
43 {
44     FLUID_MEMSET(evt, 0, sizeof(fluid_event_t));
45 
46     // by default, no type
47     evt->dest = -1;
48     evt->src = -1;
49     evt->type = -1;
50 }
51 
52 /**
53  * Create a new sequencer event structure.
54  * @return New sequencer event structure or NULL if out of memory
55  */
56 fluid_event_t *
new_fluid_event()57 new_fluid_event()
58 {
59     fluid_event_t *evt;
60 
61     evt = FLUID_NEW(fluid_event_t);
62 
63     if(evt == NULL)
64     {
65         FLUID_LOG(FLUID_PANIC, "event: Out of memory\n");
66         return NULL;
67     }
68 
69     fluid_event_clear(evt);
70 
71     return(evt);
72 }
73 
74 /**
75  * Delete a sequencer event structure.
76  * @param evt Sequencer event structure created by new_fluid_event().
77  */
78 void
delete_fluid_event(fluid_event_t * evt)79 delete_fluid_event(fluid_event_t *evt)
80 {
81     fluid_return_if_fail(evt != NULL);
82 
83     FLUID_FREE(evt);
84 }
85 
86 /**
87  * Set the time field of a sequencer event.
88  * @internal
89  * @param evt Sequencer event structure
90  * @param time Time value to assign
91  */
92 void
fluid_event_set_time(fluid_event_t * evt,unsigned int time)93 fluid_event_set_time(fluid_event_t *evt, unsigned int time)
94 {
95     evt->time = time;
96 }
97 
98 /**
99  * Set source of a sequencer event. \c src must be a unique sequencer ID or -1 if not set.
100  * @param evt Sequencer event structure
101  * @param src Unique sequencer ID
102  */
103 void
fluid_event_set_source(fluid_event_t * evt,fluid_seq_id_t src)104 fluid_event_set_source(fluid_event_t *evt, fluid_seq_id_t src)
105 {
106     evt->src = src;
107 }
108 
109 /**
110  * Set destination of this sequencer event, i.e. the sequencer client this event will be sent to. \c dest must be a unique sequencer ID.
111  * @param evt Sequencer event structure
112  * @param dest The destination unique sequencer ID
113  */
114 void
fluid_event_set_dest(fluid_event_t * evt,fluid_seq_id_t dest)115 fluid_event_set_dest(fluid_event_t *evt, fluid_seq_id_t dest)
116 {
117     evt->dest = dest;
118 }
119 
120 /**
121  * Set a sequencer event to be a timer event.
122  * @param evt Sequencer event structure
123  * @param data User supplied data pointer
124  */
125 void
fluid_event_timer(fluid_event_t * evt,void * data)126 fluid_event_timer(fluid_event_t *evt, void *data)
127 {
128     evt->type = FLUID_SEQ_TIMER;
129     evt->data = data;
130 }
131 
132 /**
133  * Set a sequencer event to be a note on event.
134  * @param evt Sequencer event structure
135  * @param channel MIDI channel number
136  * @param key MIDI note number (0-127)
137  * @param vel MIDI velocity value (0-127)
138  */
139 void
fluid_event_noteon(fluid_event_t * evt,int channel,short key,short vel)140 fluid_event_noteon(fluid_event_t *evt, int channel, short key, short vel)
141 {
142     evt->type = FLUID_SEQ_NOTEON;
143     evt->channel = channel;
144     evt->key = key;
145     evt->vel = vel;
146 }
147 
148 /**
149  * Set a sequencer event to be a note off event.
150  * @param evt Sequencer event structure
151  * @param channel MIDI channel number
152  * @param key MIDI note number (0-127)
153  */
154 void
fluid_event_noteoff(fluid_event_t * evt,int channel,short key)155 fluid_event_noteoff(fluid_event_t *evt, int channel, short key)
156 {
157     evt->type = FLUID_SEQ_NOTEOFF;
158     evt->channel = channel;
159     evt->key = key;
160 }
161 
162 /**
163  * Set a sequencer event to be a note duration event.
164  * @param evt Sequencer event structure
165  * @param channel MIDI channel number
166  * @param key MIDI note number (0-127)
167  * @param vel MIDI velocity value (0-127)
168  * @param duration Duration of note in the time scale used by the sequencer (by default milliseconds)
169  */
170 void
fluid_event_note(fluid_event_t * evt,int channel,short key,short vel,unsigned int duration)171 fluid_event_note(fluid_event_t *evt, int channel, short key, short vel, unsigned int duration)
172 {
173     evt->type = FLUID_SEQ_NOTE;
174     evt->channel = channel;
175     evt->key = key;
176     evt->vel = vel;
177     evt->duration = duration;
178 }
179 
180 /**
181  * Set a sequencer event to be an all sounds off event.
182  * @param evt Sequencer event structure
183  * @param channel MIDI channel number
184  */
185 void
fluid_event_all_sounds_off(fluid_event_t * evt,int channel)186 fluid_event_all_sounds_off(fluid_event_t *evt, int channel)
187 {
188     evt->type = FLUID_SEQ_ALLSOUNDSOFF;
189     evt->channel = channel;
190 }
191 
192 /**
193  * Set a sequencer event to be a all notes off event.
194  * @param evt Sequencer event structure
195  * @param channel MIDI channel number
196  */
197 void
fluid_event_all_notes_off(fluid_event_t * evt,int channel)198 fluid_event_all_notes_off(fluid_event_t *evt, int channel)
199 {
200     evt->type = FLUID_SEQ_ALLNOTESOFF;
201     evt->channel = channel;
202 }
203 
204 /**
205  * Set a sequencer event to be a bank select event.
206  * @param evt Sequencer event structure
207  * @param channel MIDI channel number
208  * @param bank_num MIDI bank number (0-16383)
209  */
210 void
fluid_event_bank_select(fluid_event_t * evt,int channel,short bank_num)211 fluid_event_bank_select(fluid_event_t *evt, int channel, short bank_num)
212 {
213     evt->type = FLUID_SEQ_BANKSELECT;
214     evt->channel = channel;
215     evt->control = bank_num;
216 }
217 
218 /**
219  * Set a sequencer event to be a program change event.
220  * @param evt Sequencer event structure
221  * @param channel MIDI channel number
222  * @param val MIDI program number (0-127)
223  */
224 void
fluid_event_program_change(fluid_event_t * evt,int channel,short val)225 fluid_event_program_change(fluid_event_t *evt, int channel, short val)
226 {
227     evt->type = FLUID_SEQ_PROGRAMCHANGE;
228     evt->channel = channel;
229     evt->value = val;
230 }
231 
232 /**
233  * Set a sequencer event to be a program select event.
234  * @param evt Sequencer event structure
235  * @param channel MIDI channel number
236  * @param sfont_id SoundFont ID number
237  * @param bank_num MIDI bank number (0-16383)
238  * @param preset_num MIDI preset number (0-127)
239  */
240 void
fluid_event_program_select(fluid_event_t * evt,int channel,unsigned int sfont_id,short bank_num,short preset_num)241 fluid_event_program_select(fluid_event_t *evt, int channel,
242                            unsigned int sfont_id, short bank_num, short preset_num)
243 {
244     evt->type = FLUID_SEQ_PROGRAMSELECT;
245     evt->channel = channel;
246     evt->duration = sfont_id;
247     evt->value = preset_num;
248     evt->control = bank_num;
249 }
250 
251 /**
252  * Set a sequencer event to be an any control change event (for internal use).
253  * @param evt Sequencer event structure
254  * @param channel MIDI channel number
255  */
256 void
fluid_event_any_control_change(fluid_event_t * evt,int channel)257 fluid_event_any_control_change(fluid_event_t *evt, int channel)
258 {
259     evt->type = FLUID_SEQ_ANYCONTROLCHANGE;
260     evt->channel = channel;
261 }
262 
263 /**
264  * Set a sequencer event to be a pitch bend event.
265  * @param evt Sequencer event structure
266  * @param channel MIDI channel number
267  * @param pitch MIDI pitch bend value (0-16383, 8192 = no bend)
268  */
269 void
fluid_event_pitch_bend(fluid_event_t * evt,int channel,int pitch)270 fluid_event_pitch_bend(fluid_event_t *evt, int channel, int pitch)
271 {
272     evt->type = FLUID_SEQ_PITCHBEND;
273     evt->channel = channel;
274 
275     if(pitch < 0)
276     {
277         pitch = 0;
278     }
279 
280     if(pitch > 16383)
281     {
282         pitch = 16383;
283     }
284 
285     evt->pitch = pitch;
286 }
287 
288 /**
289  * Set a sequencer event to be a pitch wheel sensitivity event.
290  * @param evt Sequencer event structure
291  * @param channel MIDI channel number
292  * @param value MIDI pitch wheel sensitivity value in semitones
293  */
294 void
fluid_event_pitch_wheelsens(fluid_event_t * evt,int channel,short value)295 fluid_event_pitch_wheelsens(fluid_event_t *evt, int channel, short value)
296 {
297     evt->type = FLUID_SEQ_PITCHWHEELSENS;
298     evt->channel = channel;
299     evt->value = value;
300 }
301 
302 /**
303  * Set a sequencer event to be a modulation event.
304  * @param evt Sequencer event structure
305  * @param channel MIDI channel number
306  * @param val MIDI modulation value (0-127)
307  */
308 void
fluid_event_modulation(fluid_event_t * evt,int channel,short val)309 fluid_event_modulation(fluid_event_t *evt, int channel, short val)
310 {
311     evt->type = FLUID_SEQ_MODULATION;
312     evt->channel = channel;
313 
314     if(val < 0)
315     {
316         val = 0;
317     }
318 
319     if(val > 127)
320     {
321         val = 127;
322     }
323 
324     evt->value = val;
325 }
326 
327 /**
328  * Set a sequencer event to be a MIDI sustain event.
329  * @param evt Sequencer event structure
330  * @param channel MIDI channel number
331  * @param val MIDI sustain value (0-127)
332  */
333 void
fluid_event_sustain(fluid_event_t * evt,int channel,short val)334 fluid_event_sustain(fluid_event_t *evt, int channel, short val)
335 {
336     evt->type = FLUID_SEQ_SUSTAIN;
337     evt->channel = channel;
338 
339     if(val < 0)
340     {
341         val = 0;
342     }
343 
344     if(val > 127)
345     {
346         val = 127;
347     }
348 
349     evt->value = val;
350 }
351 
352 /**
353  * Set a sequencer event to be a MIDI control change event.
354  * @param evt Sequencer event structure
355  * @param channel MIDI channel number
356  * @param control MIDI control number (0-127)
357  * @param val MIDI control value (0-127)
358  */
359 void
fluid_event_control_change(fluid_event_t * evt,int channel,short control,short val)360 fluid_event_control_change(fluid_event_t *evt, int channel, short control, short val)
361 {
362     evt->type = FLUID_SEQ_CONTROLCHANGE;
363     evt->channel = channel;
364     evt->control = control;
365     evt->value = val;
366 }
367 
368 /**
369  * Set a sequencer event to be a stereo pan event.
370  * @param evt Sequencer event structure
371  * @param channel MIDI channel number
372  * @param val MIDI panning value (0-127, 0=left, 64 = middle, 127 = right)
373  */
374 void
fluid_event_pan(fluid_event_t * evt,int channel,short val)375 fluid_event_pan(fluid_event_t *evt, int channel, short val)
376 {
377     evt->type = FLUID_SEQ_PAN;
378     evt->channel = channel;
379 
380     if(val < 0)
381     {
382         val = 0;
383     }
384 
385     if(val > 127)
386     {
387         val = 127;
388     }
389 
390     evt->value = val;
391 }
392 
393 /**
394  * Set a sequencer event to be a volume event.
395  * @param evt Sequencer event structure
396  * @param channel MIDI channel number
397  * @param val Volume value (0-127)
398  */
399 void
fluid_event_volume(fluid_event_t * evt,int channel,short val)400 fluid_event_volume(fluid_event_t *evt, int channel, short val)
401 {
402     evt->type = FLUID_SEQ_VOLUME;
403     evt->channel = channel;
404 
405     if(val < 0)
406     {
407         val = 0;
408     }
409 
410     if(val > 127)
411     {
412         val = 127;
413     }
414 
415     evt->value = val;
416 }
417 
418 /**
419  * Set a sequencer event to be a reverb send event.
420  * @param evt Sequencer event structure
421  * @param channel MIDI channel number
422  * @param val Reverb amount (0-127)
423  */
424 void
fluid_event_reverb_send(fluid_event_t * evt,int channel,short val)425 fluid_event_reverb_send(fluid_event_t *evt, int channel, short val)
426 {
427     evt->type = FLUID_SEQ_REVERBSEND;
428     evt->channel = channel;
429 
430     if(val < 0)
431     {
432         val = 0;
433     }
434 
435     if(val > 127)
436     {
437         val = 127;
438     }
439 
440     evt->value = val;
441 }
442 
443 /**
444  * Set a sequencer event to be a chorus send event.
445  * @param evt Sequencer event structure
446  * @param channel MIDI channel number
447  * @param val Chorus amount (0-127)
448  */
449 void
fluid_event_chorus_send(fluid_event_t * evt,int channel,short val)450 fluid_event_chorus_send(fluid_event_t *evt, int channel, short val)
451 {
452     evt->type = FLUID_SEQ_CHORUSSEND;
453     evt->channel = channel;
454 
455     if(val < 0)
456     {
457         val = 0;
458     }
459 
460     if(val > 127)
461     {
462         val = 127;
463     }
464 
465     evt->value = val;
466 }
467 
468 
469 /**
470  * Set a sequencer event to be an unregistering event.
471  * @param evt Sequencer event structure
472  * @since 1.1.0
473  */
474 void
fluid_event_unregistering(fluid_event_t * evt)475 fluid_event_unregistering(fluid_event_t *evt)
476 {
477     evt->type = FLUID_SEQ_UNREGISTERING;
478 }
479 
480 /**
481  * Set a sequencer event to be a channel-wide aftertouch event.
482  * @param evt Sequencer event structure
483  * @param channel MIDI channel number
484  * @param val Aftertouch amount (0-127)
485  * @since 1.1.0
486  */
487 void
fluid_event_channel_pressure(fluid_event_t * evt,int channel,short val)488 fluid_event_channel_pressure(fluid_event_t *evt, int channel, short val)
489 {
490     evt->type = FLUID_SEQ_CHANNELPRESSURE;
491     evt->channel = channel;
492 
493     if(val < 0)
494     {
495         val = 0;
496     }
497 
498     if(val > 127)
499     {
500         val = 127;
501     }
502 
503     evt->value = val;
504 }
505 
506 /**
507  * Set a sequencer event to be a polyphonic aftertouch event.
508  * @param evt Sequencer event structure
509  * @param channel MIDI channel number
510  * @param key MIDI note number (0-127)
511  * @param val Aftertouch amount (0-127)
512  * @since 2.0.0
513  */
514 void
fluid_event_key_pressure(fluid_event_t * evt,int channel,short key,short val)515 fluid_event_key_pressure(fluid_event_t *evt, int channel, short key, short val)
516 {
517     evt->type = FLUID_SEQ_KEYPRESSURE;
518     evt->channel = channel;
519 
520     if(key < 0)
521     {
522         key = 0;
523     }
524 
525     if(key > 127)
526     {
527         key = 127;
528     }
529 
530     if(val < 0)
531     {
532         val = 0;
533     }
534 
535     if(val > 127)
536     {
537         val = 127;
538     }
539 
540     evt->key = key;
541     evt->value = val;
542 }
543 
544 /**
545  * Set a sequencer event to be a midi system reset event.
546  * @param evt Sequencer event structure
547  * @since 1.1.0
548  */
549 void
fluid_event_system_reset(fluid_event_t * evt)550 fluid_event_system_reset(fluid_event_t *evt)
551 {
552     evt->type = FLUID_SEQ_SYSTEMRESET;
553 }
554 
555 
556 
557 /*
558  * Accessing event data
559  */
560 
561 /**
562  * Get the event type (#fluid_seq_event_type) field from a sequencer event structure.
563  * @param evt Sequencer event structure
564  * @return Event type (#fluid_seq_event_type).
565  */
fluid_event_get_type(fluid_event_t * evt)566 int fluid_event_get_type(fluid_event_t *evt)
567 {
568     return evt->type;
569 }
570 
571 /**
572  * @internal
573  * Get the time field from a sequencer event structure.
574  * @param evt Sequencer event structure
575  * @return Time value
576  */
fluid_event_get_time(fluid_event_t * evt)577 unsigned int fluid_event_get_time(fluid_event_t *evt)
578 {
579     return evt->time;
580 }
581 
582 /**
583  * Get the source sequencer client from a sequencer event structure.
584  * @param evt Sequencer event structure
585  * @return source field of the sequencer event
586  */
fluid_event_get_source(fluid_event_t * evt)587 fluid_seq_id_t fluid_event_get_source(fluid_event_t *evt)
588 {
589     return evt->src;
590 }
591 
592 /**
593  * Get the dest sequencer client from a sequencer event structure.
594  * @param evt Sequencer event structure
595  * @return dest field of the sequencer event
596  */
fluid_event_get_dest(fluid_event_t * evt)597 fluid_seq_id_t fluid_event_get_dest(fluid_event_t *evt)
598 {
599     return evt->dest;
600 }
601 
602 /**
603  * Get the MIDI channel field from a sequencer event structure.
604  * @param evt Sequencer event structure
605  * @return MIDI zero-based channel number
606  */
fluid_event_get_channel(fluid_event_t * evt)607 int fluid_event_get_channel(fluid_event_t *evt)
608 {
609     return evt->channel;
610 }
611 
612 /**
613  * Get the MIDI note field from a sequencer event structure.
614  * @param evt Sequencer event structure
615  * @return MIDI note number (0-127)
616  */
fluid_event_get_key(fluid_event_t * evt)617 short fluid_event_get_key(fluid_event_t *evt)
618 {
619     return evt->key;
620 }
621 
622 /**
623  * Get the MIDI velocity field from a sequencer event structure.
624  * @param evt Sequencer event structure
625  * @return MIDI velocity value (0-127)
626  */
fluid_event_get_velocity(fluid_event_t * evt)627 short fluid_event_get_velocity(fluid_event_t *evt)
628 
629 {
630     return evt->vel;
631 }
632 
633 /**
634  * Get the MIDI control number field from a sequencer event structure.
635  * @param evt Sequencer event structure
636  * @return MIDI control number (0-127)
637  */
fluid_event_get_control(fluid_event_t * evt)638 short fluid_event_get_control(fluid_event_t *evt)
639 {
640     return evt->control;
641 }
642 
643 /**
644  * Get the value field from a sequencer event structure.
645  * @param evt Sequencer event structure
646  * @return Value field of event.
647  *
648  * The Value field is used by the following event types:
649  * #FLUID_SEQ_PROGRAMCHANGE, #FLUID_SEQ_PROGRAMSELECT (preset_num),
650  * #FLUID_SEQ_PITCHWHEELSENS, #FLUID_SEQ_MODULATION, #FLUID_SEQ_SUSTAIN,
651  * #FLUID_SEQ_CONTROLCHANGE, #FLUID_SEQ_PAN, #FLUID_SEQ_VOLUME,
652  * #FLUID_SEQ_REVERBSEND, #FLUID_SEQ_CHORUSSEND.
653  */
fluid_event_get_value(fluid_event_t * evt)654 short fluid_event_get_value(fluid_event_t *evt)
655 {
656     return evt->value;
657 }
658 
659 /**
660  * Get the data field from a sequencer event structure.
661  * @param evt Sequencer event structure
662  * @return Data field of event.
663  *
664  * Used by the #FLUID_SEQ_TIMER event type.
665  */
fluid_event_get_data(fluid_event_t * evt)666 void *fluid_event_get_data(fluid_event_t *evt)
667 {
668     return evt->data;
669 }
670 
671 /**
672  * Get the duration field from a sequencer event structure.
673  * @param evt Sequencer event structure
674  * @return Note duration value in the time scale used by the sequencer (by default milliseconds)
675  *
676  * Used by the #FLUID_SEQ_NOTE event type.
677  */
fluid_event_get_duration(fluid_event_t * evt)678 unsigned int fluid_event_get_duration(fluid_event_t *evt)
679 {
680     return evt->duration;
681 }
682 
683 /**
684  * Get the MIDI bank field from a sequencer event structure.
685  * @param evt Sequencer event structure
686  * @return MIDI bank number (0-16383)
687  *
688  * Used by the #FLUID_SEQ_BANKSELECT and #FLUID_SEQ_PROGRAMSELECT
689  * event types.
690  */
fluid_event_get_bank(fluid_event_t * evt)691 short fluid_event_get_bank(fluid_event_t *evt)
692 {
693     return evt->control;
694 }
695 
696 /**
697  * Get the pitch field from a sequencer event structure.
698  * @param evt Sequencer event structure
699  * @return MIDI pitch bend pitch value (0-16383, 8192 = no bend)
700  *
701  * Used by the #FLUID_SEQ_PITCHBEND event type.
702  */
fluid_event_get_pitch(fluid_event_t * evt)703 int fluid_event_get_pitch(fluid_event_t *evt)
704 {
705     return evt->pitch;
706 }
707 
708 /**
709  * Get the MIDI program field from a sequencer event structure.
710  * @param evt Sequencer event structure
711  * @return MIDI program number (0-127)
712  *
713  * Used by the #FLUID_SEQ_PROGRAMCHANGE and #FLUID_SEQ_PROGRAMSELECT
714  * event types.
715  */
716 short
fluid_event_get_program(fluid_event_t * evt)717 fluid_event_get_program(fluid_event_t *evt)
718 {
719     return evt->value;
720 }
721 
722 /**
723  * Get the SoundFont ID field from a sequencer event structure.
724  * @param evt Sequencer event structure
725  * @return SoundFont identifier value.
726  *
727  * Used by the #FLUID_SEQ_PROGRAMSELECT event type.
728  */
729 unsigned int
fluid_event_get_sfont_id(fluid_event_t * evt)730 fluid_event_get_sfont_id(fluid_event_t *evt)
731 {
732     return evt->duration;
733 }
734 
735 
736 
737 /********************/
738 /* heap management  */
739 /********************/
740 
741 fluid_evt_heap_t *
_fluid_evt_heap_init(int nbEvents)742 _fluid_evt_heap_init(int nbEvents)
743 {
744 #ifdef HEAP_WITH_DYNALLOC
745 
746     int i;
747     fluid_evt_heap_t *heap;
748     fluid_evt_entry *tmp;
749 
750     heap = FLUID_NEW(fluid_evt_heap_t);
751 
752     if(heap == NULL)
753     {
754         FLUID_LOG(FLUID_PANIC, "sequencer: Out of memory\n");
755         return NULL;
756     }
757 
758     heap->freelist = NULL;
759     fluid_mutex_init(heap->mutex);
760 
761     /* LOCK */
762     fluid_mutex_lock(heap->mutex);
763 
764     /* Allocate the event entries */
765     for(i = 0; i < nbEvents; i++)
766     {
767         tmp = FLUID_NEW(fluid_evt_entry);
768         tmp->next = heap->freelist;
769         heap->freelist = tmp;
770     }
771 
772     /* UNLOCK */
773     fluid_mutex_unlock(heap->mutex);
774 
775 
776 #else
777     int i;
778     fluid_evt_heap_t *heap;
779     int siz = 2 * sizeof(fluid_evt_entry *) + sizeof(fluid_evt_entry) * nbEvents;
780 
781     heap = (fluid_evt_heap_t *)FLUID_MALLOC(siz);
782 
783     if(heap == NULL)
784     {
785         FLUID_LOG(FLUID_PANIC, "sequencer: Out of memory\n");
786         return NULL;
787     }
788 
789     FLUID_MEMSET(heap, 0, siz);
790 
791     /* link all heap events */
792     {
793         fluid_evt_entry *tmp = &(heap->pool);
794 
795         for(i = 0 ; i < nbEvents - 1 ; i++)
796         {
797             tmp[i].next = &(tmp[i + 1]);
798         }
799 
800         tmp[nbEvents - 1].next = NULL;
801 
802         /* set head & tail */
803         heap->tail = &(tmp[nbEvents - 1]);
804         heap->head = &(heap->pool);
805     }
806 #endif
807     return (heap);
808 }
809 
810 void
_fluid_evt_heap_free(fluid_evt_heap_t * heap)811 _fluid_evt_heap_free(fluid_evt_heap_t *heap)
812 {
813 #ifdef HEAP_WITH_DYNALLOC
814     fluid_evt_entry *tmp, *next;
815 
816     /* LOCK */
817     fluid_mutex_lock(heap->mutex);
818 
819     tmp = heap->freelist;
820 
821     while(tmp)
822     {
823         next = tmp->next;
824         FLUID_FREE(tmp);
825         tmp = next;
826     }
827 
828     /* UNLOCK */
829     fluid_mutex_unlock(heap->mutex);
830     fluid_mutex_destroy(heap->mutex);
831 
832     FLUID_FREE(heap);
833 
834 #else
835     FLUID_FREE(heap);
836 #endif
837 }
838 
839 fluid_evt_entry *
_fluid_seq_heap_get_free(fluid_evt_heap_t * heap)840 _fluid_seq_heap_get_free(fluid_evt_heap_t *heap)
841 {
842 #ifdef HEAP_WITH_DYNALLOC
843     fluid_evt_entry *evt = NULL;
844 
845     /* LOCK */
846     fluid_mutex_lock(heap->mutex);
847 
848 #if !defined(MACOS9)
849 
850     if(heap->freelist == NULL)
851     {
852         heap->freelist = FLUID_NEW(fluid_evt_entry);
853 
854         if(heap->freelist != NULL)
855         {
856             heap->freelist->next = NULL;
857         }
858     }
859 
860 #endif
861 
862     evt = heap->freelist;
863 
864     if(evt != NULL)
865     {
866         heap->freelist = heap->freelist->next;
867         evt->next = NULL;
868     }
869 
870     /* UNLOCK */
871     fluid_mutex_unlock(heap->mutex);
872 
873     return evt;
874 
875 #else
876     fluid_evt_entry *evt;
877 
878     if(heap->head == NULL)
879     {
880         return NULL;
881     }
882 
883     /* take from head of the heap */
884     /* critical - should threadlock ? */
885     evt = heap->head;
886     heap->head = heap->head->next;
887 
888     return evt;
889 #endif
890 }
891 
892 void
_fluid_seq_heap_set_free(fluid_evt_heap_t * heap,fluid_evt_entry * evt)893 _fluid_seq_heap_set_free(fluid_evt_heap_t *heap, fluid_evt_entry *evt)
894 {
895 #ifdef HEAP_WITH_DYNALLOC
896 
897     /* LOCK */
898     fluid_mutex_lock(heap->mutex);
899 
900     evt->next = heap->freelist;
901     heap->freelist = evt;
902 
903     /* UNLOCK */
904     fluid_mutex_unlock(heap->mutex);
905 
906 #else
907     /* append to the end of the heap */
908     /* critical - should threadlock ? */
909     heap->tail->next = evt;
910     heap->tail = evt;
911     evt->next = NULL;
912 #endif
913 }
914