fluid_event.c
上传用户:tjmskj2
上传日期:2020-08-17
资源大小:577k
文件大小:17k
源码类别:

midi

开发平台:

C/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.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  18.  * 02111-1307, USA
  19.  */
  20. /*
  21.  2002 : API design by Peter Hanappe and Antoine Schmitt
  22.  August 2002 : Implementation by Antoine Schmitt as@gratin.org
  23.                as part of the infiniteCD author project
  24.                http://www.infiniteCD.org/
  25.  Oct4.2002 : AS : corrected bug in heap allocation, that caused a crash during sequencer free.
  26. */
  27. #include "fluid_event_priv.h"
  28. #include "fluidsynth_priv.h"
  29. /***************************************************************
  30.  *
  31.  *                           SEQUENCER EVENTS
  32.  */
  33. /* Event alloc/free */
  34. void
  35. fluid_event_clear(fluid_event_t* evt)
  36. {
  37.   FLUID_MEMSET(evt, 0, sizeof(fluid_event_t));
  38.   // by default, no type
  39.   evt->dest = -1;
  40.   evt->src = -1;
  41.   evt->type = -1;
  42. }
  43. /**
  44.  * Create a new sequencer event structure.
  45.  * @return New sequencer event structure or NULL if out of memory
  46.  */
  47. fluid_event_t*
  48. new_fluid_event()
  49. {
  50.   fluid_event_t* evt;
  51.   evt = FLUID_NEW(fluid_event_t);
  52.   if (evt == NULL) {
  53.     fluid_log(FLUID_PANIC, "event: Out of memoryn");
  54.     return NULL;
  55.   }
  56.   fluid_event_clear(evt);
  57.   return(evt);
  58. }
  59. /**
  60.  * Delete a sequencer event structure.
  61.  * @param evt Sequencer event structure created by new_fluid_event().
  62.  */
  63. void
  64. delete_fluid_event(fluid_event_t* evt)
  65. {
  66.   if (evt == NULL) {
  67.     return;
  68.   }
  69.   FLUID_FREE(evt);
  70. }
  71. /**
  72.  * Set the time field of a sequencer event.
  73.  * @internal
  74.  * @param evt Sequencer event structure
  75.  * @param time Time value to assign
  76.  */
  77. void
  78. fluid_event_set_time(fluid_event_t* evt, unsigned int time)
  79. {
  80. evt->time = time;
  81. }
  82. /**
  83.  * Set source of a sequencer event (DOCME).
  84.  * @param evt Sequencer event structure
  85.  * @param src DOCME
  86.  */
  87. void
  88. fluid_event_set_source(fluid_event_t* evt, short src)
  89. {
  90. evt->src = src;
  91. }
  92. /**
  93.  * Set destination of a sequencer event (DOCME).
  94.  * @param evt Sequencer event structure
  95.  * @param dest DOCME
  96.  */
  97. void
  98. fluid_event_set_dest(fluid_event_t* evt, short dest)
  99. {
  100. evt->dest = dest;
  101. }
  102. /**
  103.  * Set a sequencer event to be a timer event.
  104.  * @param evt Sequencer event structure
  105.  * @param data DOCME
  106.  */
  107. void
  108. fluid_event_timer(fluid_event_t* evt, void* data)
  109. {
  110. evt->type = FLUID_SEQ_TIMER;
  111. evt->data = data;
  112. }
  113. /**
  114.  * Set a sequencer event to be a note on event.
  115.  * @param evt Sequencer event structure
  116.  * @param channel MIDI channel number
  117.  * @param key MIDI note number (0-127)
  118.  * @param vel MIDI velocity value (0-127)
  119.  */
  120. void
  121. fluid_event_noteon(fluid_event_t* evt, int channel, short key, short vel)
  122. {
  123. evt->type = FLUID_SEQ_NOTEON;
  124. evt->channel = channel;
  125. evt->key = key;
  126. evt->vel = vel;
  127. }
  128. /**
  129.  * Set a sequencer event to be a note off event.
  130.  * @param evt Sequencer event structure
  131.  * @param channel MIDI channel number
  132.  * @param key MIDI note number (0-127)
  133.  */
  134. void
  135. fluid_event_noteoff(fluid_event_t* evt, int channel, short key)
  136. {
  137. evt->type = FLUID_SEQ_NOTEOFF;
  138. evt->channel = channel;
  139. evt->key = key;
  140. }
  141. /**
  142.  * Set a sequencer event to be a note duration event.
  143.  * @param evt Sequencer event structure
  144.  * @param channel MIDI channel number
  145.  * @param key MIDI note number (0-127)
  146.  * @param vel MIDI velocity value (0-127)
  147.  * @param duration Duration of note (DOCME units?)
  148.  */
  149. void
  150. fluid_event_note(fluid_event_t* evt, int channel, short key, short vel, unsigned int duration)
  151. {
  152. evt->type = FLUID_SEQ_NOTE;
  153. evt->channel = channel;
  154. evt->key = key;
  155. evt->vel = vel;
  156. evt->duration = duration;
  157. }
  158. /**
  159.  * Set a sequencer event to be an all sounds off event.
  160.  * @param evt Sequencer event structure
  161.  * @param channel MIDI channel number
  162.  */
  163. void
  164. fluid_event_all_sounds_off(fluid_event_t* evt, int channel)
  165. {
  166. evt->type = FLUID_SEQ_ALLSOUNDSOFF;
  167. evt->channel = channel;
  168. }
  169. /**
  170.  * Set a sequencer event to be a all notes off event.
  171.  * @param evt Sequencer event structure
  172.  * @param channel MIDI channel number
  173.  */
  174. void
  175. fluid_event_all_notes_off(fluid_event_t* evt, int channel)
  176. {
  177. evt->type = FLUID_SEQ_ALLNOTESOFF;
  178. evt->channel = channel;
  179. }
  180. /**
  181.  * Set a sequencer event to be a bank select event.
  182.  * @param evt Sequencer event structure
  183.  * @param channel MIDI channel number
  184.  * @param bank_num MIDI bank number (0-16383)
  185.  */
  186. void
  187. fluid_event_bank_select(fluid_event_t* evt, int channel, short bank_num)
  188. {
  189. evt->type = FLUID_SEQ_BANKSELECT;
  190. evt->channel = channel;
  191. evt->control = bank_num;
  192. }
  193. /**
  194.  * Set a sequencer event to be a program change event.
  195.  * @param evt Sequencer event structure
  196.  * @param channel MIDI channel number
  197.  * @param val MIDI program number (0-127)
  198.  */
  199. void
  200. fluid_event_program_change(fluid_event_t* evt, int channel, short val)
  201. {
  202. evt->type = FLUID_SEQ_PROGRAMCHANGE;
  203. evt->channel = channel;
  204. evt->value = val;
  205. }
  206. /**
  207.  * Set a sequencer event to be a program select event.
  208.  * @param evt Sequencer event structure
  209.  * @param channel MIDI channel number
  210.  * @param sfont_id SoundFont ID number
  211.  * @param bank_num MIDI bank number (0-16383)
  212.  * @param preset_num MIDI preset number (0-127)
  213.  */
  214. void
  215. fluid_event_program_select(fluid_event_t* evt, int channel,
  216.   unsigned int sfont_id, short bank_num, short preset_num)
  217. {
  218. evt->type = FLUID_SEQ_PROGRAMSELECT;
  219. evt->channel = channel;
  220. evt->duration = sfont_id;
  221. evt->value = preset_num;
  222. evt->control = bank_num;
  223. }
  224. /**
  225.  * Set a sequencer event to be an any control change event.
  226.  * @param evt Sequencer event structure
  227.  * @param channel MIDI channel number
  228.  * DOCME
  229.  */
  230. void
  231. fluid_event_any_control_change(fluid_event_t* evt, int channel)
  232. {
  233. evt->type = FLUID_SEQ_ANYCONTROLCHANGE;
  234. evt->channel = channel;
  235. }
  236. /**
  237.  * Set a sequencer event to be a pitch bend event.
  238.  * @param evt Sequencer event structure
  239.  * @param channel MIDI channel number
  240.  * @param pitch MIDI pitch bend value (0-16383, 8192 = no bend)
  241.  */
  242. void
  243. fluid_event_pitch_bend(fluid_event_t* evt, int channel, int pitch)
  244. {
  245. evt->type = FLUID_SEQ_PITCHBEND;
  246. evt->channel = channel;
  247. if (pitch < 0) pitch = 0;
  248. if (pitch > 16383) pitch = 16383;
  249. evt->pitch = pitch;
  250. }
  251. /**
  252.  * Set a sequencer event to be a pitch wheel sensitivity event.
  253.  * @param evt Sequencer event structure
  254.  * @param channel MIDI channel number
  255.  * @param value MIDI pitch wheel sensitivity value (DOCME units?)
  256.  */
  257. void
  258. fluid_event_pitch_wheelsens(fluid_event_t* evt, int channel, short value)
  259. {
  260. evt->type = FLUID_SEQ_PITCHWHHELSENS;
  261. evt->channel = channel;
  262. evt->value = value;
  263. }
  264. /**
  265.  * Set a sequencer event to be a modulation event.
  266.  * @param evt Sequencer event structure
  267.  * @param channel MIDI channel number
  268.  * @param val MIDI modulation value (0-127)
  269.  */
  270. void
  271. fluid_event_modulation(fluid_event_t* evt, int channel, short val)
  272. {
  273. evt->type = FLUID_SEQ_MODULATION;
  274. evt->channel = channel;
  275. if (val < 0) val = 0;
  276. if (val > 127) val = 127;
  277. evt->value = val;
  278. }
  279. /**
  280.  * Set a sequencer event to be a MIDI sustain event.
  281.  * @param evt Sequencer event structure
  282.  * @param channel MIDI channel number
  283.  * @param val MIDI sustain value (0-127)
  284.  */
  285. void
  286. fluid_event_sustain(fluid_event_t* evt, int channel, short val)
  287. {
  288. evt->type = FLUID_SEQ_SUSTAIN;
  289. evt->channel = channel;
  290. if (val < 0) val = 0;
  291. if (val > 127) val = 127;
  292. evt->value = val;
  293. }
  294. /**
  295.  * Set a sequencer event to be a MIDI control change event.
  296.  * @param evt Sequencer event structure
  297.  * @param channel MIDI channel number
  298.  * @param control MIDI control number (0-127)
  299.  * @param val MIDI control value (0-16383 DOCME is that true?)
  300.  */
  301. void
  302. fluid_event_control_change(fluid_event_t* evt, int channel, short control, short val)
  303. {
  304. evt->type = FLUID_SEQ_CONTROLCHANGE;
  305. evt->channel = channel;
  306. evt->control = control;
  307. evt->value = val;
  308. }
  309. /**
  310.  * Set a sequencer event to be a stereo pan event.
  311.  * @param evt Sequencer event structure
  312.  * @param channel MIDI channel number
  313.  * @param val MIDI panning value (0-127, 0=left, 64 = middle, 127 = right)
  314.  */
  315. void
  316. fluid_event_pan(fluid_event_t* evt, int channel, short val)
  317. {
  318. evt->type = FLUID_SEQ_PAN;
  319. evt->channel = channel;
  320. if (val < 0) val = 0;
  321. if (val > 127) val = 127;
  322. evt->value = val;
  323. }
  324. /**
  325.  * Set a sequencer event to be a volume event.
  326.  * @param evt Sequencer event structure
  327.  * @param channel MIDI channel number
  328.  * @param val Volume value (0-127)
  329.  */
  330. void
  331. fluid_event_volume(fluid_event_t* evt, int channel, short val)
  332. {
  333. evt->type = FLUID_SEQ_VOLUME;
  334. evt->channel = channel;
  335. if (val < 0) val = 0;
  336. if (val > 127) val = 127;
  337. evt->value = val;
  338. }
  339. /**
  340.  * Set a sequencer event to be a reverb send event.
  341.  * @param evt Sequencer event structure
  342.  * @param channel MIDI channel number
  343.  * @param val Reverb amount (0-127)
  344.  */
  345. void
  346. fluid_event_reverb_send(fluid_event_t* evt, int channel, short val)
  347. {
  348. evt->type = FLUID_SEQ_REVERBSEND;
  349. evt->channel = channel;
  350. if (val < 0) val = 0;
  351. if (val > 127) val = 127;
  352. evt->value = val;
  353. }
  354. /**
  355.  * Set a sequencer event to be a chorus send event.
  356.  * @param evt Sequencer event structure
  357.  * @param channel MIDI channel number
  358.  * @param val Chorus amount (0-127)
  359.  */
  360. void
  361. fluid_event_chorus_send(fluid_event_t* evt, int channel, short val)
  362. {
  363. evt->type = FLUID_SEQ_CHORUSSEND;
  364. evt->channel = channel;
  365. if (val < 0) val = 0;
  366. if (val > 127) val = 127;
  367. evt->value = val;
  368. }
  369. /**
  370.  * Set a sequencer event to be an unregistering event.
  371.  * @param evt Sequencer event structure
  372.  * @since 1.1.0
  373.  */
  374. void
  375. fluid_event_unregistering(fluid_event_t* evt)
  376. {
  377. evt->type = FLUID_SEQ_UNREGISTERING;
  378. }
  379. /**
  380.  * Set a sequencer event to be a channel-wide aftertouch event.
  381.  * @param evt Sequencer event structure
  382.  * @param channel MIDI channel number
  383.  * @param val Aftertouch amount (0-127)
  384.  * @since 1.1.0
  385.  */
  386. void 
  387. fluid_event_channel_pressure(fluid_event_t* evt, int channel, short val)
  388. {
  389. evt->type = FLUID_SEQ_CHANNELPRESSURE;
  390. evt->channel = channel;
  391. if (val < 0) val = 0;
  392. if (val > 127) val = 127;
  393. evt->value = val;
  394. }
  395. /**
  396.  * Set a sequencer event to be a midi system reset event.
  397.  * @param evt Sequencer event structure
  398.  * @since 1.1.0
  399.  */
  400. void 
  401. fluid_event_system_reset(fluid_event_t* evt)
  402. {
  403. evt->type = FLUID_SEQ_SYSTEMRESET;
  404. }
  405. /*
  406.  * Accessing event data
  407.  */
  408. /**
  409.  * Get the event type (#fluid_seq_event_type) field from a sequencer event structure.
  410.  * @param evt Sequencer event structure
  411.  * @return Event type (#fluid_seq_event_type).
  412.  */
  413. int fluid_event_get_type(fluid_event_t* evt)
  414. {
  415. return evt->type;
  416. }
  417. /**
  418.  * Get the time field from a sequencer event structure.
  419.  * @param evt Sequencer event structure
  420.  * @return Time value (DOCME units?)
  421.  */
  422. unsigned int fluid_event_get_time(fluid_event_t* evt)
  423. {
  424. return evt->time;
  425. }
  426. /**
  427.  * Get the source field from a sequencer event structure.
  428.  * @param evt Sequencer event structure
  429.  * @return DOCME
  430.  */
  431. short fluid_event_get_source(fluid_event_t* evt)
  432. {
  433. return evt->src;
  434. }
  435. /**
  436.  * Get the dest field from a sequencer event structure.
  437.  * @param evt Sequencer event structure
  438.  * @return DOCME
  439.  */
  440. short fluid_event_get_dest(fluid_event_t* evt)
  441. {
  442. return evt->dest;
  443. }
  444. /**
  445.  * Get the MIDI channel field from a sequencer event structure.
  446.  * @param evt Sequencer event structure
  447.  * @return MIDI channel number (DOCME 0-15 or more?)
  448.  */
  449. int fluid_event_get_channel(fluid_event_t* evt)
  450. {
  451. return evt->channel;
  452. }
  453. /**
  454.  * Get the MIDI note field from a sequencer event structure.
  455.  * @param evt Sequencer event structure
  456.  * @return MIDI note number (0-127)
  457.  */
  458. short fluid_event_get_key(fluid_event_t* evt)
  459. {
  460. return evt->key;
  461. }
  462. /**
  463.  * Get the MIDI velocity field from a sequencer event structure.
  464.  * @param evt Sequencer event structure
  465.  * @return MIDI velocity value (0-127)
  466.  */
  467. short fluid_event_get_velocity(fluid_event_t* evt)
  468. {
  469. return evt->vel;
  470. }
  471. /**
  472.  * Get the MIDI control number field from a sequencer event structure.
  473.  * @param evt Sequencer event structure
  474.  * @return MIDI control number (0-127)
  475.  */
  476. short fluid_event_get_control(fluid_event_t* evt)
  477. {
  478. return evt->control;
  479. }
  480. /**
  481.  * Get the value field from a sequencer event structure.
  482.  * @param evt Sequencer event structure
  483.  * @return Value field of event.
  484.  *
  485.  * The Value field is used by the following event types:
  486.  * #FLUID_SEQ_PROGRAMCHANGE, #FLUID_SEQ_PROGRAMSELECT (preset_num),
  487.  * #FLUID_SEQ_PITCHWHHELSENS, #FLUID_SEQ_MODULATION, #FLUID_SEQ_SUSTAIN,
  488.  * #FLUID_SEQ_CONTROLCHANGE, #FLUID_SEQ_PAN, #FLUID_SEQ_VOLUME,
  489.  * #FLUID_SEQ_REVERBSEND, #FLUID_SEQ_CHORUSSEND.
  490.  */
  491. short fluid_event_get_value(fluid_event_t* evt)
  492. {
  493. return evt->value;
  494. }
  495. /**
  496.  * Get the data field from a sequencer event structure.
  497.  * @param evt Sequencer event structure
  498.  * @return Data field of event.
  499.  *
  500.  * Used by the #FLUID_SEQ_TIMER event type.
  501.  */
  502. void* fluid_event_get_data(fluid_event_t* evt)
  503. {
  504. return evt->data;
  505. }
  506. /**
  507.  * Get the duration field from a sequencer event structure.
  508.  * @param evt Sequencer event structure
  509.  * @return Note duration value (DOCME units?)
  510.  *
  511.  * Used by the #FLUID_SEQ_NOTE event type.
  512.  */
  513. unsigned int fluid_event_get_duration(fluid_event_t* evt)
  514. {
  515. return evt->duration;
  516. }
  517. /**
  518.  * Get the MIDI bank field from a sequencer event structure.
  519.  * @param evt Sequencer event structure
  520.  * @return MIDI bank number (0-16383)
  521.  *
  522.  * Used by the #FLUID_SEQ_BANKSELECT and #FLUID_SEQ_PROGRAMSELECT
  523.  * event types.
  524.  */
  525. short fluid_event_get_bank(fluid_event_t* evt)
  526. {
  527. return evt->control;
  528. }
  529. /**
  530.  * Get the pitch field from a sequencer event structure.
  531.  * @param evt Sequencer event structure
  532.  * @return MIDI pitch bend pitch value (0-16383, 8192 = no bend)
  533.  *
  534.  * Used by the #FLUID_SEQ_PITCHBEND event type.
  535.  */
  536. int fluid_event_get_pitch(fluid_event_t* evt)
  537. {
  538. return evt->pitch;
  539. }
  540. /**
  541.  * Get the MIDI program field from a sequencer event structure.
  542.  * @param evt Sequencer event structure
  543.  * @return MIDI program number (0-127)
  544.  *
  545.  * Used by the #FLUID_SEQ_PROGRAMCHANGE and #FLUID_SEQ_PROGRAMSELECT
  546.  * event types.
  547.  */
  548. short
  549. fluid_event_get_program(fluid_event_t* evt)
  550. {
  551. return evt->value;
  552. }
  553. /**
  554.  * Get the SoundFont ID field from a sequencer event structure.
  555.  * @param evt Sequencer event structure
  556.  * @return SoundFont identifier value.
  557.  *
  558.  * Used by the #FLUID_SEQ_PROGRAMSELECT event type.
  559.  */
  560. unsigned int
  561. fluid_event_get_sfont_id(fluid_event_t* evt)
  562. {
  563. return evt->duration;
  564. }
  565. /********************/
  566. /* heap management  */
  567. /********************/
  568. fluid_evt_heap_t*
  569. _fluid_evt_heap_init(int nbEvents)
  570. {
  571. #ifdef HEAP_WITH_DYNALLOC
  572.   int i;
  573.   fluid_evt_heap_t* heap;
  574.   fluid_evt_entry *tmp;
  575.   heap = FLUID_NEW(fluid_evt_heap_t);
  576.   if (heap == NULL) {
  577.     fluid_log(FLUID_PANIC, "sequencer: Out of memoryn");
  578.     return NULL;
  579.   }
  580.   heap->freelist = NULL;
  581.   fluid_mutex_init(heap->mutex);
  582.   /* LOCK */
  583.   fluid_mutex_lock(heap->mutex);
  584.   /* Allocate the event entries */
  585.   for (i = 0; i < nbEvents; i++) {
  586.     tmp = FLUID_NEW(fluid_evt_entry);
  587.     tmp->next = heap->freelist;
  588.     heap->freelist = tmp;
  589.   }
  590.   /* UNLOCK */
  591.   fluid_mutex_unlock(heap->mutex);
  592. #else
  593. int i;
  594. fluid_evt_heap_t* heap;
  595. int siz = 2*sizeof(fluid_evt_entry *) + sizeof(fluid_evt_entry)*nbEvents;
  596. heap = (fluid_evt_heap_t *)FLUID_MALLOC(siz);
  597.   if (heap == NULL) {
  598.     fluid_log(FLUID_PANIC, "sequencer: Out of memoryn");
  599.     return NULL;
  600.   }
  601.   FLUID_MEMSET(heap, 0, siz);
  602.   /* link all heap events */
  603.   {
  604.    fluid_evt_entry *tmp = &(heap->pool);
  605.   for (i = 0 ; i < nbEvents - 1 ; i++)
  606.     tmp[i].next = &(tmp[i+1]);
  607.     tmp[nbEvents-1].next = NULL;
  608.     /* set head & tail */
  609.     heap->tail = &(tmp[nbEvents-1]);
  610.    heap->head = &(heap->pool);
  611.   }
  612. #endif
  613.   return (heap);
  614. }
  615. void
  616. _fluid_evt_heap_free(fluid_evt_heap_t* heap)
  617. {
  618. #ifdef HEAP_WITH_DYNALLOC
  619.   fluid_evt_entry *tmp, *next;
  620.   /* LOCK */
  621.   fluid_mutex_lock(heap->mutex);
  622.   tmp = heap->freelist;
  623.   while (tmp) {
  624.     next = tmp->next;
  625.     FLUID_FREE(tmp);
  626.     tmp = next;
  627.   }
  628.   /* UNLOCK */
  629.   fluid_mutex_unlock(heap->mutex);
  630.   fluid_mutex_destroy(heap->mutex);
  631.   FLUID_FREE(heap);
  632. #else
  633. FLUID_FREE(heap);
  634. #endif
  635. }
  636. fluid_evt_entry*
  637. _fluid_seq_heap_get_free(fluid_evt_heap_t* heap)
  638. {
  639. #ifdef HEAP_WITH_DYNALLOC
  640.   fluid_evt_entry* evt = NULL;
  641.   /* LOCK */
  642.   fluid_mutex_lock(heap->mutex);
  643. #if !defined(MACOS9)
  644.   if (heap->freelist == NULL) {
  645.     heap->freelist = FLUID_NEW(fluid_evt_entry);
  646.     if (heap->freelist != NULL) {
  647.       heap->freelist->next = NULL;
  648.     }
  649.   }
  650. #endif
  651.   evt = heap->freelist;
  652.   if (evt != NULL) {
  653.     heap->freelist = heap->freelist->next;
  654.     evt->next = NULL;
  655.   }
  656.   /* UNLOCK */
  657.   fluid_mutex_unlock(heap->mutex);
  658.   return evt;
  659. #else
  660. fluid_evt_entry* evt;
  661. if (heap->head == NULL) return NULL;
  662. /* take from head of the heap */
  663. /* critical - should threadlock ? */
  664. evt = heap->head;
  665. heap->head = heap->head->next;
  666. return evt;
  667. #endif
  668. }
  669. void
  670. _fluid_seq_heap_set_free(fluid_evt_heap_t* heap, fluid_evt_entry* evt)
  671. {
  672. #ifdef HEAP_WITH_DYNALLOC
  673.   /* LOCK */
  674.   fluid_mutex_lock(heap->mutex);
  675.   evt->next = heap->freelist;
  676.   heap->freelist = evt;
  677.   /* UNLOCK */
  678.   fluid_mutex_unlock(heap->mutex);
  679. #else
  680. /* append to the end of the heap */
  681. /* critical - should threadlock ? */
  682. heap->tail->next = evt;
  683. heap->tail = evt;
  684. evt->next = NULL;
  685. #endif
  686. }