/** * Iterate the existing settings defined in a settings object, calling the * provided callback function for each setting. * * @param settings a settings object * @param data any user provided pointer * @param func callback function to be called on each iteration * * NOTE: Starting with FluidSynth 1.1.0 the \a func callback is called for each * setting in alphabetical order. Sort order was undefined in previous versions. */ void fluid_settings_foreach (fluid_settings_t* settings, void* data, fluid_settings_foreach_t func) { fluid_settings_foreach_bag_t bag; fluid_setting_node_t *node; fluid_list_t *p; int r; fluid_return_if_fail (settings != NULL); fluid_return_if_fail (func != NULL); bag.path[0] = 0; bag.names = NULL; fluid_rec_mutex_lock (settings->mutex); /* Add all node names to the bag.names list */ fluid_hashtable_foreach (settings, fluid_settings_foreach_iter, &bag); /* Sort names */ bag.names = fluid_list_sort (bag.names, fluid_list_str_compare_func); /* Loop over names and call the callback */ for (p = bag.names; p; p = p->next) { r = fluid_settings_get (settings, (char *)(p->data), &node); if (r && node) (*func) (data, (char *)(p->data), node->type); FLUID_FREE (p->data); /* -- Free name */ } fluid_rec_mutex_unlock (settings->mutex); delete_fluid_list (bag.names); /* -- Free names list */ }
/** * delete_fluid_hashtable: * @hashtable: a #fluid_hashtable_t. * * Destroys all keys and values in the #fluid_hashtable_t and decrements its * reference count by 1. If keys and/or values are dynamically allocated, * you should either free them first or create the #fluid_hashtable_t with destroy * notifiers using fluid_hashtable_new_full(). In the latter case the destroy * functions you supplied will be called on all keys and values during the * destruction phase. **/ void delete_fluid_hashtable (fluid_hashtable_t *hashtable) { fluid_return_if_fail (hashtable != NULL); fluid_return_if_fail (hashtable->ref_count > 0); fluid_hashtable_remove_all (hashtable); fluid_hashtable_unref (hashtable); }
/** * fluid_hashtable_unref: * @hashtable: a valid #fluid_hashtable_t. * * Atomically decrements the reference count of @hashtable by one. * If the reference count drops to 0, all keys and values will be * destroyed, and all memory allocated by the hash table is released. * This function is MT-safe and may be called from any thread. * * Since: 2.10 **/ void fluid_hashtable_unref (fluid_hashtable_t *hashtable) { fluid_return_if_fail (hashtable != NULL); fluid_return_if_fail (hashtable->ref_count > 0); if (fluid_atomic_int_exchange_and_add (&hashtable->ref_count, -1) - 1 == 0) { fluid_hashtable_remove_all_nodes (hashtable, TRUE); FLUID_FREE (hashtable->nodes); FLUID_FREE (hashtable); } }
/* * fluid_hashtable_insert_internal: * @hashtable: our #fluid_hashtable_t * @key: the key to insert * @value: the value to insert * @keep_new_key: if %TRUE and this key already exists in the table * then call the destroy notify function on the old key. If %FALSE * then call the destroy notify function on the new key. * * Implements the common logic for the fluid_hashtable_insert() and * fluid_hashtable_replace() functions. * * Do a lookup of @key. If it is found, replace it with the new * @value (and perhaps the new @key). If it is not found, create a * new node. */ static void fluid_hashtable_insert_internal (fluid_hashtable_t *hashtable, void *key, void *value, int keep_new_key) { fluid_hashnode_t **node_ptr, *node; unsigned int key_hash; fluid_return_if_fail (hashtable != NULL); fluid_return_if_fail (hashtable->ref_count > 0); node_ptr = fluid_hashtable_lookup_node (hashtable, key, &key_hash); if ((node = *node_ptr)) { if (keep_new_key) { if (hashtable->key_destroy_func) hashtable->key_destroy_func (node->key); node->key = key; } else { if (hashtable->key_destroy_func) hashtable->key_destroy_func (key); } if (hashtable->value_destroy_func) hashtable->value_destroy_func (node->value); node->value = value; } else { node = FLUID_NEW (fluid_hashnode_t); if (!node) { FLUID_LOG (FLUID_ERR, "Out of memory"); return; } node->key = key; node->value = value; node->key_hash = key_hash; node->next = NULL; *node_ptr = node; hashtable->nnodes++; fluid_hashtable_maybe_resize (hashtable); } }
static void iter_remove_or_steal (RealIter *ri, int notify) { fluid_hashnode_t *prev; fluid_hashnode_t *node; int position; fluid_return_if_fail (ri != NULL); fluid_return_if_fail (ri->node != NULL); prev = ri->prev_node; node = ri->node; position = ri->position; /* pre-advance the iterator since we will remove the node */ ri->node = ri->node->next; /* ri->prev_node is still the correct previous node */ while (ri->node == NULL) { ri->position++; if (ri->position >= ri->hashtable->size) break; ri->prev_node = NULL; ri->node = ri->hashtable->nodes[ri->position]; } ri->pre_advanced = TRUE; /* remove the node */ if (prev != NULL) prev->next = node->next; else ri->hashtable->nodes[position] = node->next; if (notify) { if (ri->hashtable->key_destroy_func) ri->hashtable->key_destroy_func(node->key); if (ri->hashtable->value_destroy_func) ri->hashtable->value_destroy_func(node->value); } FLUID_FREE (node); ri->hashtable->nnodes--; }
/** * fluid_hashtable_foreach: * @hashtable: a #fluid_hashtable_t. * @func: the function to call for each key/value pair. * @user_data: user data to pass to the function. * * Calls the given function for each of the key/value pairs in the * #fluid_hashtable_t. The function is passed the key and value of each * pair, and the given @user_data parameter. The hash table may not * be modified while iterating over it (you can't add/remove * items). To remove all items matching a predicate, use * fluid_hashtable_foreach_remove(). * * See fluid_hashtable_find() for performance caveats for linear * order searches in contrast to fluid_hashtable_lookup(). **/ void fluid_hashtable_foreach (fluid_hashtable_t *hashtable, fluid_hr_func_t func, void *user_data) { fluid_hashnode_t *node; int i; fluid_return_if_fail (hashtable != NULL); fluid_return_if_fail (func != NULL); for (i = 0; i < hashtable->size; i++) for (node = hashtable->nodes[i]; node; node = node->next) (* func) (node->key, node->value, user_data); }
/** * fluid_hashtable_iter_init: * @iter: an uninitialized #fluid_hashtable_iter_t. * @hashtable: a #fluid_hashtable_t. * * Initializes a key/value pair iterator and associates it with * @hashtable. Modifying the hash table after calling this function * invalidates the returned iterator. * |[ * fluid_hashtable_iter_t iter; * gpointer key, value; * * fluid_hashtable_iter_init (&iter, hashtable); * while (fluid_hashtable_iter_next (&iter, &key, &value)) * { * /* do something with key and value */ * } * ]| * * Since: 2.16 **/ void fluid_hashtable_iter_init (fluid_hashtable_iter_t *iter, fluid_hashtable_t *hashtable) { RealIter *ri = (RealIter *) iter; fluid_return_if_fail (iter != NULL); fluid_return_if_fail (hashtable != NULL); ri->hashtable = hashtable; ri->prev_node = NULL; ri->node = NULL; ri->position = -1; ri->pre_advanced = FALSE; }
void delete_fluid_dsound_audio_driver(fluid_audio_driver_t* d) { fluid_dsound_audio_driver_t* dev = (fluid_dsound_audio_driver_t*) d; fluid_return_if_fail(dev != NULL); /* tell the audio thread to stop its loop */ dev->cont = 0; /* wait till the audio thread exits */ if (dev->thread != 0) { if (WaitForSingleObject(dev->thread, 2000) != WAIT_OBJECT_0) { /* on error kill the thread mercilessly */ FLUID_LOG(FLUID_DBG, "Couldn't join the audio thread. killing it."); TerminateThread(dev->thread, 0); } } /* release all the allocated ressources */ FLUID_FREE(dev->format); if (dev->sec_buffer != NULL) { IDirectSoundBuffer_Stop(dev->sec_buffer); IDirectSoundBuffer_Release(dev->sec_buffer); } if (dev->prim_buffer != NULL) { IDirectSoundBuffer_Release(dev->prim_buffer); } if (dev->direct_sound != NULL) { IDirectSound_Release(dev->direct_sound); } FLUID_FREE(dev); }
/* Add a reference to a tuning object */ void fluid_tuning_ref (fluid_tuning_t *tuning) { fluid_return_if_fail (tuning != NULL); fluid_atomic_int_inc (&tuning->refcount); }
/* Only called by delete_fluid_synth(), so no need to queue a preset free event */ void delete_fluid_channel(fluid_channel_t* chan) { fluid_return_if_fail(chan != NULL); fluid_preset_delete_internal (chan->preset); FLUID_FREE(chan); }
/** * fluid_hashtable_steal_all: * @hashtable: a #fluid_hashtable_t. * * Removes all keys and their associated values from a #fluid_hashtable_t * without calling the key and value destroy functions. * * Since: 2.12 **/ void fluid_hashtable_steal_all (fluid_hashtable_t *hashtable) { fluid_return_if_fail (hashtable != NULL); fluid_hashtable_remove_all_nodes (hashtable, FALSE); fluid_hashtable_maybe_resize (hashtable); }
/** * Delete the provided settings object * @param settings a settings object */ void delete_fluid_settings(fluid_settings_t* settings) { fluid_return_if_fail (settings != NULL); fluid_rec_mutex_destroy (settings->mutex); delete_fluid_hashtable(settings); }
static void delete_samplecache_entry(fluid_samplecache_entry_t *entry) { fluid_return_if_fail(entry != NULL); FLUID_FREE(entry->filename); FLUID_FREE(entry->sample_data); FLUID_FREE(entry->sample_data24); FLUID_FREE(entry); }
/** * Set the second parameter portion of a rule. * @param rule MIDI router rule * @param min Minimum value for rule match * @param max Maximum value for rule match * @param mul Value which is multiplied by matching event's 2nd parameter value (1.0 to not modify) * @param add Value which is added to matching event's 2nd parameter value (0 to not modify) * @since 1.1.0 * * The 2nd parameter of an event depends on the type of event. For note events * its the MIDI velocity, for CC events its the control value and for key pressure * events its the key pressure value. All other types lack a 2nd parameter. * * All applicable 2nd parameters have the range 0-127. * * The \a min and \a max parameters define a parameter range window to match * incoming events to. If \a min is less than or equal to \a max then an event * is matched if its 2nd parameter is within the defined range (including \a min * and \a max). If \a min is greater than \a max then rule is inverted and matches * everything except in *between* the defined range (so \a min and \a max would match). * * The \a mul and \a add values are used to modify event 2nd parameter values prior to * sending the event, if the rule matches. */ void fluid_midi_router_rule_set_param2 (fluid_midi_router_rule_t *rule, int min, int max, float mul, int add) { fluid_return_if_fail (rule != NULL); rule->par2_min = min; rule->par2_max = max; rule->par2_mul = mul; rule->par2_add = add; }
void delete_fluid_list(fluid_list_t *list) { fluid_list_t *next; fluid_return_if_fail(list != NULL); while (list) { next = list->next; FLUID_FREE(list); list = next; } }
void fluid_settings_init(fluid_settings_t* settings) { fluid_return_if_fail (settings != NULL); fluid_synth_settings(settings); fluid_shell_settings(settings); fluid_player_settings(settings); fluid_file_renderer_settings(settings); fluid_audio_driver_settings(settings); fluid_midi_driver_settings(settings); }
/** * Get the range of values of an integer setting * @param settings a settings object * @param name a setting's name * @param min setting's range lower limit * @param max setting's range upper limit */ void fluid_settings_getint_range(fluid_settings_t* settings, const char *name, int* min, int* max) { fluid_setting_node_t *node; fluid_return_if_fail (settings != NULL); fluid_return_if_fail (name != NULL); fluid_return_if_fail (min != NULL); fluid_return_if_fail (max != NULL); fluid_rec_mutex_lock (settings->mutex); if (fluid_settings_get(settings, name, &node) && (node->type == FLUID_INT_TYPE)) { fluid_int_setting_t* setting = (fluid_int_setting_t*) node; *min = setting->min; *max = setting->max; } fluid_rec_mutex_unlock (settings->mutex); }
/** * Iterate the available options for a named string setting, calling the provided * callback function for each existing option. * * @param settings a settings object * @param name a setting's name * @param data any user provided pointer * @param func callback function to be called on each iteration * * NOTE: Starting with FluidSynth 1.1.0 the \a func callback is called for each * option in alphabetical order. Sort order was undefined in previous versions. */ void fluid_settings_foreach_option (fluid_settings_t* settings, const char *name, void* data, fluid_settings_foreach_option_t func) { fluid_setting_node_t *node; fluid_str_setting_t *setting; fluid_list_t *p, *newlist = NULL; fluid_return_if_fail (settings != NULL); fluid_return_if_fail (name != NULL); fluid_return_if_fail (func != NULL); fluid_rec_mutex_lock (settings->mutex); /* ++ lock */ if (!fluid_settings_get (settings, name, &node) || node->type != FLUID_STR_TYPE) { fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */ return; } setting = (fluid_str_setting_t*)node; /* Duplicate option list */ for (p = setting->options; p; p = p->next) newlist = fluid_list_append (newlist, fluid_list_get (p)); /* Sort by name */ newlist = fluid_list_sort (newlist, fluid_list_str_compare_func); for (p = newlist; p; p = p->next) (*func)(data, (char *)name, (char *)fluid_list_get (p)); fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */ delete_fluid_list (newlist); }
/* * delete_fluid_portaudio_driver */ void delete_fluid_portaudio_driver(fluid_audio_driver_t *p) { fluid_portaudio_driver_t* dev = (fluid_portaudio_driver_t*)p; PaError err; fluid_return_if_fail(dev != NULL); /* PortAudio section */ if (dev->stream) Pa_CloseStream (dev->stream); err = Pa_Terminate(); if (err != paNoError) printf ("PortAudio termination error: %s\n", Pa_GetErrorText (err) ); FLUID_FREE (dev); }
/** * Delete a MIDI router instance. * @param router MIDI router to delete * @return Returns #FLUID_OK on success, #FLUID_FAILED otherwise (only if NULL * \a router passed really) */ void delete_fluid_midi_router (fluid_midi_router_t *router) { fluid_midi_router_rule_t *rule; fluid_midi_router_rule_t *next_rule; int i; fluid_return_if_fail (router != NULL); for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) { for (rule = router->rules[i]; rule; rule = next_rule) { next_rule = rule->next; FLUID_FREE (rule); } } fluid_mutex_destroy (router->rules_mutex); FLUID_FREE (router); }
/* * delete_fluid_sndmgr_audio_driver */ void delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p) { fluid_sndmgr_audio_driver_t* dev = (fluid_sndmgr_audio_driver_t*) p; fluid_return_if_fail(dev != NULL); if (dev->channel != NULL) { SndDisposeChannel(dev->channel, 1); } if (dev->doubleCallbackProc != NULL) { DisposeRoutineDescriptor(dev->doubleCallbackProc); } if (dev->doubleHeader != NULL) { FLUID_FREE(dev->doubleHeader->dbhBufferPtr[0]); FLUID_FREE(dev->doubleHeader->dbhBufferPtr[1]); FLUID_FREE(dev->doubleHeader); } FLUID_FREE(dev->convbuffers[0]); FLUID_FREE(dev->convbuffers[1]); FLUID_FREE(dev); }
/** * Free a MIDI router rule. * @param rule Router rule to free * @since 1.1.0 * * Note that rules which have been added to a router are managed by the router, * so this function should seldom be needed. */ void delete_fluid_midi_router_rule (fluid_midi_router_rule_t *rule) { fluid_return_if_fail (rule != NULL); FLUID_FREE (rule); }