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 }

Generated on Sat Nov 17 13:40:23 2007 for libfluidsynth by  doxygen 1.5.3