--- Makefile (revision 422412) +++ Makefile (working copy) @@ -13,7 +13,7 @@ LICENSE= LGPL20 LICENSE_FILE= ${WRKSRC}/COPYING -OPTIONS_DEFINE= JACK ALSA DBUS LADSPA LASH PORTAUDIO PULSEAUDIO SNDFILE +OPTIONS_DEFINE= JACK ALSA DBUS LADSPA LASH PORTAUDIO PULSEAUDIO SNDFILE SNDIO OPTIONS_DEFAULT= JACK USE_GNOME= glib20 @@ -49,7 +49,11 @@ SNDFILE_LIB_DEPENDS= libsndfile.so:audio/libsndfile SNDFILE_CMAKE_OFF= -Denable-libsndfile:BOOL=FALSE +SNDIO_LIB_DEPENDS= libsndio.so:audio/sndio +SNDIO_CMAKE_OFF= -Denable-sndio:BOOL=FALSE + post-patch: + ${CP} ${FILESDIR}/fluid_sndio.c ${WRKSRC}/src/drivers/ @${REINPLACE_CMD} -e \ '/Linux/s|^|#| ; \ /_init_lib_suffix/s|"64"|""| ; \ --- files/fluid_sndio.c (nonexistent) +++ files/fluid_sndio.c (working copy) @@ -0,0 +1,521 @@ +/* sndio backend for FluidSynth - A Software Synthesizer + * + * Copyright (c) 2008 Jacob Meuser + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +/* fluid_sndio.c + * + * Driver for the sndio audio access library + */ + +#include "fluid_synth.h" +#include "fluid_adriver.h" +#include "fluid_midi.h" +#include "fluid_mdriver.h" +#include "fluid_settings.h" + +#if SNDIO_SUPPORT + +#include + +#include +#include +#include +#include + + +/** fluid_sndio_audio_driver_t + * + * This structure should not be accessed directly. Use audio port + * functions instead. + */ +typedef struct { + fluid_audio_driver_t driver; + fluid_synth_t* synth; + fluid_audio_callback_t read; + void* buffer; + pthread_t thread; + int cont; + struct sio_hdl *hdl; + struct sio_par par; + int buffer_size; + int buffer_byte_size; + fluid_audio_func_t callback; + void* data; + float* buffers[2]; +} fluid_sndio_audio_driver_t; + +typedef struct { + fluid_midi_driver_t driver; + struct mio_hdl *hdl; + pthread_t thread; + int status; + fluid_midi_parser_t *parser; +} fluid_sndio_midi_driver_t; + +int delete_fluid_sndio_audio_driver(fluid_audio_driver_t* p); + +/* local utilities */ +static void* fluid_sndio_audio_run(void* d); +static void* fluid_sndio_audio_run2(void* d); + + +void +fluid_sndio_audio_driver_settings(fluid_settings_t* settings) +{ + fluid_settings_register_str(settings, "audio.sndio.device", "default", 0, NULL, NULL); +} + +/* + * new_fluid_sndio_audio_driver + */ +fluid_audio_driver_t* +new_fluid_sndio_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) +{ + fluid_sndio_audio_driver_t* dev = NULL; + double sample_rate; + int periods, period_size; + char* devname; + pthread_attr_t attr; + int err; + + dev = FLUID_NEW(fluid_sndio_audio_driver_t); + if (dev == NULL) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + FLUID_MEMSET(dev, 0, sizeof(fluid_sndio_audio_driver_t)); + + fluid_settings_getint(settings, "audio.periods", &periods); + fluid_settings_getint(settings, "audio.period-size", &period_size); + fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); + + dev->hdl = NULL; + dev->synth = synth; + dev->callback = NULL; + dev->data = NULL; + dev->cont = 1; + + if (!fluid_settings_getstr(settings, "audio.sndio.device", &devname)) { + devname = NULL; + } + + dev->hdl = sio_open(devname, SIO_PLAY, 0); + if (dev->hdl == NULL) { + FLUID_LOG(FLUID_ERR, "sndio could not be opened for writing"); + goto error_recovery; + } + + sio_initpar(&dev->par); + + if (fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) { + dev->par.bits = 16; + dev->par.le = SIO_LE_NATIVE; + dev->read = fluid_synth_write_s16; + } else { + FLUID_LOG(FLUID_ERR, "Unknown sample format"); + goto error_recovery; + } + + dev->par.appbufsz = period_size * periods; + dev->par.round = period_size; + + dev->par.pchan = 2; + dev->par.rate = sample_rate; + + if (!sio_setpar(dev->hdl, &dev->par)) { + FLUID_LOG(FLUID_ERR, "Couldn't set sndio audio parameters"); + goto error_recovery; + } + + if (!sio_getpar(dev->hdl, &dev->par)) { + FLUID_LOG(FLUID_ERR, "Couldn't get sndio audio parameters"); + goto error_recovery; + } else if (dev->par.pchan != 2 || dev->par.rate != sample_rate || + dev->par.bits != 16) { + FLUID_LOG(FLUID_ERR, "Couldn't set sndio audio parameters as desired"); + goto error_recovery; + } + + dev->buffer_size = dev->par.round; + dev->buffer_byte_size = dev->par.round * dev->par.bps * dev->par.pchan; + + dev->buffer = FLUID_MALLOC(dev->buffer_byte_size); + if (dev->buffer == NULL) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + + if (!sio_start(dev->hdl)) { + FLUID_LOG(FLUID_ERR, "Couldn't start sndio"); + goto error_recovery; + } + + if (pthread_attr_init(&attr)) { + FLUID_LOG(FLUID_ERR, "Couldn't initialize audio thread attributes"); + goto error_recovery; + } + + err = pthread_create(&dev->thread, &attr, fluid_sndio_audio_run, (void*) dev); + if (err) { + FLUID_LOG(FLUID_ERR, "Couldn't create audio thread"); + goto error_recovery; + } + + return (fluid_audio_driver_t*) dev; + +error_recovery: + delete_fluid_sndio_audio_driver((fluid_audio_driver_t*) dev); + return NULL; +} + +fluid_audio_driver_t* +new_fluid_sndio_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data) +{ + fluid_sndio_audio_driver_t* dev = NULL; + double sample_rate; + int periods, period_size; + char* devname; + pthread_attr_t attr; + int err; + + dev = FLUID_NEW(fluid_sndio_audio_driver_t); + if (dev == NULL) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + FLUID_MEMSET(dev, 0, sizeof(fluid_sndio_audio_driver_t)); + + fluid_settings_getint(settings, "audio.periods", &periods); + fluid_settings_getint(settings, "audio.period-size", &period_size); + fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); + + dev->hdl = NULL; + dev->synth = NULL; + dev->read = NULL; + dev->callback = func; + dev->data = data; + dev->cont = 1; + + if (!fluid_settings_getstr(settings, "audio.sndio.device", &devname)) { + devname = NULL; + } + + dev->hdl = sio_open(devname, SIO_PLAY, 0); + if (dev->hdl == NULL) { + FLUID_LOG(FLUID_ERR, "sndio could not be opened for writing"); + goto error_recovery; + } + + sio_initpar(&dev->par); + + dev->par.appbufsz = period_size * periods; + dev->par.round = period_size; + + dev->par.bits = 16; + dev->par.le = SIO_LE_NATIVE; + dev->par.pchan = 2; + dev->par.rate = sample_rate; + + if (!sio_setpar(dev->hdl, &dev->par)){ + FLUID_LOG(FLUID_ERR, "Can't configure sndio parameters"); + goto error_recovery; + } + + if (!sio_getpar(dev->hdl, &dev->par)) { + FLUID_LOG(FLUID_ERR, "Couldn't get sndio audio parameters"); + goto error_recovery; + } else if (dev->par.pchan != 2 || dev->par.rate != sample_rate || + dev->par.bits != 16) { + FLUID_LOG(FLUID_ERR, "Couldn't set sndio audio parameters as desired"); + goto error_recovery; + } + + dev->buffer_size = dev->par.round; + dev->buffer_byte_size = dev->par.round * dev->par.bps * dev->par.pchan; + + /* allocate the buffers. FIXME!!! don't use interleaved samples */ + dev->buffer = FLUID_MALLOC(dev->buffer_byte_size); + if (dev->buffer == NULL) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + dev->buffers[0] = FLUID_ARRAY(float, dev->buffer_size); + dev->buffers[1] = FLUID_ARRAY(float, dev->buffer_size); + if ((dev->buffer == NULL) || (dev->buffers[0] == NULL) || (dev->buffers[1] == NULL)) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + + if (!sio_start(dev->hdl)) { + FLUID_LOG(FLUID_ERR, "Couldn't start sndio"); + goto error_recovery; + } + + if (pthread_attr_init(&attr)) { + FLUID_LOG(FLUID_ERR, "Couldn't initialize audio thread attributes"); + goto error_recovery; + } + + err = pthread_create(&dev->thread, &attr, fluid_sndio_audio_run2, (void*) dev); + if (err) { + FLUID_LOG(FLUID_ERR, "Couldn't create audio2 thread"); + goto error_recovery; + } + + return (fluid_audio_driver_t*) dev; + +error_recovery: + delete_fluid_sndio_audio_driver((fluid_audio_driver_t*) dev); + return NULL; +} + +/* + * delete_fluid_sndio_audio_driver + */ +int +delete_fluid_sndio_audio_driver(fluid_audio_driver_t* p) +{ + fluid_sndio_audio_driver_t* dev = (fluid_sndio_audio_driver_t*) p; + + if (dev == NULL) { + return FLUID_OK; + } + dev->cont = 0; + if (dev->thread) { + if (pthread_join(dev->thread, NULL)) { + FLUID_LOG(FLUID_ERR, "Failed to join the audio thread"); + return FLUID_FAILED; + } + } + if (dev->hdl) { + sio_close(dev->hdl); + } + if (dev->buffer != NULL) { + FLUID_FREE(dev->buffer); + } + FLUID_FREE(dev); + return FLUID_OK; +} + +/* + * fluid_sndio_audio_run + */ +void* +fluid_sndio_audio_run(void* d) +{ + fluid_sndio_audio_driver_t* dev = (fluid_sndio_audio_driver_t*) d; + fluid_synth_t* synth = dev->synth; + void* buffer = dev->buffer; + int len = dev->buffer_size; + + /* it's as simple as that: */ + while (dev->cont) + { + dev->read (synth, len, buffer, 0, 2, buffer, 1, 2); + sio_write (dev->hdl, buffer, dev->buffer_byte_size); + } + + FLUID_LOG(FLUID_DBG, "Audio thread finished"); + + pthread_exit(NULL); + + return 0; /* not reached */ +} + + +/* + * fluid_sndio_audio_run + */ +void* +fluid_sndio_audio_run2(void* d) +{ + fluid_sndio_audio_driver_t* dev = (fluid_sndio_audio_driver_t*) d; + short* buffer = (short*) dev->buffer; + float* left = dev->buffers[0]; + float* right = dev->buffers[1]; + int buffer_size = dev->buffer_size; + int dither_index = 0; + + FLUID_LOG(FLUID_DBG, "Audio thread running"); + + /* it's as simple as that: */ + while (dev->cont) + { + (*dev->callback)(dev->data, buffer_size, 0, NULL, 2, dev->buffers); + + fluid_synth_dither_s16 (&dither_index, buffer_size, left, right, + buffer, 0, 2, buffer, 1, 2); + + sio_write (dev->hdl, buffer, dev->buffer_byte_size); + } + + FLUID_LOG(FLUID_DBG, "Audio thread finished"); + + pthread_exit(NULL); + + return 0; /* not reached */ +} + +void fluid_sndio_midi_driver_settings(fluid_settings_t* settings) +{ + fluid_settings_register_str(settings, "midi.sndio.device", "default", 0, NULL, NULL); +} + +int +delete_fluid_sndio_midi_driver(fluid_midi_driver_t *addr) +{ + int err; + fluid_sndio_midi_driver_t *dev = (fluid_sndio_midi_driver_t *)addr; + + if (dev == NULL) { + return FLUID_OK; + } + dev->status = FLUID_MIDI_DONE; + + /* cancel the thread and wait for it before cleaning up */ + if (dev->thread) { + err = pthread_cancel(dev->thread); + if (err) { + FLUID_LOG(FLUID_ERR, "Failed to cancel the midi thread"); + return FLUID_FAILED; + } + if (pthread_join(dev->thread, NULL)) { + FLUID_LOG(FLUID_ERR, "Failed to join the midi thread"); + return FLUID_FAILED; + } + } + if (dev->hdl != NULL) { + mio_close(dev->hdl); + } + if (dev->parser != NULL) { + delete_fluid_midi_parser(dev->parser); + } + FLUID_FREE(dev); + return FLUID_OK; +} + +void * +fluid_sndio_midi_run(void *addr) +{ + int n, i; + fluid_midi_event_t* evt; + fluid_sndio_midi_driver_t *dev = (fluid_sndio_midi_driver_t *)addr; +#define MIDI_BUFLEN (3125 / 10) + unsigned char buffer[MIDI_BUFLEN]; + + /* make sure the other threads can cancel this thread any time */ + if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) { + FLUID_LOG(FLUID_ERR, "Failed to set the cancel state of the midi thread"); + pthread_exit(NULL); + } + if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { + FLUID_LOG(FLUID_ERR, "Failed to set the cancel state of the midi thread"); + pthread_exit(NULL); + } + + /* go into a loop until someone tells us to stop */ + dev->status = FLUID_MIDI_LISTENING; + + while (dev->status == FLUID_MIDI_LISTENING) { + + /* read new data */ + n = mio_read(dev->hdl, buffer, MIDI_BUFLEN); + if (n == 0 && mio_eof(dev->hdl)) { + FLUID_LOG(FLUID_ERR, "Failed to read the midi input"); + dev->status = FLUID_MIDI_DONE; + } + + /* let the parser convert the data into events */ + for (i = 0; i < n; i++) { + evt = fluid_midi_parser_parse(dev->parser, buffer[i]); + if (evt != NULL) { + /* send the event to the next link in the chain */ + (*dev->driver.handler)(dev->driver.data, evt); + } + } + } + pthread_exit(NULL); +} + +int +fluid_sndio_midi_driver_status(fluid_midi_driver_t *addr) +{ + fluid_sndio_midi_driver_t *dev = (fluid_sndio_midi_driver_t *)addr; + return dev->status; +} + + +fluid_midi_driver_t * +new_fluid_sndio_midi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, void *data) +{ + int err; + fluid_sndio_midi_driver_t *dev; + char *device; + + /* not much use doing anything */ + if (handler == NULL) { + FLUID_LOG(FLUID_ERR, "Invalid argument"); + return NULL; + } + + /* allocate the device */ + dev = FLUID_NEW(fluid_sndio_midi_driver_t); + if (dev == NULL) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + FLUID_MEMSET(dev, 0, sizeof(fluid_sndio_midi_driver_t)); + dev->hdl = NULL; + + dev->driver.handler = handler; + dev->driver.data = data; + + /* allocate one event to store the input data */ + dev->parser = new_fluid_midi_parser(); + if (dev->parser == NULL) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + + /* get the device name. if none is specified, use the default device. */ + if (!fluid_settings_getstr(settings, "midi.sndio.device", &device)) { + device = NULL; + } + + /* open the default hardware device. only use midi in. */ + dev->hdl = mio_open(device, MIO_IN, 0); + if (dev->hdl == NULL) { + FLUID_LOG(FLUID_ERR, "Couldn't open sndio midi device"); + goto error_recovery; + } + + dev->status = FLUID_MIDI_READY; + + err = pthread_create(&dev->thread, NULL, fluid_sndio_midi_run, (void *)dev); + if (err) { + FLUID_LOG(FLUID_PANIC, "Couldn't create the midi thread."); + goto error_recovery; + } + return (fluid_midi_driver_t *) dev; + + error_recovery: + delete_fluid_sndio_midi_driver((fluid_midi_driver_t *)dev); + return NULL; +} + +#endif /*#if SNDIO_SUPPORT */ --- files/patch-CMakeLists.txt (nonexistent) +++ files/patch-CMakeLists.txt (working copy) @@ -0,0 +1,22 @@ +--- CMakeLists.txt.orig 2012-08-16 04:01:13 UTC ++++ CMakeLists.txt +@@ -61,6 +61,7 @@ option ( enable-debug "enable debugging + option ( enable-libsndfile "compile libsndfile support (if it is available)" on ) + option ( enable-aufile "compile support for sound file output" on ) + option ( enable-pulseaudio "compile PulseAudio support (if it is available)" on ) ++option ( enable-sndio "compile Sndio support (if it is available)" on ) + option ( enable-jack "compile JACK support (if it is available)" on ) + option ( enable-midishare "compile MidiShare support (if it is available)" on ) + option ( enable-readline "compile readline lib line editing (if it is available)" on ) +@@ -313,6 +314,11 @@ else ( enable-pulseaudio ) + unset_pkg_config ( PULSE ) + endif ( enable-pulseaudio ) + ++unset ( SNDIO_SUPPORT CACHE ) ++if ( enable-sndio ) ++ set ( SNDIO_SUPPORT 1 ) ++endif ( enable-sndio ) ++ + unset ( ALSA_SUPPORT CACHE ) + if ( enable-alsa ) + pkg_check_modules ( ALSA alsa>=0.9.1 ) --- files/patch-cmake__admin_report.cmake (nonexistent) +++ files/patch-cmake__admin_report.cmake (working copy) @@ -0,0 +1,15 @@ +--- cmake_admin/report.cmake.orig 2012-08-16 04:01:13 UTC ++++ cmake_admin/report.cmake +@@ -25,6 +25,12 @@ else ( PULSE_SUPPORT ) + message ( "PulseAudio: no" ) + endif ( PULSE_SUPPORT ) + ++if ( SNDIO_SUPPORT ) ++ message ( "Sndio: yes" ) ++else ( SNDIO_SUPPORT ) ++ message ( "Sndio: no" ) ++endif ( SNDIO_SUPPORT ) ++ + if ( JACK_SUPPORT ) + message ( "JACK: yes" ) + else ( JACK_SUPPORT ) --- files/patch-src_CMakeLists.txt (nonexistent) +++ files/patch-src_CMakeLists.txt (working copy) @@ -0,0 +1,30 @@ +--- src/CMakeLists.txt.orig 2012-08-16 04:01:13 UTC ++++ src/CMakeLists.txt +@@ -47,6 +47,11 @@ if ( PULSE_SUPPORT ) + include_directories ( ${PULSE_INCLUDEDIR} ${PULSE_INCLUDE_DIRS} ) + endif ( PULSE_SUPPORT ) + ++if ( SNDIO_SUPPORT ) ++ set ( fluid_sndio_SOURCES drivers/fluid_sndio.c ) ++ set ( SNDIO_LIBRARIES sndio ) ++endif ( SNDIO_SUPPORT ) ++ + if ( ALSA_SUPPORT ) + set ( fluid_alsa_SOURCES drivers/fluid_alsa.c ) + include_directories ( ${ALSA_INCLUDEDIR} ${ALSA_INCLUDE_DIRS} ) +@@ -244,6 +249,7 @@ add_library ( libfluidsynth + ${fluid_oss_SOURCES} + ${fluid_portaudio_SOURCES} + ${fluid_pulse_SOURCES} ++ ${fluid_sndio_SOURCES} + ${fluid_windows_SOURCES} + ${libfluidsynth_SOURCES} + ${public_HEADERS} +@@ -286,6 +292,7 @@ target_link_libraries ( libfluidsynth + ${JACK_LIBRARIES} + ${ALSA_LIBRARIES} + ${PULSE_LIBRARIES} ++ ${SNDIO_LIBRARIES} + ${PORTAUDIO_LIBRARIES} + ${LIBSNDFILE_LIBRARIES} + ${DBUS_LIBRARIES} --- files/patch-src_config.cmake (nonexistent) +++ files/patch-src_config.cmake (working copy) @@ -0,0 +1,12 @@ +--- src/config.cmake.orig 2012-08-16 04:01:13 UTC ++++ src/config.cmake +@@ -178,6 +178,9 @@ + /* Define to enable PulseAudio driver */ + #cmakedefine PULSE_SUPPORT @PULSE_SUPPORT@ + ++/* Define to enable Sndio driver */ ++#cmakedefine SNDIO_SUPPORT @SNDIO_SUPPORT@ ++ + /* Define to 1 if you have the ANSI C header files. */ + #cmakedefine STDC_HEADERS @STDC_HEADERS@ + --- files/patch-src_drivers_fluid__adriver.c (nonexistent) +++ files/patch-src_drivers_fluid__adriver.c (working copy) @@ -0,0 +1,54 @@ +$OpenBSD: patch-src_drivers_fluid_adriver_c,v 1.1 2013/03/29 12:37:43 sthen Exp $ +--- src/drivers/fluid_adriver.c.orig 2012-08-16 04:01:13 UTC ++++ src/drivers/fluid_adriver.c +@@ -64,6 +64,15 @@ int delete_fluid_oss_audio_driver(fluid_ + void fluid_oss_audio_driver_settings(fluid_settings_t* settings); + #endif + ++#if SNDIO_SUPPORT ++fluid_audio_driver_t* new_fluid_sndio_audio_driver(fluid_settings_t* settings, ++ fluid_synth_t* synth); ++fluid_audio_driver_t* new_fluid_sndio_audio_driver2(fluid_settings_t* settings, ++ fluid_audio_func_t func, void* data); ++int delete_fluid_sndio_audio_driver(fluid_audio_driver_t* p); ++void fluid_sndio_audio_driver_settings(fluid_settings_t* settings); ++#endif ++ + #if COREAUDIO_SUPPORT + fluid_audio_driver_t* new_fluid_core_audio_driver(fluid_settings_t* settings, + fluid_synth_t* synth); +@@ -120,6 +129,13 @@ int delete_fluid_file_audio_driver(fluid + + /* Available audio drivers, listed in order of preference */ + fluid_audriver_definition_t fluid_audio_drivers[] = { ++#if SNDIO_SUPPORT ++ { "sndio", ++ new_fluid_sndio_audio_driver, ++ new_fluid_sndio_audio_driver2, ++ delete_fluid_sndio_audio_driver, ++ fluid_sndio_audio_driver_settings }, ++#endif + #if JACK_SUPPORT + { "jack", + new_fluid_jack_audio_driver, +@@ -223,7 +239,9 @@ void fluid_audio_driver_settings(fluid_s + FLUID_DEFAULT_AUDIO_RT_PRIO, 0, 99, 0, NULL, NULL); + + /* Set the default driver */ +-#if JACK_SUPPORT ++#if SNDIO_SUPPORT ++ fluid_settings_register_str(settings, "audio.driver", "sndio", 0, NULL, NULL); ++#elif JACK_SUPPORT + fluid_settings_register_str(settings, "audio.driver", "jack", 0, NULL, NULL); + #elif ALSA_SUPPORT + fluid_settings_register_str(settings, "audio.driver", "alsa", 0, NULL, NULL); +@@ -257,6 +275,9 @@ void fluid_audio_driver_settings(fluid_s + #if OSS_SUPPORT + fluid_settings_add_option(settings, "audio.driver", "oss"); + #endif ++#if SNDIO_SUPPORT ++ fluid_settings_add_option(settings, "audio.driver", "sndio"); ++#endif + #if COREAUDIO_SUPPORT + fluid_settings_add_option(settings, "audio.driver", "coreaudio"); + #endif --- files/patch-src_drivers_fluid__mdriver.c (nonexistent) +++ files/patch-src_drivers_fluid__mdriver.c (working copy) @@ -0,0 +1,53 @@ +$OpenBSD: patch-src_drivers_fluid_mdriver_c,v 1.1 2013/03/29 12:37:43 sthen Exp $ +--- src/drivers/fluid_mdriver.c.orig 2012-08-16 04:01:13 UTC ++++ src/drivers/fluid_mdriver.c +@@ -46,6 +46,15 @@ fluid_midi_driver_t *new_fluid_jack_midi + int delete_fluid_jack_midi_driver(fluid_midi_driver_t *p); + #endif + ++/* SNDIO */ ++#if SNDIO_SUPPORT ++fluid_midi_driver_t* new_fluid_sndio_midi_driver(fluid_settings_t* settings, ++ handle_midi_event_func_t handler, ++ void* event_handler_data); ++int delete_fluid_sndio_midi_driver(fluid_midi_driver_t* p); ++void fluid_sndio_midi_driver_settings(fluid_settings_t* settings); ++#endif ++ + /* OSS */ + #if OSS_SUPPORT + fluid_midi_driver_t* new_fluid_oss_midi_driver(fluid_settings_t* settings, +@@ -96,6 +105,12 @@ struct fluid_mdriver_definition_t { + + + struct fluid_mdriver_definition_t fluid_midi_drivers[] = { ++#if SNDIO_SUPPORT ++ { "sndio", ++ new_fluid_sndio_midi_driver, ++ delete_fluid_sndio_midi_driver, ++ fluid_sndio_midi_driver_settings }, ++#endif + #if JACK_SUPPORT + { "jack", + new_fluid_jack_midi_driver, +@@ -149,7 +164,9 @@ void fluid_midi_driver_settings(fluid_se + FLUID_DEFAULT_MIDI_RT_PRIO, 0, 99, 0, NULL, NULL); + + /* Set the default driver */ +-#if ALSA_SUPPORT ++#if SNDIO_SUPPORT ++ fluid_settings_register_str(settings, "midi.driver", "sndio", 0, NULL, NULL); ++#elif ALSA_SUPPORT + fluid_settings_register_str(settings, "midi.driver", "alsa_seq", 0, NULL, NULL); + #elif JACK_SUPPORT + fluid_settings_register_str(settings, "midi.driver", "jack", 0, NULL, NULL); +@@ -170,6 +187,9 @@ void fluid_midi_driver_settings(fluid_se + fluid_settings_add_option(settings, "midi.driver", "alsa_seq"); + fluid_settings_add_option(settings, "midi.driver", "alsa_raw"); + #endif ++#if SNDIO_SUPPORT ++ fluid_settings_add_option(settings, "midi.driver", "sndio"); ++#endif + #if JACK_SUPPORT + fluid_settings_add_option(settings, "midi.driver", "jack"); + #endif