Index: libroarlight/Makefile
===================================================================
--- libroarlight/Makefile	(revision 5849)
+++ libroarlight/Makefile	(revision 5982)
@@ -7,5 +7,5 @@
 
 TARGETS=$(SLIB) $(ALIB) $(IMPLIB)
-OBJS=libroarlight.o colors.o roardmx.o pwm.o
+OBJS=libroarlight.o colors.o roardmx.o pwm.o slfi.o
 
 #DEFINES        = -DDEBUG
Index: libroarlight/slfi.c
===================================================================
--- libroarlight/slfi.c	(revision 5982)
+++ libroarlight/slfi.c	(revision 5982)
@@ -0,0 +1,242 @@
+//slfi.h:
+
+/*
+ *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009-2014
+ *
+ *  This file is part of libroardsp a part of RoarAudio,
+ *  a cross-platform sound system for both, home and professional use.
+ *  See README for details.
+ *
+ *  This file is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3
+ *  as published by the Free Software Foundation.
+ *
+ *  libroardsp is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this software; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "libroarlight.h"
+
+static const struct roar_slfi_filter * __find_impl_registered(const char * name, struct roar_dl_lhandle ** lhandle) {
+ const void * impl;
+ size_t impl_size;
+ int options;
+ ssize_t i;
+
+ for (i = 0; ; i++) {
+  if ( roar_dl_query_fn(lhandle, ROAR_DL_FN_FILTER, ROAR_DL_FILTER_SUBTYPE_SLFI, &impl, &impl_size, ROAR_DL_FILTER_VERSION_SLFI, &options, i) == -1 ) {
+   return NULL;
+  }
+
+  if ( impl_size != ROAR_DL_FILTER_SIZE_SLFI ) {
+   ROAR_WARN("__find_impl_registered(*): Object %p has wrong size of %u. Strange.", impl, (unsigned int)impl_size);
+   continue;
+  }
+
+  if ( ((const struct roar_slfi_filter *)impl)->name == NULL ) {
+   ROAR_WARN("__find_impl_registered(*): Object %p has no name. Strange.", impl);
+   continue;
+  }
+
+  if ( !!strcmp(((const struct roar_slfi_filter *)impl)->name, name) )
+   continue;
+
+  return impl;
+ }
+}
+
+static struct roar_dl_lhandle * __find_impl_autoload(const char * name) {
+ struct roar_dl_lhandle * lhandle = NULL;
+ struct roar_dl_librarypara * para = NULL;
+ char buf[80];
+ int err;
+
+ para = roar_dl_para_new(NULL, NULL, LIBROAR_DL_APPNAME, LIBROAR_DL_ABIVERSION);
+ if ( para == NULL )
+  return NULL;
+
+ snprintf(buf, sizeof(buf), "filter-slfi-%s", name);
+ lhandle = roar_dl_open(buf, ROAR_DL_FLAG_PLUGIN, 1, para);
+
+ err = roar_error;
+ roar_dl_para_unref(para);
+ roar_error = err;
+
+ return lhandle;
+}
+
+static const struct roar_slfi_filter * __find_impl(const char * name, int autoload, struct roar_dl_lhandle ** lhandle) {
+ const struct roar_slfi_filter * impl;
+ struct roar_dl_lhandle * loaded_lhandle = NULL;
+ int err;
+
+ impl = __find_impl_registered(name, lhandle);
+ if ( impl != NULL ) {
+  roar_dl_ref(*lhandle);
+  return impl;
+ }
+
+ if ( autoload ) {
+  loaded_lhandle = __find_impl_autoload(name);
+  if ( loaded_lhandle == NULL )
+   return NULL;
+
+  impl = __find_impl_registered(name, lhandle);
+  if ( impl == NULL ) {
+   err = roar_error;
+   roar_dl_unref(loaded_lhandle);
+   roar_err_set(err);
+   return NULL;
+  } else if ( *lhandle != loaded_lhandle ) {
+   ROAR_WARN("__find_impl(name='%s', autoload=%i, lhandle=%p): Loaded handle and found handle do not match. Strange.", name, autoload, lhandle);
+   roar_dl_unref(loaded_lhandle);
+   roar_err_set(ROAR_ERROR_BADFH);
+   return NULL;
+  } else {
+   *lhandle = loaded_lhandle;
+   return impl;
+  }
+ }
+
+ roar_err_set(ROAR_ERROR_NOENT);
+ return NULL;
+}
+
+struct roar_slfi_inst * roar_slfi_new(const char * name, int autoload, const struct roar_keyval * para, ssize_t paralen) {
+ const struct roar_slfi_filter * impl;
+ struct roar_dl_lhandle  * lhandle = NULL;
+ struct roar_slfi_inst   * inst;
+ int err;
+
+ impl = __find_impl(name, autoload, &lhandle);
+ if ( impl == NULL )
+  return NULL;
+
+ inst = roar_mm_malloc(sizeof(*inst));
+ if ( inst == NULL )
+  return NULL;
+
+ memset(inst, 0, sizeof(*inst));
+
+ inst->refc = 1;
+ inst->impl = impl;
+ inst->flags = impl->flags;
+ inst->userdata = NULL;
+ inst->lhandle = lhandle;
+
+ if ( inst->impl->init != NULL ) {
+  if ( lhandle != NULL )
+   roar_dl_context_restore(lhandle);
+  if ( inst->impl->init(inst, para, paralen) != 0 ) {
+   err = roar_error;
+   if ( lhandle != NULL )
+    roar_dl_context_store(lhandle);
+   if ( inst->userdata != NULL )
+    roar_mm_free(inst->userdata);
+   roar_mm_free(inst);
+   if ( lhandle != NULL )
+    roar_dl_unref(lhandle);
+   roar_err_set(err);
+   return NULL;
+  }
+  if ( lhandle != NULL )
+   roar_dl_context_store(lhandle);
+ }
+
+ return inst;
+}
+
+int roar_slfi_ref(struct roar_slfi_inst * inst) {
+  if ( inst == NULL || inst->impl == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ inst->refc++;
+
+ return 0;
+}
+
+int roar_slfi_unref(struct roar_slfi_inst * inst) {
+  if ( inst == NULL || inst->impl == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ inst->refc--;
+
+ if ( inst->refc )
+  return 0;
+
+ if ( inst->impl->uninit != NULL ) {
+  if ( inst->lhandle != NULL )
+   roar_dl_context_restore(inst->lhandle);
+  inst->impl->uninit(inst);
+  if ( inst->lhandle != NULL )
+   roar_dl_context_store(inst->lhandle);
+ }
+
+ if ( inst->userdata != NULL )
+  roar_mm_free(inst->userdata);
+
+ if ( inst->lhandle != NULL )
+  roar_dl_unref(inst->lhandle);
+
+ roar_mm_free(inst);
+
+ return 0;
+}
+
+int roar_slfi_update(struct roar_slfi_inst * inst, uint8_t * universe, ssize_t size_of_universe, int32_t usecspassed, const uint8_t * event, size_t eventlen) {
+ int ret;
+
+ if ( inst == NULL || inst->impl == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ if ( inst->impl->update == NULL ) {
+  roar_err_set(ROAR_ERROR_NOSYS);
+  return -1;
+ }
+
+ if ( inst->lhandle != NULL )
+  roar_dl_context_restore(inst->lhandle);
+ ret = inst->impl->update(inst, universe, size_of_universe, usecspassed, event, eventlen);
+ if ( inst->lhandle != NULL )
+  roar_dl_context_store(inst->lhandle);
+
+ return ret;
+}
+
+int roar_slfi_ctl(struct roar_slfi_inst * inst, enum roar_slfi_command command, void * argp) {
+ int ret;
+
+ if ( inst == NULL || inst->impl == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ if ( inst->impl->ctl == NULL ) {
+  roar_err_set(ROAR_ERROR_NOSYS);
+  return -1;
+ }
+
+ if ( inst->lhandle != NULL )
+  roar_dl_context_restore(inst->lhandle);
+ ret = inst->impl->ctl(inst, command, argp);
+ if ( inst->lhandle != NULL )
+  roar_dl_context_store(inst->lhandle);
+
+ return ret;
+}
+
+//ll
