/* Create event_entry and append to the preQueue. * May be called from the main thread (usually) but also recursively * from the queue thread, when a callback itself does an insert... */ static void _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int type) { fluid_evt_entry * evtentry = _fluid_seq_heap_get_free(seq->heap); if (evtentry == NULL) { /* should not happen */ fluid_log(FLUID_PANIC, "sequencer: no more free events\n"); return; } evtentry->next = NULL; evtentry->entryType = FLUID_EVT_ENTRY_REMOVE; { fluid_event_t* evt = &(evtentry->evt); fluid_event_set_source(evt, src); fluid_event_set_source(evt, src); fluid_event_set_dest(evt, dest); evt->type = type; } fluid_mutex_lock(seq->mutex); /* append to preQueue */ if (seq->preQueueLast) { seq->preQueueLast->next = evtentry; } else { seq->preQueue = evtentry; } seq->preQueueLast = evtentry; fluid_mutex_unlock(seq->mutex); return; }
/* schedule a timer event (shall trigger the callback) */ void schedule_timer_event () { fluid_event_t *ev = new_fluid_event (); fluid_event_set_source (ev, -1); fluid_event_set_dest (ev, client_destination); fluid_event_timer (ev, NULL); fluid_sequencer_send_at (sequencer, ev, time_marker, 1); delete_fluid_event (ev); }
/* schedule a note on message */ void schedule_noteon (int chan, short key, unsigned int ticks) { fluid_event_t *ev = new_fluid_event (); fluid_event_set_source (ev, -1); fluid_event_set_dest (ev, synth_destination); fluid_event_noteon (ev, chan, key, 127); fluid_sequencer_send_at (sequencer, ev, ticks, 1); delete_fluid_event (ev); }
static void sendpitchbend(Data *data, int chan, int pitch, int time) { int fluid_res; fluid_event_clear(data->event); fluid_event_set_source(data->event, -1); fluid_event_set_dest(data->event, data->synth_seq_ID); fluid_event_pitch_bend(data->event, chan, pitch); fluid_res = fluid_sequencer_send_at(data->sequencer, data->event, get_fluidsynth_time(data,time), 1); if(fluid_res==FLUID_FAILED) printf("Unable to send pitchbend\n"); }
static void sendcontrolchange(Data *data, int chan, int cc, int val, int time) { int fluid_res; fluid_event_clear(data->event); fluid_event_set_source(data->event, -1); fluid_event_set_dest(data->event, data->synth_seq_ID); fluid_event_control_change(data->event, chan, cc, val); fluid_res = fluid_sequencer_send_at(data->sequencer, data->event, get_fluidsynth_time(data,time), 1); if(fluid_res==FLUID_FAILED) printf("Unable to send controlchange\n"); }
static void sendnoteoff(Data *data, int chan, short key, int velocity, unsigned int time) { int fluid_res; if(velocity>127) // not supported by fluidsynth velocity=127; fluid_event_clear(data->event); fluid_event_set_source(data->event, -1); fluid_event_set_dest(data->event, data->synth_seq_ID); fluid_event_noteoff(data->event, chan, key); fluid_res = fluid_sequencer_send_at(data->sequencer, data->event, get_fluidsynth_time(data,time), 1); if(fluid_res==FLUID_FAILED) printf("Unable to send noteOFF %d (vel: %d) at time %d. Time now: %d\n",key,velocity,time,(int)data->time); }
/** * Transforms an incoming midi event (from a midi driver or midi router) to a * sequencer event and adds it to the sequencer queue for sending as soon as possible. * @param data The sequencer, must be a valid #fluid_sequencer_t * @param event MIDI event * @return #FLUID_OK or #FLUID_FAILED * @since 1.1.0 */ int fluid_sequencer_add_midi_event_to_buffer(void* data, fluid_midi_event_t* event) { fluid_event_t evt; fluid_sequencer_t* seq = (fluid_sequencer_t*) data; int chan = fluid_midi_event_get_channel(event); fluid_event_clear(&evt); fluid_event_set_time(&evt, fluid_sequencer_get_tick(seq)); fluid_event_set_dest(&evt, get_fluidsynth_dest(seq)); switch (fluid_midi_event_get_type(event)) { case NOTE_OFF: fluid_event_noteoff(&evt, chan, fluid_midi_event_get_key(event)); break; case NOTE_ON: fluid_event_noteon(&evt, fluid_midi_event_get_channel(event), fluid_midi_event_get_key(event), fluid_midi_event_get_velocity(event)); break; case CONTROL_CHANGE: fluid_event_control_change(&evt, chan, fluid_midi_event_get_control(event), fluid_midi_event_get_value(event)); break; case PROGRAM_CHANGE: fluid_event_program_change(&evt, chan, fluid_midi_event_get_program(event)); break; case PITCH_BEND: fluid_event_pitch_bend(&evt, chan, fluid_midi_event_get_pitch(event)); break; case CHANNEL_PRESSURE: fluid_event_channel_pressure(&evt, chan, fluid_midi_event_get_program(event)); break; case MIDI_SYSTEM_RESET: fluid_event_system_reset(&evt); break; default: /* Not yet implemented */ return FLUID_FAILED; } /* Schedule for sending at next call to fluid_sequencer_process */ return fluid_sequencer_send_at(seq, &evt, 0, 0); }
/** * Unregister a previously registered client. * @param seq Sequencer object * @param id Client ID as returned by fluid_sequencer_register_client(). */ void fluid_sequencer_unregister_client (fluid_sequencer_t* seq, short id) { fluid_list_t *tmp; fluid_event_t* evt; if (seq->clients == NULL) return; evt = new_fluid_event(); if (evt != NULL) { fluid_event_unregistering(evt); fluid_event_set_dest(evt, id); } tmp = seq->clients; while (tmp) { fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data; if (client->id == id) { /* What should we really do if evt is null due to out-of-memory? */ if (client->callback != NULL && evt != NULL) (client->callback)(fluid_sequencer_get_tick(seq), evt, seq, client->data); if (client->name) FLUID_FREE(client->name); seq->clients = fluid_list_remove_link(seq->clients, tmp); delete1_fluid_list(tmp); FLUID_FREE(client); delete_fluid_event(evt); return; } tmp = tmp->next; } delete_fluid_event(evt); return; }