]> Nishi Git Mirror - gwion.git/commitdiff
:art: Introduce dynamicly loadable driver
authorfennecdjay <astor.jeremie@wanadoo.fr>
Tue, 5 Mar 2019 15:28:27 +0000 (16:28 +0100)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Tue, 5 Mar 2019 15:28:27 +0000 (16:28 +0100)
include/driver.h
include/gwion.h
include/plug.h
src/arg.c
src/gwion.c
src/plug.c
tests/import/basic_module.c
tests/import/coverage.gw
tests/import/driver.c [new file with mode: 0644]
tests/sh/plugin.sh

index 1cd9dbad562a7bcaccc5157d79fb45d0c3ebd10e..37759c99ae6744e14e7f0431b1ef71764ccca311 100644 (file)
@@ -10,6 +10,7 @@ typedef struct containing_driver_info {
   m_str card;
   m_uint backend;
   m_uint format;
+  m_str arg;
   void (*func)(Driver_);
   void (*run)(const VM*);
   void* data;
index 06c6eaff06ec7c43dab7bbf78fb0d62c306e8a23..f2ff3affa00f7fc87acbddf2e364f369b04b4d4c 100644 (file)
@@ -4,7 +4,7 @@ typedef struct Gwion_* Gwion;
 #include "plug.h"
 #include "driver.h"
 struct Gwion_ {
-  PlugInfo plug;
+  PlugInfo* plug;
   Driver* driver;
 // scanner
 // sym
index 23d2d195ac353cb010235bb3d27c2306f3fa521a..0e18dfc45e74f492a0aba847564b8b1789fcde2b 100644 (file)
@@ -8,22 +8,23 @@ enum plug_t {
   GWPLUG_LAST
 };
 
-typedef struct Vector_ PlugInfo[GWPLUG_LAST];
-void plug_discover(PlugInfo, Vector);
+//typedef struct Vector_ PlugInfo[GWPLUG_LAST];
+typedef struct {
+  struct Vector_ vec[GWPLUG_LAST];
+  struct Map_ drv;
+} PlugInfo;
+void plug_discover(PlugInfo*, Vector);
 void plug_end(const Gwion gwion);
 
-#define GWMODNAME_NAME "gwmodname"
-#define GWMODINI_NAME  "gwmodini"
-#define GWMODEND_NAME  "gwmodend"
-#define GWMODNAME_FUNC gwmodname
-#define GWMODINI_FUNC  gwmodini
-#define GWMODEND_FUNC  gwmodend
-#define GWMODNAME(a) m_str GWMODNAME_FUNC() { return a; }
-#define GWMODINI(a)  ANN void* GWMODINI_FUNC(const Gwion gwion, const Vector args)
-#define GWMODEND(a)  ANN void  GWMODEND_FUNC(const Gwion gwion, void* self)
+#define GWIMPORT_NAME    import
+#define GWMODSTR_NAME  gwmodstr
+#define GWMODINI_NAME  gwmodini
+#define GWMODEND_NAME  gwmodend
+#define GWDRIVER_NAME  gwmodend
+#define GWMODSTR(a) m_str GWMODSTR_NAME() { return #a; }
+#define GWMODINI(a)  ANN void* GWMODINI_NAME(const Gwion gwion, const Vector args)
+#define GWMODEND(a)  ANN void  GWMODEND_NAME(const Gwion gwion, void* self)
+#define GWDRIVER(a)  ANN void  GWDRIVER_NAME(struct driver_wrapper* d)
 
-//typedef void* (*f_gwmodname)(void);
-typedef void* (*f_gwmodini)(const Gwion, const Vector);
-typedef void* (*f_gwmodend)(const Gwion, void*);
 void plug_ini(const Gwion gwion, const Vector);
 #endif
index 6d51f2f0023573da7f2a844fbd92e06bea29630d..749733bd70126301ce223800bf7eb90878a46692 100644 (file)
--- a/src/arg.c
+++ b/src/arg.c
@@ -111,7 +111,7 @@ ANN static void arg_drvr(DriverInfo* di, const int i) {
         di->sr       = (uint)strtol(optarg, NULL, 10);
         break;
       case 'd':
-        select_driver(di, optarg);
+        di->arg = optarg;
         break;
       case 'f':
         select_format(di, optarg);
index bac64f3d430fec94fbd19dbc09f909b0f9dbf152..9594284a96c144de7b765e7b3528363557dd6120 100644 (file)
@@ -1,3 +1,4 @@
+#include <string.h>
 #include "gwion_util.h"
 #include "gwion_ast.h"
 #include "oo.h"
@@ -31,10 +32,22 @@ ANN void gwion_init(const Gwion gwion, const Vector args) {
   gwion->vm->gwion = gwion;
   gwion->env->gwion = gwion;
   gwion->driver = (Driver*)xcalloc(1, sizeof(Driver));
+  gwion->plug = (PlugInfo*)xmalloc(sizeof(PlugInfo));
   plug_discover(gwion->plug, args);
 }
 
 ANN m_bool gwion_audio(const Gwion gwion, DriverInfo* di) {
+  // get driver from string.
+  if(di->arg) {
+    for(m_uint i = 0; i < map_size(&gwion->plug->drv); ++i) {
+      const m_str name = (m_str)VKEY(&gwion->plug->drv, i);
+      const size_t len = strlen(name);
+      if(!strncmp(name, di->arg, len)) {
+        di->func = (void (*)(struct driver_wrapper *))VVAL(&gwion->plug->drv, i);
+        break;
+      }
+    }
+  }
   di->func(gwion->driver);
   VM* vm = gwion->vm;
   return gwion->driver->ini(vm, di) > 0 &&
@@ -42,7 +55,7 @@ ANN m_bool gwion_audio(const Gwion gwion, DriverInfo* di) {
 }
 
 ANN m_bool gwion_engine(const Gwion gwion) {
-  return type_engine_init(gwion->vm, &gwion->plug[GWPLUG_IMPORT]) > 0;
+  return type_engine_init(gwion->vm, &gwion->plug->vec[GWPLUG_IMPORT]) > 0;
 }
 
 ANN void gwion_run(const Gwion gwion, DriverInfo* di) {
@@ -61,5 +74,6 @@ ANN void gwion_release(const Gwion gwion, DriverInfo* di) {
   free_env(gwion->env);
   free_emitter(gwion->emit);
   free_vm(gwion->vm);
+  xfree(gwion->plug);
   free_symbols();
 }
index b36129a66145f72190c08a65e1b9bdeacd2bda22..7e657403e9c235bf8c7587dc33bcafca75e67de8 100644 (file)
@@ -17,36 +17,53 @@ static inline int so_filter(const struct dirent* dir) {
   return strstr(dir->d_name, ".so") ? 1 : 0;
 }
 
+typedef m_bool (*import)(Gwi);
+typedef m_str  (*modstr)(void);
+typedef void*  (*modini)(const Gwion, const Vector);
+typedef void*  (*modend)(const Gwion, void*);
+typedef void*  (*modend)(const Gwion, void*);
+typedef void   (*driver)(struct driver_wrapper*);
 struct Plug_ {
   m_str name;
-  f_gwmodini ini;
-  f_gwmodend end;
+  modini ini;
+  modend end;
   void* self;
 };
+#define STR_EXPAND(tok) #tok
+#define STR(tok) STR_EXPAND(tok)
+#define DLFUNC(dl, t, a) (t)(intptr_t)dlsym(dl, STR(a));
 
-ANN static void plug_get(PlugInfo v, const m_str c) {
-  void* handler = dlopen(c, RTLD_LAZY);
-  if(handler) {
-    vector_add(&v[GWPLUG_DL], (vtype)handler);
-    m_bool (*import)(Gwi) = (m_bool(*)(Gwi))(intptr_t)dlsym(handler, "import");
-    if(import)
-      vector_add(&v[GWPLUG_IMPORT], (vtype)import);
-    const f_gwmodini ini = (f_gwmodini)(intptr_t)dlsym(handler, GWMODINI_NAME);
+ANN static void plug_get(PlugInfo* p, const m_str c) {
+  void* dl = dlopen(c, RTLD_LAZY);
+  if(dl) {
+    vector_add(&p->vec[GWPLUG_DL], (vtype)dl);
+    const import imp = DLFUNC(dl, import, GWIMPORT_NAME);
+    if(imp)
+      vector_add(&p->vec[GWPLUG_IMPORT], (vtype)imp);
+    const modini ini = DLFUNC(dl, modini, GWMODINI_NAME);
     if(ini) {
       struct Plug_ *plug = mp_alloc(Plug);
       plug->ini  = ini;
-      m_str (*name)() = (m_str(*)())(intptr_t)dlsym(handler, GWMODNAME_NAME);
-      plug->name = name();
-      plug->end  = (f_gwmodend)(intptr_t)dlsym(handler, GWMODEND_NAME);
-      vector_add(&v[GWPLUG_MODULE], (vtype)plug);
+      const modstr str = DLFUNC(dl, modstr, GWMODSTR_NAME);
+      plug->name = str();
+      plug->end  = DLFUNC(dl, modend, GWMODEND_NAME);
+      vector_add(&p->vec[GWPLUG_MODULE], (vtype)plug);
+    }
+    const driver drv = DLFUNC(dl, driver, GWDRIVER_NAME);
+    if(drv) {
+      const modstr str = DLFUNC(dl, modstr, GWMODSTR_NAME);
+printf("%s %s\n", __func__, str());
+//      map_set(&p->drv, (vtype)str(), (vtype)drv);
+      map_set(&p->drv, (vtype)str(), (vtype)drv);
     }
   } else
     err_msg(0, "error in %s.", dlerror());
 }
 
-void plug_discover(PlugInfo v, Vector list) {
+void plug_discover(PlugInfo* p, Vector list) {
   for(m_uint i = 0; i < GWPLUG_LAST; ++i)
-    vector_init(&v[i]);
+    vector_init(&p->vec[i]);
+  map_init(&p->drv);
   for(m_uint i = 0; i < vector_size(list); i++) {
    const m_str dir = (m_str)vector_at(list, i);
    struct dirent **file;
@@ -55,7 +72,7 @@ void plug_discover(PlugInfo v, Vector list) {
      while(n--) {
        char c[strlen(dir) + strlen(file[n]->d_name) + 2];
        sprintf(c, "%s/%s", dir, file[n]->d_name);
-       plug_get(v, c);
+       plug_get(p, c);
        free(file[n]);
       }
      free(file);
@@ -64,7 +81,7 @@ void plug_discover(PlugInfo v, Vector list) {
 }
 
 void plug_end(const Gwion gwion) {
-  struct Vector_ * const v = gwion->plug;
+  struct Vector_ * const v = gwion->plug->vec;
   for(m_uint i = 0; i < vector_size(&v[GWPLUG_MODULE]); ++i) {
     struct Plug_ *plug = (struct Plug_*)vector_at(&v[GWPLUG_MODULE], i);
     if(plug->end)
@@ -75,6 +92,7 @@ void plug_end(const Gwion gwion) {
     dlclose((void*)vector_at(&v[GWPLUG_DL], i));
   for(m_uint i = 0; i < GWPLUG_LAST; ++i)
     vector_release(&v[i]);
+  map_release(&gwion->plug->drv);
 }
 
 ANN static Vector get_arg(const m_str name, const Vector v) {
@@ -98,7 +116,7 @@ ANN static Vector get_arg(const m_str name, const Vector v) {
 }
 
 void plug_ini(const Gwion gwion, const Vector args) {
-  const Vector v = &gwion->plug[GWPLUG_MODULE];
+  const Vector v = &gwion->plug->vec[GWPLUG_MODULE];
   for(m_uint i = 0; i < vector_size(v); ++i) {
     struct Plug_ *plug = (struct Plug_*)vector_at(v, i);
     const Vector arg = get_arg(plug->name, args);
index ac464588f4a0d2652742792e5be66a40d04bf8ef..8c4e521ca240f9345a3e98dc253e120f120df32b 100644 (file)
@@ -5,7 +5,7 @@
 #include "env.h"
 #include "gwion.h"
 
-GWMODNAME("basic_module")
+GWMODSTR(basic_module)
 
 GWMODINI(basic_module) {
   puts("ini module");
index d616e424a87a0fb478b21cbd2bcb65c534323ffa..9be19e829d44b4c9bf9d39c4facf22c7bf22df8c 100644 (file)
@@ -1,4 +1,4 @@
-float f;
+<<<float f>>>;
 Coverage c;
 c.s_i;
 <<< Coverage.i() >>>;
diff --git a/tests/import/driver.c b/tests/import/driver.c
new file mode 100644 (file)
index 0000000..ec3c447
--- /dev/null
@@ -0,0 +1,26 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "env.h"
+#include "vm.h"
+#include "driver.h"
+#include "gwion.h"
+#include "plug.h"
+
+static void dummy_run(VM* vm, DriverInfo* di) {
+  while(vm->is_running) {
+    di->run(vm);
+    ++vm->bbq->pos;
+  }
+}
+
+static m_bool dummy_ini(VM* vm __attribute__((unused)), DriverInfo* di __attribute__((unused))) {
+  return GW_OK;
+}
+GWMODSTR(dummy2);
+GWDRIVER(Driver* d) {
+  d->ini = dummy_ini;
+  d->run = dummy_run;
+}
index 705a73fba6f03cc43266eb34b4c2b134f13c9e1f..bc6ded3dee675e0037add4ca738562619cba9a2a 100644 (file)
@@ -1,5 +1,5 @@
 #!/bin/bash
-# [test] #27
+# [test] #28
 
 n=0
 [ "$1" ] && n="$1"