Index: include/libroar/libroar.h
===================================================================
--- include/libroar/libroar.h	(revision 5031)
+++ include/libroar/libroar.h	(revision 5317)
@@ -123,4 +123,5 @@
 #include "env.h"
 #include "roardl.h"
+#include "plugincontainer.h"
 #include "debug.h"
 #include "memmgr.h"
Index: include/libroar/plugincontainer.h
===================================================================
--- include/libroar/plugincontainer.h	(revision 5317)
+++ include/libroar/plugincontainer.h	(revision 5317)
@@ -0,0 +1,64 @@
+//plugincontainer.h:
+
+/*
+ *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2011
+ *
+ *  This file is part of libroar 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.
+ *
+ *  libroar 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.
+ *
+ *  NOTE for everyone want's to change something and send patches:
+ *  read README and HACKING! There a addition information on
+ *  the license of this document you need to read before you send
+ *  any patches.
+ *
+ *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
+ *  or libpulse*:
+ *  The libs libroaresd, libroararts and libroarpulse link this lib
+ *  and are therefore GPL. Because of this it may be illigal to use
+ *  them with any software that uses libesd, libartsc or libpulse*.
+ */
+
+#ifndef _LIBROARPLUGINCONTAINER_H_
+#define _LIBROARPLUGINCONTAINER_H_
+
+#include "libroar.h"
+
+struct roar_plugincontainer;
+
+struct roar_plugincontainer * roar_plugincontainer_new(struct roar_dl_librarypara * default_para);
+struct roar_plugincontainer * roar_plugincontainer_new_simple(const char * appname, const char * abiversion);
+
+int roar_plugincontainer_ref(struct roar_plugincontainer * cont);
+int roar_plugincontainer_unref(struct roar_plugincontainer * cont);
+
+/*
+ * stuff we still need:
+ * object creation, load plugin, get plugin handle, setting search path.
+ */
+
+// plugin loading and unloading:
+int roar_plugincontainer_load(struct roar_plugincontainer * cont, const char * name, struct roar_dl_librarypara * para);
+int roar_plugincontainer_unload(struct roar_plugincontainer * cont, const char * name);
+int roar_plugincontainer_unload_lhandle(struct roar_plugincontainer * cont, struct roar_dl_lhandle * lhandle);
+
+// appsched:
+int                      roar_plugincontainer_appsched_trigger(struct roar_plugincontainer * cont, enum roar_dl_appsched_trigger trigger);
+
+#endif
+
+//ll
Index: include/libroar/roardl.h
===================================================================
--- include/libroar/roardl.h	(revision 5313)
+++ include/libroar/roardl.h	(revision 5317)
@@ -39,5 +39,7 @@
 #include "libroar.h"
 
-#define ROAR_DL_FLAG_DEFAUTS           -1
+#define ROAR_DL_FLAG_DEFAULTS          -1
+#define ROAR_DL_FLAG_NONE               0x0000
+#define ROAR_DL_FLAG_STATIC             0x0001 /* plugins are linked statically -lfoo */
 
 #define ROAR_DL_HANDLE_DEFAULT          ((struct roar_dl_lhandle*)(void*)0)
@@ -57,4 +59,5 @@
 #define ROAR_DL_FN_PROTO               11
 #define ROAR_DL_FN_NOTIFY              12
+#define ROAR_DL_FN_INIT                13 /* global plugin instance init. should be avoided */
 //#define ROAR_DL_FN_               9
 #define ROAR_DL_FN_MAX                 24
@@ -99,4 +102,5 @@
 #define ROAR_DL_PLUGIN_REG(fn, funcptr) (lib.func[(fn)] = (funcptr))
 #define ROAR_DL_PLUGIN_REG_UNLOAD(func) (lib.unload = (func))
+#define ROAR_DL_PLUGIN_REG_APPSCHED(sched) (lib.appsched = (sched))
 #define ROAR_DL_PLUGIN_REG_GLOBAL_DATA(ptr,init) lib.global_data_len = sizeof((init)); \
                                                  lib.global_data_init = &(init);       \
@@ -132,4 +136,5 @@
                             // which introduced the current ABI.
                             // Examples: libroar2, 0.5.1
+ struct roar_notify_core * notifycore;
 };
 
@@ -138,5 +143,9 @@
  size_t   len;
  const char * name;        //Format: shortname
- const char * libversion;  //Format: Product/Version <VendorID/VendorName> (comments)
+ const char * libname;     //This is the same as appname in struct roar_dl_librarypara.
+                           //Format: Product <VendorID/VendorName> (comments)
+ const char * libversion;  //This is the pure version number of the library.
+ const char * abiversion;  //This is the same as abiversion in struct roar_dl_librarypara.
+                           //Format: Version
  const char * description; //Free form.
  const char * contact;     //Format: first ["']nick["'] last (comment) <email>/OpenPGPkey/Phone/Room
@@ -144,4 +153,12 @@
  const char * license;     //Format: LicenseName-Version (options)
                            //Examples: GPL-3.0, LGPL-2.1, LGPL-3.0 (or later).
+};
+
+struct roar_dl_librarydep {
+ int      version;
+ size_t   len;
+ const char * name;
+ const char * libname;
+ const char * abiversion;
 };
 
@@ -155,10 +172,22 @@
  void *  global_data_init;
  void ** global_data_pointer;
+ struct roar_dl_librarydep * libdep;
+ size_t libdep_len;
+ struct roar_dl_appsched * appsched;
 };
 
 struct roar_dl_appsched {
- int (*init)  (struct roar_dl_librarypara * para, struct roar_dl_libraryinst * lib);
- int (*free)  (struct roar_dl_librarypara * para, struct roar_dl_libraryinst * lib);
- int (*update)(struct roar_dl_librarypara * para, struct roar_dl_libraryinst * lib);
+ int (*init)  (struct roar_dl_librarypara * para);
+ int (*free)  (struct roar_dl_librarypara * para);
+ int (*update)(struct roar_dl_librarypara * para);
+};
+
+enum roar_dl_appsched_trigger {
+ ROAR_DL_APPSCHED_INIT = 1,
+#define ROAR_DL_APPSCHED_INIT ROAR_DL_APPSCHED_INIT
+ ROAR_DL_APPSCHED_FREE,
+#define ROAR_DL_APPSCHED_FREE ROAR_DL_APPSCHED_FREE
+ ROAR_DL_APPSCHED_UPDATE
+#define ROAR_DL_APPSCHED_UPDATE ROAR_DL_APPSCHED_UPDATE
 };
 
@@ -194,4 +223,7 @@
 int                      roar_dl_context_store(struct roar_dl_lhandle * lhandle);
 
+// appsched:
+int                      roar_dl_appsched_trigger(struct roar_dl_lhandle * lhandle, enum roar_dl_appsched_trigger trigger);
+
 #endif
 
Index: libroar/Makefile
===================================================================
--- libroar/Makefile	(revision 5270)
+++ libroar/Makefile	(revision 5317)
@@ -11,5 +11,5 @@
 PASSWORD=passwordapi.o pinentry.o sshaskpass.o
 CRYPTO=crypto.o random.o $(HASHES) crc.o
-OBJS=libroar.o config.o debug.o error.o basic.o stream.o client.o simple.o auth.o socket.o ctl.o buffer.o meta.o file.o acl.o cdrom.o $(PASSWORD) $(VIO) stack.o slp.o nnode.o roardl.o roarx11.o beep.o proto.o env.o keyval.o vs.o ltm.o notify.o notify_proxy.o asyncctl.o enumdev.o serverinfo.o $(CRYPTO) authfile.o caps.o roarfloat.o base64.o trap.o memmgr.o time.o
+OBJS=libroar.o config.o debug.o error.o basic.o stream.o client.o simple.o auth.o socket.o ctl.o buffer.o meta.o file.o acl.o cdrom.o $(PASSWORD) $(VIO) stack.o slp.o nnode.o roardl.o plugincontainer.o roarx11.o beep.o proto.o env.o keyval.o vs.o ltm.o notify.o notify_proxy.o asyncctl.o enumdev.o serverinfo.o $(CRYPTO) authfile.o caps.o roarfloat.o base64.o trap.o memmgr.o time.o
 
 #DEFINES        = -DDEBUG
Index: libroar/plugincontainer.c
===================================================================
--- libroar/plugincontainer.c	(revision 5317)
+++ libroar/plugincontainer.c	(revision 5317)
@@ -0,0 +1,184 @@
+//plugincontainer.c:
+
+/*
+ *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011
+ *
+ *  This file is part of libroar 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.
+ *
+ *  libroar 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.
+ *
+ *  NOTE for everyone want's to change something and send patches:
+ *  read README and HACKING! There a addition information on
+ *  the license of this document you need to read before you send
+ *  any patches.
+ *
+ *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
+ *  or libpulse*:
+ *  The libs libroaresd, libroararts and libroarpulse link this lib
+ *  and are therefore GPL. Because of this it may be illigal to use
+ *  them with any software that uses libesd, libartsc or libpulse*.
+ */
+
+#include "libroar.h"
+
+#define MAX_PLUGINS 64
+
+struct roar_plugincontainer {
+ size_t refc;
+ struct roar_dl_librarypara * default_para;
+ struct roar_dl_lhandle * handle[MAX_PLUGINS];
+ // TODO: add a depref counter so we do not unload libs we depend on.
+};
+
+static struct roar_plugincontainer * _new_init(void) {
+ struct roar_plugincontainer * ret = roar_mm_malloc(sizeof(struct roar_plugincontainer));
+ if ( ret == NULL )
+  return NULL;
+
+ memset(ret, 0, sizeof(struct roar_plugincontainer));
+
+ ret->refc = 1;
+
+ return ret;
+}
+
+struct roar_plugincontainer * roar_plugincontainer_new(struct roar_dl_librarypara * default_para) {
+ struct roar_plugincontainer * ret = _new_init();
+ int err;
+
+ if ( ret == NULL )
+  return NULL;
+
+ if ( default_para != NULL ) {
+  if ( roar_dl_para_ref(default_para) == -1 ) {
+   err = roar_error;
+   roar_plugincontainer_unref(ret);
+   roar_err_set(err);
+   return NULL;
+  }
+  ret->default_para = default_para;
+ }
+
+ return ret;
+}
+
+struct roar_plugincontainer * roar_plugincontainer_new_simple(const char * appname, const char * abiversion) {
+ struct roar_plugincontainer * ret;
+ struct roar_dl_librarypara * para = roar_dl_para_new(NULL, NULL, appname, abiversion);
+ int err;
+
+ ret = roar_plugincontainer_new(para);
+ err = roar_error;
+
+ roar_dl_para_unref(para);
+
+ roar_err_set(err);
+ return ret;
+}
+
+int roar_plugincontainer_ref(struct roar_plugincontainer * cont) {
+ if ( cont == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ cont->refc++;
+
+ return 0;
+}
+
+int roar_plugincontainer_unref(struct roar_plugincontainer * cont) {
+ size_t i;
+
+ if ( cont == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ cont->refc--;
+
+ if ( cont->refc )
+  return 0;
+
+ for (i = 0; i < MAX_PLUGINS; i++) {
+  if ( cont->handle[i] == NULL )
+   continue;
+
+  roar_dl_close(cont->handle[i]);
+ }
+
+ if ( cont->default_para != NULL )
+  roar_dl_para_unref(cont->default_para);
+
+ roar_mm_free(cont);
+
+ return 0;
+}
+
+// plugin loading and unloading:
+int roar_plugincontainer_load(struct roar_plugincontainer * cont, const char * name, struct roar_dl_librarypara * para);
+int roar_plugincontainer_unload(struct roar_plugincontainer * cont, const char * name) {
+ // get b name, then call roar_plugincontainer_unload_lhandle().
+ roar_err_set(ROAR_ERROR_NOSYS);
+ return -1;
+}
+
+int roar_plugincontainer_unload_lhandle(struct roar_plugincontainer * cont, struct roar_dl_lhandle * lhandle) {
+ size_t i;
+
+ if ( cont == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ if ( lhandle == NULL ) {
+  roar_err_set(ROAR_ERROR_INVAL);
+  return -1;
+ }
+
+ for (i = 0; i < MAX_PLUGINS; i++) {
+  if ( cont->handle[i] == lhandle ) {
+   roar_dl_close(cont->handle[i]);
+   cont->handle[i] = NULL;
+   return 0;
+  }
+ }
+
+ roar_err_set(ROAR_ERROR_NOENT);
+ return -1;
+}
+
+// appsched:
+int roar_plugincontainer_appsched_trigger(struct roar_plugincontainer * cont, enum roar_dl_appsched_trigger trigger) {
+ size_t i;
+
+ if ( cont == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ for (i = 0; i < MAX_PLUGINS; i++) {
+  if ( cont->handle[i] == NULL )
+   continue;
+
+  roar_dl_appsched_trigger(cont->handle[i], trigger);
+ }
+
+ return 0;
+}
+
+//ll
Index: libroar/roardl.c
===================================================================
--- libroar/roardl.c	(revision 5313)
+++ libroar/roardl.c	(revision 5317)
@@ -41,4 +41,7 @@
 
 struct roar_dl_lhandle {
+ size_t refc; // currently unused.
+ int flags;
+ char * libname; // only used for ROAR_DL_FLAG_STATIC.
  struct roar_dl_librarypara * para;
  struct roar_dl_libraryinst * lib;
@@ -47,4 +50,5 @@
   void *  global_data;
   void *  global_data_state;
+  struct roar_notify_core * notifycore;
  } context;
 #if defined(ROAR_HAVE_LIBDL)
@@ -118,11 +122,16 @@
  para->refc--;
 
- if ( para->refc == 0 ) {
-  if ( para->args_store != NULL ) {
-   roar_mm_free(para->args_store);
-   roar_mm_free(para->argv);
-  }
-  roar_mm_free(para);
- }
+ if ( para->refc )
+  return 0;
+
+ if ( para->notifycore != NULL )
+  roar_notify_core_unref(para->notifycore);
+
+ if ( para->args_store != NULL ) {
+  roar_mm_free(para->args_store);
+  roar_mm_free(para->argv);
+ }
+
+ roar_mm_free(para);
 
  return 0;
@@ -165,10 +174,17 @@
 #if defined(ROAR_HAVE_LIBDL)
 static void * _roardl2ldl (struct roar_dl_lhandle * lhandle) {
- if ( lhandle == ROAR_DL_HANDLE_DEFAULT )
+ ROAR_DBG("_roardl2ldl(lhandle=%p) = ?", lhandle);
+
+ if ( lhandle == ROAR_DL_HANDLE_DEFAULT ) {
+  ROAR_DBG("_roardl2ldl(lhandle=%p) = %p", lhandle, (void*)RTLD_DEFAULT);
   return RTLD_DEFAULT;
-
- if ( lhandle == ROAR_DL_HANDLE_NEXT )
+ }
+
+ if ( lhandle == ROAR_DL_HANDLE_NEXT ) {
+  ROAR_DBG("_roardl2ldl(lhandle=%p) = %p", lhandle, (void*)RTLD_NEXT);
   return RTLD_NEXT;
-
+ }
+
+ ROAR_DBG("_roardl2ldl(lhandle=%p) = %p", lhandle, (void*)(lhandle->handle));
  return lhandle->handle;
 }
@@ -178,12 +194,15 @@
                                       int ra_init, struct roar_dl_librarypara * para) {
  struct roar_dl_lhandle * ret = NULL;
+#if defined(ROAR_HAVE_LIBDL)
+#ifdef RTLD_DEEPBIND
+ int libdl_flags = RTLD_NOW|RTLD_DEEPBIND;
+#else
+ int libdl_flags = RTLD_NOW;
+#endif
+#endif
  int err;
 
- // early errors just return.
-
- if ( flags != ROAR_DL_FLAG_DEFAUTS ) {
-  roar_err_set(ROAR_ERROR_NOTSUP);
-  return NULL;
- }
+ if ( flags == ROAR_DL_FLAG_DEFAULTS )
+  flags = ROAR_DL_FLAG_NONE;
 
  if ( (ret = roar_mm_malloc(sizeof(struct roar_dl_lhandle))) == NULL )
@@ -194,22 +213,27 @@
  roar_err_initstore(&(ret->context.error_state));
 
-#if defined(ROAR_HAVE_LIBDL)
- flags  = RTLD_NOW;
-
-#ifdef RTLD_DEEPBIND
- flags |= RTLD_DEEPBIND;
-#endif
-
- ret->handle = dlopen(filename, flags);
-
- if ( ret->handle == NULL ) {
+ ret->flags = flags;
+
+ if ( flags & ROAR_DL_FLAG_STATIC ) {
+  if ( filename == NULL ) {
+   ret->libname = NULL;
+  } else {
+   ret->libname = roar_mm_strdup(filename);
+  }
+ } else {
+#if defined(ROAR_HAVE_LIBDL)
+  ret->handle = dlopen(filename, libdl_flags);
+
+  if ( ret->handle == NULL ) {
+   ROAR_DBG("roar_dl_open(filename='%s', flags=%i, ra_init=%i, para=%p): Can not load library: %s", filename, flags, ra_init, para, roar_dl_errstr(ret));
+   roar_mm_free(ret);
+   return NULL;
+  }
+#else
   roar_mm_free(ret);
-  return NULL;
- }
-#else
- roar_mm_free(ret);
- roar_err_set(ROAR_ERROR_NOSYS);
- return NULL;
-#endif
+  roar_err_set(ROAR_ERROR_NOSYS);
+  return NULL;
+#endif
+ }
 
  ret->para = para;
@@ -220,5 +244,6 @@
    ROAR_WARN("roar_dl_open(filename='%s', flags=%i, ra_init=%i, para=%p): Can not init RA lib: %s", filename, flags, ra_init, para, roar_error2str(err));
 #if defined(ROAR_HAVE_LIBDL)
-   dlclose(ret->handle);
+   if ( ret->handle != NULL )
+    dlclose(ret->handle);
 #endif
    roar_mm_free(ret);
@@ -242,9 +267,16 @@
  }
 
- if ( lhandle->lib != NULL && lhandle->lib->unload != NULL )
+ if ( lhandle->lib != NULL && lhandle->lib->unload != NULL ) {
+  roar_dl_context_restore(lhandle);
   lhandle->lib->unload(lhandle->para, lhandle->lib);
-
-#if defined(ROAR_HAVE_LIBDL)
- ret = dlclose(_roardl2ldl(lhandle));
+  roar_dl_context_store(lhandle);
+ }
+
+#if defined(ROAR_HAVE_LIBDL)
+ if ( lhandle->handle == NULL ) {
+  ret = 0;
+ } else {
+  ret = dlclose(_roardl2ldl(lhandle));
+ }
 #else
  ret = -1;
@@ -257,4 +289,7 @@
   roar_dl_para_unref(lhandle->para);
 
+ if ( lhandle->libname != NULL )
+  roar_mm_free(lhandle->libname);
+
  roar_mm_free(lhandle);
 
@@ -268,8 +303,11 @@
  (void)type;
 
+ ROAR_DBG("roar_dl_getsym(lhandle=%p, sym='%s', type=%i): errno=%s, dlerror()='%s'", lhandle, sym, type, ret, strerror(errno), dlerror());
  ROAR_DBG("roar_dl_getsym(lhandle=%p, sym='%s', type=%i) = %p", lhandle, sym, type, ret);
 
  return ret;
 #else
+ ROAR_DBG("roar_dl_getsym(lhandle=%p, sym='%s', type=%i) = NULL // errno=NOSYS", lhandle, sym, type, ret);
+ roar_err_set(ROAR_ERROR_NOSYS);
  return NULL;
 #endif
@@ -283,4 +321,5 @@
  struct roar_dl_libraryinst * (*func)(struct roar_dl_librarypara * para);
  struct roar_dl_libraryinst * lib;
+ struct roar_dl_lhandle     * getsymhandle = lhandle;
  void * global_data_state = NULL;
  int i;
@@ -290,6 +329,12 @@
    return -1;
  } else {
+  if ( prefix == NULL )
+   prefix = lhandle->libname;
+
   if ( para == NULL )
    para = lhandle->para;
+
+  if ( lhandle->flags & ROAR_DL_FLAG_STATIC )
+   getsymhandle = ROAR_DL_HANDLE_DEFAULT;
  }
 
@@ -303,6 +348,8 @@
  ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s'): name='%s'", lhandle, prefix, name);
 
- if ( (func = roar_dl_getsym(lhandle, name, -1)) == NULL )
-  return -1;
+ if ( (func = roar_dl_getsym(getsymhandle, name, -1)) == NULL ) {
+  ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s') = -1", lhandle, prefix);
+  return -1;
+ }
 
  ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s'): func=%p", lhandle, prefix, func);
@@ -416,5 +463,8 @@
  struct roar_error_state error_state;
 
+ ROAR_DBG("roar_dl_context_restore(lhandle=%p) = ?", lhandle);
+
  if ( (void*)lhandle < (void*)128 ) {
+  ROAR_DBG("roar_dl_context_restore(lhandle=%p) = -1 // errno=NOTSUP", lhandle);
   roar_err_set(ROAR_ERROR_NOTSUP);
   return -1;
@@ -426,8 +476,14 @@
 
  if ( lhandle->lib->global_data_pointer != NULL ) {
+  ROAR_DBG("roar_dl_context_restore(lhandle=%p): gptr(%p): %p -> %p", lhandle,
+           lhandle->lib->global_data_pointer, *(lhandle->lib->global_data_pointer), lhandle->context.global_data);
   lhandle->context.global_data_state = *(lhandle->lib->global_data_pointer);
   *(lhandle->lib->global_data_pointer) = lhandle->context.global_data;
  }
 
+ if ( lhandle->para->notifycore != NULL )
+  lhandle->context.notifycore = roar_notify_core_swap_global(lhandle->para->notifycore);
+
+ ROAR_DBG("roar_dl_context_restore(lhandle=%p) = 0", lhandle);
  return 0;
 }
@@ -436,10 +492,21 @@
  struct roar_error_state error_state;
 
+ ROAR_DBG("roar_dl_context_store(lhandle=%p) = ?", lhandle);
+
  if ( (void*)lhandle < (void*)128 ) {
+  ROAR_DBG("roar_dl_context_store(lhandle=%p) = -1 // errno=NOTSUP", lhandle);
   roar_err_set(ROAR_ERROR_NOTSUP);
   return -1;
  }
 
+ if ( lhandle->para->notifycore != NULL ) {
+  roar_notify_core_unref(roar_notify_core_swap_global(lhandle->context.notifycore));
+  roar_notify_core_unref(lhandle->context.notifycore);
+  lhandle->context.notifycore = NULL;
+ }
+
  if ( lhandle->lib->global_data_pointer != NULL ) {
+  ROAR_DBG("roar_dl_context_store(lhandle=%p): gptr(%p): %p -> %p", lhandle,
+           lhandle->lib->global_data_pointer, *(lhandle->lib->global_data_pointer), lhandle->context.global_data_state);
   *(lhandle->lib->global_data_pointer) = lhandle->context.global_data_state;
  }
@@ -449,6 +516,41 @@
  lhandle->context.error_state = error_state;
 
+ ROAR_DBG("roar_dl_context_store(lhandle=%p) = 0", lhandle);
  return 0;
 }
 
+int                      roar_dl_appsched_trigger(struct roar_dl_lhandle * lhandle, enum roar_dl_appsched_trigger trigger) {
+ int ret;
+
+ if ( (void*)lhandle < (void*)128 ) {
+  roar_err_set(ROAR_ERROR_NOTSUP);
+  return -1;
+ }
+
+ if ( lhandle->lib->appsched == NULL ) {
+  roar_err_set(ROAR_ERROR_NOENT);
+  return -1;
+ }
+
+ switch (trigger) {
+#define _trig(lname,uname) \
+  case ROAR_DL_APPSCHED_ ## uname :             \
+    if ( lhandle->lib->appsched->lname == NULL ) {   \
+     roar_err_set(ROAR_ERROR_NOENT);            \
+     return -1;                                 \
+    }                                           \
+    roar_dl_context_restore(lhandle);           \
+    ret = lhandle->lib->appsched->lname(lhandle->para); \
+    roar_dl_context_store(lhandle);             \
+    return ret;                                 \
+   break;
+  _trig(init, INIT);
+  _trig(free, FREE);
+  _trig(update, UPDATE);
+ }
+
+ roar_err_set(ROAR_ERROR_BADRQC);
+ return -1;
+}
+
 //ll
