From: fennecdjay Date: Tue, 5 Mar 2019 15:28:27 +0000 (+0100) Subject: :art: Introduce dynamicly loadable driver X-Git-Tag: nightly~2753^2~31 X-Git-Url: http://10.11.0.4:5575/?a=commitdiff_plain;h=116c65a1461f225682674ec2f198ce36bf497052;p=gwion.git :art: Introduce dynamicly loadable driver --- diff --git a/include/driver.h b/include/driver.h index 1cd9dbad..37759c99 100644 --- a/include/driver.h +++ b/include/driver.h @@ -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; diff --git a/include/gwion.h b/include/gwion.h index 06c6eaff..f2ff3aff 100644 --- a/include/gwion.h +++ b/include/gwion.h @@ -4,7 +4,7 @@ typedef struct Gwion_* Gwion; #include "plug.h" #include "driver.h" struct Gwion_ { - PlugInfo plug; + PlugInfo* plug; Driver* driver; // scanner // sym diff --git a/include/plug.h b/include/plug.h index 23d2d195..0e18dfc4 100644 --- a/include/plug.h +++ b/include/plug.h @@ -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 diff --git a/src/arg.c b/src/arg.c index 6d51f2f0..749733bd 100644 --- 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); diff --git a/src/gwion.c b/src/gwion.c index bac64f3d..9594284a 100644 --- a/src/gwion.c +++ b/src/gwion.c @@ -1,3 +1,4 @@ +#include #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(); } diff --git a/src/plug.c b/src/plug.c index b36129a6..7e657403 100644 --- a/src/plug.c +++ b/src/plug.c @@ -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); diff --git a/tests/import/basic_module.c b/tests/import/basic_module.c index ac464588..8c4e521c 100644 --- a/tests/import/basic_module.c +++ b/tests/import/basic_module.c @@ -5,7 +5,7 @@ #include "env.h" #include "gwion.h" -GWMODNAME("basic_module") +GWMODSTR(basic_module) GWMODINI(basic_module) { puts("ini module"); diff --git a/tests/import/coverage.gw b/tests/import/coverage.gw index d616e424..9be19e82 100644 --- a/tests/import/coverage.gw +++ b/tests/import/coverage.gw @@ -1,4 +1,4 @@ -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 index 00000000..ec3c447f --- /dev/null +++ b/tests/import/driver.c @@ -0,0 +1,26 @@ +#include +#include +#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; +} diff --git a/tests/sh/plugin.sh b/tests/sh/plugin.sh index 705a73fb..bc6ded3d 100644 --- a/tests/sh/plugin.sh +++ b/tests/sh/plugin.sh @@ -1,5 +1,5 @@ #!/bin/bash -# [test] #27 +# [test] #28 n=0 [ "$1" ] && n="$1"