diff --git a/doc/fluidsynth-v11-devdoc.txt b/doc/fluidsynth-v11-devdoc.txt index 53408e59..8fa724b1 100644 --- a/doc/fluidsynth-v11-devdoc.txt +++ b/doc/fluidsynth-v11-devdoc.txt @@ -95,6 +95,7 @@ Changes in FluidSynth 2.0.0 concerning developers: - add fluid_synth_add_default_mod() for manipulating default modulators - add individual reverb setters: fluid_synth_set_reverb_roomsize(), fluid_synth_set_reverb_damp(), fluid_synth_set_reverb_width(), fluid_synth_set_reverb_level() - add individual chorus setters: fluid_synth_set_chorus_nr(), fluid_synth_set_chorus_level(), fluid_synth_set_chorus_speed(), fluid_synth_set_chorus_depth(), fluid_synth_set_chorus_type() +- add a function for registering audio drivers based on acutal needs: fluid_audio_driver_register() - introduce a separate data type for sequencer client IDs: #fluid_seq_id_t @@ -788,3 +789,8 @@ Example of a simple metronome using the MIDI sequencer API \example fluidsynth_arpeggio.c Example of an arpeggio generated using the MIDI sequencer API */ + +/*! +\example fluidsynth_register_adriver.c +Example of how to register audio drivers using fluid_audio_driver_register() (advanced users only) +*/ diff --git a/doc/fluidsynth_register_adriver.c b/doc/fluidsynth_register_adriver.c new file mode 100644 index 00000000..b5a08b54 --- /dev/null +++ b/doc/fluidsynth_register_adriver.c @@ -0,0 +1,60 @@ +/** + * This is a simple C99 program that demonstrates the usage of fluid_audio_driver_register() + * + * There are 3 calls to fluid_audio_driver_register(), i.e. 3 iterations: + * First the alsa driver is registered and created, followed by the jack and portaudio driver. + * + * The usual usecase would be to call fluid_audio_driver_register() only once providing the audio drivers needed during fluidsynth usage. + * If necessary however fluid_audio_driver_register() can be called multiple times as demonstrated here. + * Therefore the user must make sure to delete all fluid-instances of any kind before making the call to fluid_audio_driver_register(). + * Else the behaviour is undefined and the application is likely to crash. + */ + +#include +#include + +int main() +{ + const char* DRV[] = { "alsa", "jack", "portaudio" }; + const char* adrivers[2]; + + for(int i=0; iname) { - fluid_audio_drivers[i].free(driver); + /* iterate over fluid_audio_drivers_template to ensure deleting even drivers currently not registered */ + for (i = 0; i < FLUID_N_ELEMENTS(fluid_audio_drivers_template); i++) { + if (fluid_audio_drivers_template[i].name == driver->name) { + fluid_audio_drivers_template[i].free(driver); return; } } } + + +/** + * @brief Registers audio drivers to use + * + * When creating a settings instance with new_fluid_settings(), all audio drivers are initialized once. + * In the past this has caused segfaults and application crashes due to buggy soundcard drivers. + * + * This function enables the user to only initialize specific audio drivers when settings instances are created. + * Therefore pass a NULL-terminated array of C-strings containing the \c names of audio drivers to register + * for the usage with fluidsynth. + * The \c names are the same as being used for the \c audio.driver setting. + * + * By default all audio drivers fluidsynth has been compiled with are registered, so calling this function is optional. + * + * @warning This function may only be called if no thread is residing in fluidsynth's API and no instances of any kind + * are alive (e.g. as it would be the case right after fluidsynth's inital creation). Else the behaviour is undefined. + * Furtermore any attempt of using audio drivers that have not been registered is undefined behaviour! + * + * @param adrivers NULL-terminated array of audio drivers to register. Pass NULL to register all available drivers. + * @return #FLUID_OK if all the audio drivers requested by the user are supported by fluidsynth and have been + * successfully registered. Otherwise #FLUID_FAILED is returned and ALL available audio drivers are registered instead. + * + * @note This function is not thread safe and will never be! + */ +int fluid_audio_driver_register(const char** adrivers) +{ + unsigned int i=0, add=0; + int res = FLUID_FAILED; + + if(adrivers == NULL) + { + res = FLUID_OK; + goto cleanup; + } + else + { + FLUID_MEMSET(fluid_audio_drivers, 0, sizeof(fluid_audio_drivers)); + for(i=0; adrivers[i] != NULL; i++) + { + unsigned int j; + /* search the requested audio driver in the template and copy it over if found */ + for (j = 0; j < FLUID_N_ELEMENTS(fluid_audio_drivers_template); j++) + { + if (FLUID_STRCMP(adrivers[i], fluid_audio_drivers_template[j].name) == 0) + { + FLUID_MEMCPY(&fluid_audio_drivers[add], &fluid_audio_drivers_template[j], sizeof(fluid_audio_drivers[add])); + add++; + break; + } + } + + if(j >= FLUID_N_ELEMENTS(fluid_audio_drivers_template)) + { + /* requested driver not found, failure */ + goto cleanup; + } + } + } + + if(i >= FLUID_N_ELEMENTS(fluid_audio_drivers_template)) + { + /* user requested more drivers than this build of fluidsynth supports, failure */ + goto cleanup; + } + + res = FLUID_OK; + return res; + +cleanup: + FLUID_MEMCPY(fluid_audio_drivers, fluid_audio_drivers_template, sizeof(fluid_audio_drivers)); + return res; +}