# src/fluid_seq.c

    00001 /* FluidSynth - A Software Synthesizer
    00002  *
    00003  * Copyright (C) 2003  Peter Hanappe and others.
    00004  *
    00005  * This library is free software; you can redistribute it and/or
    00006  * modify it under the terms of the GNU Library General Public License
    00007  * as published by the Free Software Foundation; either version 2 of
    00008  * the License, or (at your option) any later version.
    00009  *
    00010  * This library is distributed in the hope that it will be useful, but
    00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013  * Library General Public License for more details.
    00014  *
    00015  * You should have received a copy of the GNU Library General Public
    00016  * License along with this library; if not, write to the Free
    00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    00018  * 02111-1307, USA
    00019  */
    00020
    00021
    00022
    00023 /*
    00024   2002 : API design by Peter Hanappe and Antoine Schmitt
    00025   August 2002 : Implementation by Antoine Schmitt as@gratin.org
    00026   as part of the infiniteCD author project
    00027   http://www.infiniteCD.org/
    00028 */
    00029
    00030 #include "fluid_event_priv.h"
    00031 #include "fluidsynth_priv.h"    // FLUID_NEW, etc
    00032 #include "fluid_sys.h"  // timer, threads, etc...
    00033 #include "fluid_list.h"
    00034
    00035 /***************************************************************
    00036  *
    00037  *                           SEQUENCER
    00038  */
    00039
    00040 #define FLUID_SEQUENCER_EVENTS_MAX      1000
    00041
    00042 /* Private data for SEQUENCER */
    00043 struct _fluid_sequencer_t {
    00044         unsigned int startMs;
    00045         double scale; // ticks per second
    00046         fluid_list_t* clients;
    00047         short clientsID;
    00048         /* for queue + heap */
    00049         fluid_evt_entry* preQueue;
    00050         fluid_evt_entry* preQueueLast;
    00051         fluid_timer_t* timer;
    00052         int queue0StartTime;
    00053         short prevCellNb;
    00054         fluid_evt_entry* queue0[256][2];
    00055         fluid_evt_entry* queue1[255][2];
    00056         fluid_evt_entry* queueLater;
    00057         fluid_evt_heap_t* heap;
    00058         fluid_mutex_t mutex;
    00059 #if FLUID_SEQ_WITH_TRACE
    00060         char *tracebuf;
    00061         char *traceptr;
    00062         int tracelen;
    00063 #endif
    00064 };
    00065
    00066 /* Private data for clients */
    00067 typedef struct _fluid_sequencer_client_t {
    00068         short id;
    00069         char* name;
    00070         fluid_event_callback_t callback;
    00071         void* data;
    00072 } fluid_sequencer_client_t;
    00073
    00074 /* prototypes */
    00075 /* sorting API */
    00076 short _fluid_seq_queue_init(fluid_sequencer_t* seq, int nbEvents);
    00077 void _fluid_seq_queue_end(fluid_sequencer_t* seq);
    00078 short _fluid_seq_queue_pre_insert(fluid_sequencer_t* seq, fluid_event_t * evt);
    00079 void _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int type);
    00080 int _fluid_seq_queue_process(void* data, unsigned int msec); // callback from timer
    00081
    00082
    00083 /* API implementation */
    00084
    00085 fluid_sequencer_t*
    00086 new_fluid_sequencer()
    00087 {
    00088         fluid_sequencer_t* seq;
    00089
    00090         seq = FLUID_NEW(fluid_sequencer_t);
    00091         if (seq == NULL) {
    00092                 fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
    00093                 return NULL;
    00094         }
    00095
    00096         FLUID_MEMSET(seq, 0, sizeof(fluid_sequencer_t));
    00097
    00098         seq->scale = 1000;      // default value
    00099         seq->startMs = fluid_curtime();
    00100         seq->clients = NULL;
    00101         seq->clientsID = 0;
    00102
    00103         if (-1 == _fluid_seq_queue_init(seq, FLUID_SEQUENCER_EVENTS_MAX)) {
    00104                 FLUID_FREE(seq);
    00105                 fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
    00106                 return NULL;
    00107         }
    00108
    00109 #if FLUID_SEQ_WITH_TRACE
    00110         seq->tracelen = 1024*100;
    00111         seq->tracebuf = (char *)FLUID_MALLOC(seq->tracelen);
    00112         if (seq->tracebuf == NULL) {
    00113                 _fluid_seq_queue_end(seq);
    00114                 FLUID_FREE(seq);
    00115                 fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
    00116                 return NULL;
    00117         }
    00118         seq->traceptr = seq->tracebuf;
    00119 #endif
    00120
    00121         return(seq);
    00122 }
    00123
    00124 void
    00125 delete_fluid_sequencer(fluid_sequencer_t* seq)
    00126 {
    00127
    00128         if (seq == NULL) {
    00129                 return;
    00130         }
    00131
    00132         _fluid_seq_queue_end(seq);
    00133
    00134         /* cleanup clients */
    00135         if (seq->clients) {
    00136                 fluid_list_t *tmp = seq->clients;
    00137                 while (tmp != NULL) {
    00138                         fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
    00139                         if (client->name) FLUID_FREE(client->name);
    00140                         tmp = tmp->next;
    00141                 }
    00142                 delete_fluid_list(seq->clients);
    00143                 seq->clients = NULL;
    00144         }
    00145
    00146 #if FLUID_SEQ_WITH_TRACE
    00147         if (seq->tracebuf != NULL)
    00148                 FLUID_FREE(seq->tracebuf);
    00149         seq->tracebuf = NULL;
    00150 #endif
    00151
    00152         FLUID_FREE(seq);
    00153 }
    00154
    00155 #if FLUID_SEQ_WITH_TRACE
    00156
    00157 /* trace */
    00158 void
    00159 fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...)
    00160 {
    00161         va_list args;
    00162         int len, remain = seq->tracelen - (seq->traceptr - seq->tracebuf);
    00163         if (remain <= 0) return;
    00164
    00165         va_start (args, fmt);
    00166         len = vsnprintf(seq->traceptr, remain, fmt, args);
    00167         va_end (args);
    00168
    00169         if (len > 0) {
    00170                 if (len <= remain) {
    00171                         // all written, with 0 at end
    00172                         seq->traceptr += len;
    00173                 } else {
    00174                         // not enough room, set to end
    00175                         seq->traceptr = seq->tracebuf + seq->tracelen;
    00176                 }
    00177         }
    00178
    00179         return;
    00180 }
    00181
    00182 void
    00183 fluid_seq_cleartrace(fluid_sequencer_t* seq)
    00184 {
    00185         seq->traceptr = seq->tracebuf;
    00186 }
    00187
    00188 char *
    00189 fluid_seq_gettrace(fluid_sequencer_t* seq)
    00190 {
    00191         return seq->tracebuf;
    00192 }
    00193 #else
    00194
    00195 void fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...) {}
    00196
    00197 #endif // FLUID_SEQ_WITH_TRACE
    00198
    00199 /* clients */
    00200
    00201 short fluid_sequencer_register_client(fluid_sequencer_t* seq, char* name,
    00202                                       fluid_event_callback_t callback, void* data) {
    00203
    00204         fluid_sequencer_client_t * client;
    00205         char * nameCopy;
    00206
    00207         client = FLUID_NEW(fluid_sequencer_client_t);
    00208         if (client == NULL) {
    00209                 fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
    00210                 return -1;
    00211         }
    00212
    00213         nameCopy = FLUID_STRDUP(name);
    00214         if (nameCopy == NULL) {
    00215                 fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
    00216                 return -1;
    00217         }
    00218
    00219         seq->clientsID++;
    00220
    00221         client->name = nameCopy;
    00222         client->id = seq->clientsID;
    00223         client->callback = callback;
    00224         client->data = data;
    00225
    00226         seq->clients = fluid_list_append(seq->clients, (void *)client);
    00227
    00228         return (client->id);
    00229 }
    00230
    00232 void fluid_sequencer_unregister_client(fluid_sequencer_t* seq, short id)
    00233 {
    00234         fluid_list_t *tmp;
    00235
    00236         if (seq->clients == NULL) return;
    00237
    00238         tmp = seq->clients;
    00239         while (tmp) {
    00240                 fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
    00241
    00242                 if (client->id == id) {
    00243                         if (client->name)
    00244                                 FLUID_FREE(client->name);
    00245                         seq->clients = fluid_list_remove_link(seq->clients, tmp);
    00246                         delete1_fluid_list(tmp);
    00247                         return;
    00248                 }
    00249                 tmp = tmp->next;
    00250         }
    00251         return;
    00252 }
    00253
    00254 int fluid_sequencer_count_clients(fluid_sequencer_t* seq)
    00255 {
    00256         if (seq->clients == NULL)
    00257                 return 0;
    00258         return fluid_list_size(seq->clients);
    00259 }
    00260
    00262 short fluid_sequencer_get_client_id(fluid_sequencer_t* seq, int index)
    00263 {
    00264         fluid_list_t *tmp = fluid_list_nth(seq->clients, index);
    00265         if (tmp == NULL) {
    00266                 return -1;
    00267         } else {
    00268                 fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
    00269                 return client->id;
    00270         }
    00271 }
    00272
    00274 char* fluid_sequencer_get_client_name(fluid_sequencer_t* seq, int id)
    00275 {
    00276         fluid_list_t *tmp;
    00277
    00278         if (seq->clients == NULL)
    00279                 return NULL;
    00280
    00281         tmp = seq->clients;
    00282         while (tmp) {
    00283                 fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
    00284
    00285                 if (client->id == id)
    00286                         return client->name;
    00287
    00288                 tmp = tmp->next;
    00289         }
    00290         return NULL;
    00291 }
    00292
    00293 int fluid_sequencer_client_is_dest(fluid_sequencer_t* seq, int id)
    00294 {
    00295         fluid_list_t *tmp;
    00296
    00297         if (seq->clients == NULL) return 0;
    00298
    00299         tmp = seq->clients;
    00300         while (tmp) {
    00301                 fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
    00302
    00303                 if (client->id == id)
    00304                         return (client->callback != NULL);
    00305
    00306                 tmp = tmp->next;
    00307         }
    00308         return 0;
    00309 }
    00310
    00311 /* sending events */
    00312 void fluid_sequencer_send_now(fluid_sequencer_t* seq, fluid_event_t* evt)
    00313 {
    00314         short destID = fluid_event_get_dest(evt);
    00315
    00316         /* find callback */
    00317         fluid_list_t *tmp = seq->clients;
    00318         while (tmp) {
    00319                 fluid_sequencer_client_t *dest = (fluid_sequencer_client_t*)tmp->data;
    00320
    00321                 if (dest->id == destID) {
    00322                         if (dest->callback)
    00323                                 (dest->callback)(fluid_sequencer_get_tick(seq),
    00324                                                  evt, seq, dest->data);
    00325                         return;
    00326                 }
    00327                 tmp = tmp->next;
    00328         }
    00329 }
    00330
    00331 int
    00332 fluid_sequencer_send_at(fluid_sequencer_t* seq, fluid_event_t* evt, unsigned int time, int absolute)
    00333 {
    00334         unsigned int now = fluid_sequencer_get_tick(seq);
    00335
    00336         /* set absolute */
    00337         if (!absolute)
    00338                 time = now + time;
    00339
    00340         /* time stamp event */
    00341         fluid_event_set_time(evt, time);
    00342
    00343         /* process late */
    00344         if (time < now) {
    00345                 fluid_sequencer_send_now(seq, evt);
    00346                 return 0;
    00347         }
    00348
    00349         /* process now */
    00350         if (time == now) {
    00351                 fluid_sequencer_send_now(seq, evt);
    00352                 return 0;
    00353         }
    00354
    00355         /* queue for processing later */
    00356         return _fluid_seq_queue_pre_insert(seq, evt);
    00357 }
    00358
    00359 void
    00360 fluid_sequencer_remove_events(fluid_sequencer_t* seq, short source, short dest, int type)
    00361 {
    00362         _fluid_seq_queue_pre_remove(seq, source, dest, type);
    00363 }
    00364
    00365
    00366 /*************************************
    00367         time
    00368 **************************************/
    00369 unsigned int fluid_sequencer_get_tick(fluid_sequencer_t* seq)
    00370 {
    00371         unsigned int absMs = fluid_curtime();
    00372         double nowFloat;
    00373         unsigned int now;
    00374         nowFloat = ((double)(absMs - seq->startMs))*seq->scale/1000.0f;
    00375         now = nowFloat;
    00376         return now;
    00377 }
    00378
    00379 void fluid_sequencer_set_time_scale(fluid_sequencer_t* seq, double scale)
    00380 {
    00381         if (scale <= 0) {
    00382                 fluid_log(FLUID_WARN, "sequencer: scale <= 0 : %f\n", scale);
    00383                 return;
    00384         }
    00385
    00386         if (scale > 1000.0)
    00387                 // Otherwise : problems with the timer = 0ms...
    00388                 scale = 1000.0;
    00389
    00390         if (seq->scale != scale) {
    00391                 double oldScale = seq->scale;
    00392
    00393                 // stop timer
    00394                 if (seq->timer) {
    00395                         delete_fluid_timer(seq->timer);
    00396                         seq->timer = NULL;
    00397                 }
    00398
    00399                 seq->scale = scale;
    00400
    00401                 // change start0 so that cellNb is preserved
    00402                 seq->queue0StartTime =  (seq->queue0StartTime + seq->prevCellNb)*(seq->scale/oldScale) - seq->prevCellNb;
    00403
    00404                 // change all preQueue events for new scale
    00405                 {
    00406                         fluid_evt_entry* tmp;
    00407                         tmp = seq->preQueue;
    00408                         while (tmp) {
    00409                                 if (tmp->entryType == FLUID_EVT_ENTRY_INSERT)
    00410                                         tmp->evt.time = tmp->evt.time*seq->scale/oldScale;
    00411
    00412                                 tmp = tmp->next;
    00413                         }
    00414                 }
    00415
    00416                 /* re-start timer */
    00417                 seq->timer = new_fluid_timer((int)(1000/seq->scale), _fluid_seq_queue_process, (void *)seq, 1, 0);
    00418         }
    00419 }
    00420
    00423 double fluid_sequencer_get_time_scale(fluid_sequencer_t* seq)
    00424 {
    00425         return seq->scale;
    00426 }
    00427
    00428
    00429 /**********************
    00430
    00431       the queue
    00432
    00433 **********************/
    00434
    00435 /*
    00436   The queue stores all future events to be processed.
    00437
    00438   Data structures
    00439
    00440   There is a heap, allocated at init time, for managing a pool
    00441   of event entries, that is description of an event, its time,
    00442   and whether it is a normal event or a removal command.
    00443
    00444   The queue is separated in two arrays, and a list.  The first
    00445   array 'queue0' corresponds to the events to be sent in the
    00446   next 256 ticks (0 to 255), the second array 'queue1' contains
    00447   the events to be send from now+256 to now+65535. The list
    00448   called 'queueLater' contains the events to be sent later than
    00449   that. In each array, one cell contains a list of events having
    00450   the same time (in the queue0 array), or the same time/256 (in
    00451   the queue1 array), and a pointer to the last event in the list
    00452   of the cell so as to be able to insert fast at the end of the
    00453   list (i.e. a cell = 2 pointers).  The 'queueLater' list is
    00454   ordered by time and by post time.  This way, inserting 'soon'
    00455   events is fast (below 65535 ticks, that is about 1 minute if 1
    00456   tick=1ms).  Inserting later events is more slow, but this is a
    00457   realtime engine, isn't it ?
    00458
    00459   The queue0 starts at queue0StartTime.  When 256 ticks have
    00460   elapsed, the queue0 array is emptied, and the first cell of
    00461   the queue1 array is expanded in the queue0 array, according to
    00462   the time of each event. The queue1 array is shifted to the
    00463   left, and the first events of the queueLater list are inserte
    00464   in the last cell of the queue1 array.
    00465
    00466   We remember the previously managed cell in queue0 in the
    00467   prevCellNb variable. When processing the current cell, we
    00468   process the events in between (late events).
    00469
    00470   Functions
    00471
    00472   The main thread functions first get an event entry from the
    00473   heap, and copy the given event into it, then merely enqueue it
    00474   in a preQueue. This is in order to protect the data structure:
    00475   everything is managed in the callback (thread or interrupt,
    00476   depending on the architecture).
    00477
    00478   All queue data structure management is done in a timer
    00479   callback: '_fluid_seq_queue_process'.  The
    00480   _fluid_seq_queue_process function first process the preQueue,
    00481   inserting or removing event entrys from the queue, then
    00482   processes the queue, by sending events ready to be sent at the
    00483   current time.
    00484
    00485   Critical sections between the main thread (or app) and the
    00486   sequencer thread (or interrupt) are:
    00487
    00488   - the heap management (if two threads get a free event at the
    00489   same time)
    00490   - the preQueue access.
    00491
    00492   These are really small and fast sections (merely a pointer or
    00493   two changing value). They are not protected by a mutex for now
    00494   (August 2002). Waiting for crossplatform mutex solutions. When
    00495   changing this code, beware that the
    00496   _fluid_seq_queue_pre_insert function may be called by the
    00497   callback of the queue thread (ex : a note event inserts a
    00498   noteoff event).
    00499
    00500 */
    00501
    00502
    00503
    00504 void _fluid_seq_queue_insert_entry(fluid_sequencer_t* seq, fluid_evt_entry * evtentry);
    00505 void _fluid_seq_queue_remove_entries_matching(fluid_sequencer_t* seq, fluid_evt_entry* temp);
    00506 void _fluid_seq_queue_send_queued_events(fluid_sequencer_t* seq);
    00507
    00508
    00509 /********************/
    00510 /*       API        */
    00511 /********************/
    00512
    00513 short
    00514 _fluid_seq_queue_init(fluid_sequencer_t* seq, int maxEvents)
    00515 {
    00516         int i;
    00517
    00518         seq->heap = _fluid_evt_heap_init(maxEvents);
    00519         if (seq->heap == NULL) {
    00520                 fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
    00521                 return -1;
    00522         }
    00523
    00524         seq->preQueue = NULL;
    00525         seq->preQueueLast = NULL;
    00526
    00527         FLUID_MEMSET(seq->queue0, 0, 2*256*sizeof(fluid_evt_entry *));
    00528         FLUID_MEMSET(seq->queue1, 0, 2*255*sizeof(fluid_evt_entry *));
    00529
    00530         seq->queueLater = NULL;
    00531         seq->queue0StartTime = fluid_sequencer_get_tick(seq);
    00532         seq->prevCellNb = -1;
    00533
    00534         fluid_mutex_init(seq->mutex);
    00535
    00536         /* start timer */
    00537         seq->timer = new_fluid_timer((int)(1000/seq->scale), _fluid_seq_queue_process,
    00538                                      (void *)seq, 1, 0);
    00539         return (0);
    00540 }
    00541
    00542 void
    00543 _fluid_seq_queue_end(fluid_sequencer_t* seq)
    00544 {
    00545         if (seq->timer) {
    00546                 delete_fluid_timer(seq->timer);
    00547                 seq->timer = NULL;
    00548         }
    00549
    00550         if (seq->heap) {
    00551                 _fluid_evt_heap_free(seq->heap);
    00552                 seq->heap = NULL;
    00553         }
    00554         fluid_mutex_destroy(seq->mutex);
    00555 }
    00556
    00557
    00558
    00559 /********************/
    00560 /* queue management */
    00561 /********************/
    00562
    00563 /* create event_entry and append to the preQueue */
    00564 /* may be called from the main thread (usually) but also recursively
    00565    from the queue thread, when a callback itself does an insert... */
    00566 short
    00567 _fluid_seq_queue_pre_insert(fluid_sequencer_t* seq, fluid_event_t * evt)
    00568 {
    00569         fluid_evt_entry * evtentry = _fluid_seq_heap_get_free(seq->heap);
    00570         if (evtentry == NULL) {
    00571                 /* should not happen */
    00572                 fluid_log(FLUID_PANIC, "sequencer: no more free events\n");
    00573                 return -1;
    00574         }
    00575
    00576         evtentry->next = NULL;
    00577         evtentry->entryType = FLUID_EVT_ENTRY_INSERT;
    00578         FLUID_MEMCPY(&(evtentry->evt), evt, sizeof(fluid_event_t));
    00579
    00580         fluid_mutex_lock(seq->mutex);
    00581
    00582         /* append to preQueue */
    00583         if (seq->preQueueLast) {
    00584                 seq->preQueueLast->next = evtentry;
    00585         } else {
    00586                 seq->preQueue = evtentry;
    00587         }
    00588         seq->preQueueLast = evtentry;
    00589
    00590         fluid_mutex_unlock(seq->mutex);
    00591
    00592         return (0);
    00593 }
    00594
    00595 /* create event_entry and append to the preQueue */
    00596 /* may be called from the main thread (usually) but also recursively
    00597    from the queue thread, when a callback itself does an insert... */
    00598 void
    00599 _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int type)
    00600 {
    00601         fluid_evt_entry * evtentry = _fluid_seq_heap_get_free(seq->heap);
    00602         if (evtentry == NULL) {
    00603                 /* should not happen */
    00604                 fluid_log(FLUID_PANIC, "sequencer: no more free events\n");
    00605                 return;
    00606         }
    00607
    00608         evtentry->next = NULL;
    00609         evtentry->entryType = FLUID_EVT_ENTRY_REMOVE;
    00610         {
    00611                 fluid_event_t* evt = &(evtentry->evt);
    00612                 fluid_event_set_source(evt, src);
    00613                 fluid_event_set_source(evt, src);
    00614                 fluid_event_set_dest(evt, dest);
    00615                 evt->type = type;
    00616         }
    00617
    00618         fluid_mutex_lock(seq->mutex);
    00619
    00620         /* append to preQueue */
    00621         if (seq->preQueueLast) {
    00622                 seq->preQueueLast->next = evtentry;
    00623         } else {
    00624                 seq->preQueue = evtentry;
    00625         }
    00626         seq->preQueueLast = evtentry;
    00627
    00628         fluid_mutex_unlock(seq->mutex);
    00629         return;
    00630 }
    00631
    00632 /***********************
    00633  * callback from timer
    00634  * (may be in a different thread, or in an interrupt)
    00635  *
    00636  ***********************/
    00637 int
    00638 _fluid_seq_queue_process(void* data, unsigned int msec)
    00639 {
    00640         fluid_sequencer_t* seq = (fluid_sequencer_t *)data;
    00641
    00642         /* process prequeue */
    00643         fluid_evt_entry* tmp;
    00644         fluid_evt_entry* next;
    00645
    00646         fluid_mutex_lock(seq->mutex);
    00647
    00648         /* get the preQueue */
    00649         tmp = seq->preQueue;
    00650         seq->preQueue = NULL;
    00651         seq->preQueueLast = NULL;
    00652
    00653         fluid_mutex_unlock(seq->mutex);
    00654
    00655         /* walk all the preQueue and process them in order : inserts and removes */
    00656         while (tmp) {
    00657                 next = tmp->next;
    00658
    00659                 if (tmp->entryType == FLUID_EVT_ENTRY_REMOVE) {
    00660                         _fluid_seq_queue_remove_entries_matching(seq, tmp);
    00661                 } else {
    00662                         _fluid_seq_queue_insert_entry(seq, tmp);
    00663                 }
    00664
    00665                 tmp = next;
    00666         }
    00667
    00668         /* send queued events */
    00669         _fluid_seq_queue_send_queued_events(seq);
    00670
    00671         /* continue timer */
    00672         return 1;
    00673 }
    00674
    00675
    00676 void
    00677 _fluid_seq_queue_print_later(fluid_sequencer_t* seq)
    00678 {
    00679         int count = 0;
    00680         fluid_evt_entry* tmp = seq->queueLater;
    00681
    00682         printf("queueLater:\n");
    00683
    00684         while (tmp) {
    00685                 unsigned int delay = tmp->evt.time - seq->queue0StartTime;
    00686                 printf("queueLater: Delay = %i\n", delay);
    00687                 tmp = tmp->next;
    00688                 count++;
    00689         }
    00690         printf("queueLater: Total of %i events\n", count);
    00691 }
    00692
    00693
    00694 void
    00695 _fluid_seq_queue_insert_queue0(fluid_sequencer_t* seq, fluid_evt_entry* tmp, int cell)
    00696 {
    00697         if (seq->queue0[cell][1] == NULL) {
    00698                 seq->queue0[cell][1] = seq->queue0[cell][0] = tmp;
    00699         } else {
    00700                 seq->queue0[cell][1]->next = tmp;
    00701                 seq->queue0[cell][1] = tmp;
    00702         }
    00703         tmp->next = NULL;
    00704 }
    00705
    00706 void
    00707 _fluid_seq_queue_insert_queue1(fluid_sequencer_t* seq, fluid_evt_entry* tmp, int cell)
    00708 {
    00709         if (seq->queue1[cell][1] == NULL) {
    00710                 seq->queue1[cell][1] = seq->queue1[cell][0] = tmp;
    00711         } else {
    00712                 seq->queue1[cell][1]->next = tmp;
    00713                 seq->queue1[cell][1] = tmp;
    00714         }
    00715         tmp->next = NULL;
    00716 }
    00717
    00718 void
    00719 _fluid_seq_queue_insert_queue_later(fluid_sequencer_t* seq, fluid_evt_entry* evtentry)
    00720 {
    00721         fluid_evt_entry* prev;
    00722         fluid_evt_entry* tmp;
    00723         unsigned int time = evtentry->evt.time;
    00724
    00725         /* insert in 'queueLater', after the ones that have the same
    00726          * time */
    00727
    00728         /* first? */
    00729         if ((seq->queueLater == NULL)
    00730             || (seq->queueLater->evt.time > time)) {
    00731                 evtentry->next = seq->queueLater;
    00732                 seq->queueLater = evtentry;
    00733                 return;
    00734         }
    00735
    00736         /* walk queueLater */
    00737         /* this is the only slow thing : if the event is more
    00738            than 65535 ticks after the current time */
    00739
    00740         prev = seq->queueLater;
    00741         tmp = prev->next;
    00742         while (tmp) {
    00743                 if (tmp->evt.time > time) {
    00744                         /* insert before tmp */
    00745                         evtentry->next = tmp;
    00746                         prev->next = evtentry;
    00747                         return;
    00748                 }
    00749                 prev = tmp;
    00750                 tmp = prev->next;
    00751         }
    00752
    00753         /* last */
    00754         evtentry->next = NULL;
    00755         prev->next = evtentry;
    00756 }
    00757
    00758 void
    00759 _fluid_seq_queue_insert_entry(fluid_sequencer_t* seq, fluid_evt_entry * evtentry)
    00760 {
    00761         /* time is relative to seq origin, in ticks */
    00762         fluid_event_t * evt = &(evtentry->evt);
    00763         unsigned int time = evt->time;
    00764         unsigned int delay;
    00765
    00766         if (seq->queue0StartTime > 0) {
    00767                 /* queue0StartTime could be < 0 if the scale changed a
    00768                    lot early, breaking the following comparison
    00769                 */
    00770                 if (time < (unsigned int)seq->queue0StartTime) {
    00771                         /* we are late, send now */
    00772                         fluid_sequencer_send_now(seq, evt);
    00773
    00774                         _fluid_seq_heap_set_free(seq->heap, evtentry);
    00775                         return;
    00776                 }
    00777         }
    00778
    00779         if (seq->prevCellNb >= 0) {
    00780                 /* prevCellNb could be -1 is seq was just started - unlikely */
    00781                 /* prevCellNb can also be -1 if cellNb was reset to 0 in
    00782                    _fluid_seq_queue_send_queued_events() */
    00783                 if (time <= (unsigned int)(seq->queue0StartTime + seq->prevCellNb)) {
    00784                         /* we are late, send now */
    00785                         fluid_sequencer_send_now(seq, evt);
    00786
    00787                         _fluid_seq_heap_set_free(seq->heap, evtentry);
    00788                         return;
    00789                 }
    00790         }
    00791
    00792         delay = time - seq->queue0StartTime;
    00793
    00794         if (delay > 65535) {
    00795                 _fluid_seq_queue_insert_queue_later(seq, evtentry);
    00796
    00797         } else if (delay > 255) {
    00798                 _fluid_seq_queue_insert_queue1(seq, evtentry, delay/256 - 1);
    00799
    00800         } else {
    00801                 _fluid_seq_queue_insert_queue0(seq, evtentry, delay);
    00802         }
    00803 }
    00804
    00805 int
    00806 _fluid_seq_queue_matchevent(fluid_event_t* evt, int templType, short templSrc, short templDest)
    00807 {
    00808         int eventType;
    00809
    00810         if (templSrc != -1 && templSrc != fluid_event_get_source(evt))
    00811                 return 0;
    00812
    00813         if (templDest != -1 && templDest != fluid_event_get_dest(evt))
    00814                 return 0;
    00815
    00816         if (templType == -1)
    00817                 return 1;
    00818
    00819         eventType = fluid_event_get_type(evt);
    00820
    00821         if (templType == eventType)
    00822                 return 1;
    00823
    00824         if (templType == FLUID_SEQ_ANYCONTROLCHANGE)
    00825                 if (eventType == FLUID_SEQ_PITCHBEND ||
    00826                     eventType == FLUID_SEQ_MODULATION ||
    00827                     eventType == FLUID_SEQ_SUSTAIN ||
    00828                     eventType == FLUID_SEQ_PAN ||
    00829                     eventType == FLUID_SEQ_VOLUME ||
    00830                     eventType == FLUID_SEQ_REVERBSEND ||
    00831                     eventType == FLUID_SEQ_CONTROLCHANGE ||
    00832                     eventType == FLUID_SEQ_CHORUSSEND)
    00833                         return 1;
    00834
    00835         return 0;
    00836 }
    00837
    00838 void
    00839 _fluid_seq_queue_remove_entries_matching(fluid_sequencer_t* seq, fluid_evt_entry* templ)
    00840 {
    00841         /* we walk everything : this is slow, but that is life */
    00842         int i, type;
    00843         short src, dest;
    00844
    00845         src = templ->evt.src;
    00846         dest = templ->evt.dest;
    00847         type = templ->evt.type;
    00848
    00849         /* we can set it free now */
    00850         _fluid_seq_heap_set_free(seq->heap, templ);
    00851
    00852         /* queue0 */
    00853         for (i = 0 ; i < 256 ; i++) {
    00854                 fluid_evt_entry* tmp = seq->queue0[i][0];
    00855                 fluid_evt_entry* prev = NULL;
    00856                 while (tmp) {
    00857                         /* remove and/or walk */
    00858                         if (_fluid_seq_queue_matchevent((&tmp->evt), type, src, dest)) {
    00859                                 /* remove */
    00860                                 if (prev) {
    00861                                         prev->next = tmp->next;
    00862                                         if (tmp == seq->queue0[i][1]) // last one in list
    00863                                                 seq->queue0[i][1] = prev;
    00864
    00865                                         _fluid_seq_heap_set_free(seq->heap, tmp);
    00866                                         tmp = prev->next;
    00867                                 } else {
    00868                                         /* first one in list */
    00869                                         seq->queue0[i][0] = tmp->next;
    00870                                         if (tmp == seq->queue0[i][1]) // last one in list
    00871                                                 seq->queue0[i][1] = NULL;
    00872
    00873                                         _fluid_seq_heap_set_free(seq->heap, tmp);
    00874                                         tmp = seq->queue0[i][0];
    00875                                 }
    00876                         } else {
    00877                                 prev = tmp;
    00878                                 tmp = prev->next;
    00879                         }
    00880                 }
    00881         }
    00882
    00883         /* queue1 */
    00884         for (i = 0 ; i < 255 ; i++) {
    00885                 fluid_evt_entry* tmp = seq->queue1[i][0];
    00886                 fluid_evt_entry* prev = NULL;
    00887                 while (tmp) {
    00888                         if (_fluid_seq_queue_matchevent((&tmp->evt), type, src, dest)) {
    00889                                 /* remove */
    00890                                 if (prev) {
    00891                                         prev->next = tmp->next;
    00892                                         if (tmp == seq->queue1[i][1]) // last one in list
    00893                                                 seq->queue1[i][1] = prev;
    00894
    00895                                         _fluid_seq_heap_set_free(seq->heap, tmp);
    00896                                         tmp = prev->next;
    00897                                 } else {
    00898                                         /* first one in list */
    00899                                         seq->queue1[i][0] = tmp->next;
    00900                                         if (tmp == seq->queue1[i][1]) // last one in list
    00901                                                 seq->queue1[i][1] = NULL;
    00902
    00903                                         _fluid_seq_heap_set_free(seq->heap, tmp);
    00904                                         tmp = seq->queue1[i][0];
    00905                                 }
    00906                         } else {
    00907                                 prev = tmp;
    00908                                 tmp = prev->next;
    00909                         }
    00910                 }
    00911         }
    00912
    00913         /* queueLater */
    00914         {
    00915                 fluid_evt_entry* tmp = seq->queueLater;
    00916                 fluid_evt_entry* prev = NULL;
    00917                 while (tmp) {
    00918                         if (_fluid_seq_queue_matchevent((&tmp->evt), type, src, dest)) {
    00919                                 /* remove */
    00920                                 if (prev) {
    00921                                         prev->next = tmp->next;
    00922
    00923                                         _fluid_seq_heap_set_free(seq->heap, tmp);
    00924                                         tmp = prev->next;
    00925                                 } else {
    00926                                         seq->queueLater = tmp->next;
    00927
    00928                                         _fluid_seq_heap_set_free(seq->heap, tmp);
    00929                                         tmp = seq->queueLater;
    00930                                 }
    00931                         } else {
    00932                                 prev = tmp;
    00933                                 tmp = prev->next;
    00934                         }
    00935                 }
    00936         }
    00937 }
    00938
    00939 void
    00940 _fluid_seq_queue_send_cell_events(fluid_sequencer_t* seq, int cellNb)
    00941 {
    00942         fluid_evt_entry* next;
    00943         fluid_evt_entry* tmp;
    00944
    00945         tmp = seq->queue0[cellNb][0];
    00946         while (tmp) {
    00947                 fluid_sequencer_send_now(seq, &(tmp->evt));
    00948
    00949                 next = tmp->next;
    00950
    00951                 _fluid_seq_heap_set_free(seq->heap, tmp);
    00952                 tmp = next;
    00953         }
    00954         seq->queue0[cellNb][0] = NULL;
    00955         seq->queue0[cellNb][1] = NULL;
    00956 }
    00957
    00958 void
    00959 _fluid_seq_queue_slide(fluid_sequencer_t* seq)
    00960 {
    00961         short i;
    00962         fluid_evt_entry* next;
    00963         fluid_evt_entry* tmp;
    00964         int count = 0;
    00965
    00966         /* do the slide */
    00967         seq->queue0StartTime += 256;
    00968
    00969         /* sort all queue1[0] into queue0 according to new queue0StartTime */
    00970         tmp = seq->queue1[0][0];
    00971         while (tmp) {
    00972                 unsigned int delay = tmp->evt.time - seq->queue0StartTime;
    00973                 next = tmp->next;
    00974                 if (delay > 255) {
    00975                         /* should not happen !! */
    00976                         /* append it to queue1[1] */
    00977                         _fluid_seq_queue_insert_queue1(seq, tmp, 1);
    00978                 } else {
    00979                         _fluid_seq_queue_insert_queue0(seq, tmp, delay);
    00980                 }
    00981                 tmp = next;
    00982                 count++;
    00983         }
    00984
    00985         /* slide all queue1[i] into queue1[i-1] */
    00986         for (i = 1 ; i < 255 ; i++) {
    00987                 seq->queue1[i-1][0] = seq->queue1[i][0];
    00988                 seq->queue1[i-1][1] = seq->queue1[i][1];
    00989         }
    00990         seq->queue1[254][0] = NULL;
    00991         seq->queue1[254][1] = NULL;
    00992
    00993
    00994         /* append queueLater to queue1[254] */
    00995         count = 0;
    00996         tmp = seq->queueLater;
    00997         while (tmp) {
    00998                 unsigned int delay = tmp->evt.time - seq->queue0StartTime;
    00999
    01000                 if (delay > 65535) {
    01001                         break;
    01002                 }
    01003
    01004                 next = tmp->next;
    01005
    01006                 /* append it */
    01007                 _fluid_seq_queue_insert_queue1(seq, tmp, 254);
    01008                 tmp = next;
    01009                 count++;
    01010         }
    01011
    01012         seq->queueLater = tmp;
    01013 }
    01014
    01015 void
    01016 _fluid_seq_queue_send_queued_events(fluid_sequencer_t* seq)
    01017 {
    01018         unsigned int nowTicks = fluid_sequencer_get_tick(seq);
    01019         short cellNb;
    01020
    01021         cellNb = seq->prevCellNb + 1;
    01022         while (cellNb <= (int)(nowTicks - seq->queue0StartTime)) {
    01023                 if (cellNb == 256) {
    01024                         cellNb = 0;
    01025                         _fluid_seq_queue_slide(seq);
    01026                 } /* slide */
    01027
    01028
    01029                 /* process queue0[cellNb] */
    01030                 _fluid_seq_queue_send_cell_events(seq, cellNb);
    01031
    01032                 /* next cell */
    01033                 cellNb++;
    01034         }
    01035
    01036         seq->prevCellNb = cellNb - 1;
    01037 }