diff options
author | Hanspeter Portner <dev@open-music-kontrollers.ch> | 2015-06-29 20:53:04 +0200 |
---|---|---|
committer | Hanspeter Portner <dev@open-music-kontrollers.ch> | 2015-06-29 20:53:04 +0200 |
commit | 66baac218c2056d32eef1a82d25110db592d663c (patch) | |
tree | dc77d1727de89c9e7f543dc274d186ec91c7e853 /lib | |
parent | d924ea91b1ad3475f08fad59bbe9963bdd38e6de (diff) | |
parent | a04e30593bc0a3f8ce2c1bd0a19781bedcb84a68 (diff) | |
download | synthpod-66baac218c2056d32eef1a82d25110db592d663c.tar.xz |
Merge branch 'master' of /media/sdext/omk/synthpod
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/synthpod_app.c | 185 | ||||
-rw-r--r-- | lib/synthpod_app.h | 31 |
3 files changed, 167 insertions, 50 deletions
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index b6375735..51e44c33 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -2,6 +2,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${PROJECT_SOURCE_DIR}/eo_ui.lv2) include_directories(${PROJECT_SOURCE_DIR}/zero_worker.lv2) include_directories(${PROJECT_SOURCE_DIR}/zero_writer.lv2) +include_directories(${PROJECT_SOURCE_DIR}/system_port.lv2) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cjson) add_definitions("-D_GNU_SOURCE=1") # asprintf diff --git a/lib/synthpod_app.c b/lib/synthpod_app.c index ddc73d94..680a0830 100644 --- a/lib/synthpod_app.c +++ b/lib/synthpod_app.c @@ -34,7 +34,7 @@ #include <synthpod_app.h> #include <synthpod_private.h> -#define NUM_FEATURES 8 +#define NUM_FEATURES 9 #define MAX_SOURCES 32 // TODO how many? #define MAX_MODS 512 // TODO how many? @@ -96,6 +96,11 @@ struct _mod_t { Zero_Worker_Schedule schedule; } zero; + // system_port + struct { + const System_Port_Interface *iface; + } sys; + // log LV2_Log_Log log; @@ -151,6 +156,12 @@ struct _port_t { float min; float dflt; float max; + + // system_port iface + struct { + System_Port_Type type; + void *data; + } sys; }; struct _sp_app_t { @@ -177,10 +188,8 @@ struct _sp_app_t { uint32_t num_mods; mod_t *mods [MAX_MODS]; - struct { - mod_t *source; - mod_t *sink; - } system; + sp_app_system_source_t system_sources [128]; //FIXME, how many? + sp_app_system_sink_t system_sinks [128]; //FIXME, how many? u_id_t uid; @@ -292,33 +301,82 @@ sp_app_activate(sp_app_t *app) } // rt -void * -sp_app_get_system_source(sp_app_t *app, uint32_t index) +const sp_app_system_source_t * +sp_app_get_system_sources(sp_app_t *app) { - if(!app->system.source) - return NULL; + int num_system_sources = 0; + + for(uint32_t m=0; m<app->num_mods; m++) + { + mod_t *mod = app->mods[m]; + + if(!mod->sys.iface) // has system ports? + continue; // skip + + for(uint32_t p=0; p<mod->num_ports; p++) + { + port_t *port = &mod->ports[p]; + + if(port->sys.type == SYSTEM_PORT_NONE) + continue; // skip - // get last mod aka system source - mod_t *mod = app->system.source; - port_t *port = &mod->ports[index]; + if(port->direction == PORT_DIRECTION_OUTPUT) + { + app->system_sources[num_system_sources].type = port->sys.type; + app->system_sources[num_system_sources].buf = port->buf; + app->system_sources[num_system_sources].sys_port = port->sys.data; + num_system_sources += 1; + } + } + } + + // sentinel + app->system_sources[num_system_sources].type = SYSTEM_PORT_NONE; + app->system_sources[num_system_sources].buf = NULL; + app->system_sources[num_system_sources].sys_port = NULL; - return port->buf; + return app->system_sources; } // rt -const void * -sp_app_get_system_sink(sp_app_t *app, uint32_t index) +const sp_app_system_sink_t * +sp_app_get_system_sinks(sp_app_t *app) { - if(!app->system.sink) - return NULL; + int num_system_sinks = 0; + + for(uint32_t m=0; m<app->num_mods; m++) + { + mod_t *mod = app->mods[m]; + + if(!mod->sys.iface) // has system ports? + continue; + + for(uint32_t p=0; p<mod->num_ports; p++) + { + port_t *port = &mod->ports[p]; + + if(port->sys.type == SYSTEM_PORT_NONE) + continue; // skip + + if(port->direction == PORT_DIRECTION_INPUT) + { + app->system_sinks[num_system_sinks].type = port->sys.type; + app->system_sinks[num_system_sinks].buf = + (port->num_sources + port->num_feedbacks) == 1 + ? port->sources[0]->buf + : port->buf; + app->system_sinks[num_system_sinks].sys_port = port->sys.data; + num_system_sinks += 1; + } + } + } - // get last mod aka system sink - mod_t *mod = app->system.sink; - port_t *port = &mod->ports[index]; + // sentinel + app->system_sinks[num_system_sinks].type = SYSTEM_PORT_NONE; + app->system_sinks[num_system_sinks].buf = NULL; + app->system_sinks[num_system_sinks].sys_port = NULL; - return (port->num_sources + port->num_feedbacks) == 1 - ? port->sources[0]->buf - : port->buf; + return app->system_sinks; } // rt @@ -378,7 +436,7 @@ _zero_sched_advance(Zero_Worker_Handle handle, uint32_t written) // non-rt worker-thread static inline mod_t * -_sp_app_mod_add(sp_app_t *app, const char *uri) +_sp_app_mod_add(sp_app_t *app, const char *uri, uint32_t uid) { LilvNode *uri_node = lilv_new_uri(app->world, uri); const LilvPlugin *plug = lilv_plugins_get_by_uri(app->plugs, uri_node); @@ -482,6 +540,12 @@ _sp_app_mod_add(sp_app_t *app, const char *uri) mod->feature_list[nfeatures].URI = ZERO_WORKER__schedule; mod->feature_list[nfeatures++].data = &mod->zero.schedule; + if(app->driver->system_port_add && app->driver->system_port_del) + { + mod->feature_list[nfeatures].URI = SYSTEM_PORT__dynamicPorts; + mod->feature_list[nfeatures++].data = NULL; + } + assert(nfeatures <= NUM_FEATURES); for(int i=0; i<nfeatures; i++) @@ -524,7 +588,7 @@ _sp_app_mod_add(sp_app_t *app, const char *uri) } mod->app = app; - mod->uid = app->uid++; + mod->uid = uid != 0 ? uid : app->uid++; mod->plug = plug; mod->num_ports = lilv_plugin_get_num_ports(plug); mod->inst = lilv_plugin_instantiate(plug, app->driver->sample_rate, mod->features); @@ -535,6 +599,8 @@ _sp_app_mod_add(sp_app_t *app, const char *uri) ZERO_WORKER__interface); mod->opts.iface = lilv_instance_get_extension_data(mod->inst, LV2_OPTIONS__interface); //TODO actually use this for something? + mod->sys.iface = lilv_instance_get_extension_data(mod->inst, + SYSTEM_PORT__interface); lilv_instance_activate(mod->inst); int system_source = 0; @@ -560,6 +626,32 @@ _sp_app_mod_add(sp_app_t *app, const char *uri) ? PORT_DIRECTION_INPUT : PORT_DIRECTION_OUTPUT; + // register system ports + if(mod->sys.iface) + { + tar->sys.type = mod->sys.iface->query(mod->inst, i); + + if(app->driver->system_port_add) + { + //FIXME check lilv returns + char *short_name = NULL; + char *pretty_name = NULL; + asprintf(&short_name, "plugin_%u_%s", + mod->uid, lilv_node_as_string(lilv_port_get_symbol(plug, port))); + asprintf(&pretty_name, "Plugin %u - %s", + mod->uid, lilv_node_as_string(lilv_port_get_name(plug, port))); + tar->sys.data = app->driver->system_port_add(app->data, tar->sys.type, + short_name, pretty_name, tar->direction == PORT_DIRECTION_OUTPUT); + free(short_name); + free(pretty_name); + } + } + else + { + tar->sys.type = SYSTEM_PORT_NONE; + tar->sys.data = NULL; + } + if(lilv_port_is_a(plug, port, app->regs.port.audio.node)) { tar->size = app->driver->max_block_size * sizeof(float); @@ -712,6 +804,15 @@ _sp_app_mod_del(sp_app_t *app, mod_t *mod) free(mod->buf); } + // unregister system ports + for(uint32_t i=0; i<mod->num_ports; i++) + { + port_t *port = &mod->ports[i]; + + if(port->sys.data && app->driver->system_port_del) + app->driver->system_port_del(app->data, port->sys.data); + } + // free ports if(mod->ports) free(mod->ports); @@ -873,10 +974,9 @@ sp_app_new(const LilvWorld *world, sp_app_driver_t *driver, void *data) // inject source mod uri_str = SYNTHPOD_PREFIX"source"; - mod = _sp_app_mod_add(app, uri_str); + mod = _sp_app_mod_add(app, uri_str, 0); if(mod) { - app->system.source = mod; app->mods[app->num_mods] = mod; app->num_mods += 1; } @@ -885,10 +985,9 @@ sp_app_new(const LilvWorld *world, sp_app_driver_t *driver, void *data) // inject sink mod uri_str = SYNTHPOD_PREFIX"sink"; - mod = _sp_app_mod_add(app, uri_str); + mod = _sp_app_mod_add(app, uri_str, 0); if(mod) { - app->system.sink = mod; app->mods[app->num_mods] = mod; app->num_mods += 1; } @@ -1410,15 +1509,17 @@ sp_app_from_worker(sp_app_t *app, uint32_t len, const void *data) { case JOB_TYPE_MODULE_ADD: { + mod_t *mod = job->mod; + if(app->num_mods >= MAX_MODS) break; //TODO delete mod // inject module into module graph app->mods[app->num_mods] = app->mods[app->num_mods-1]; // system sink - app->mods[app->num_mods-1] = job->mod; + app->mods[app->num_mods-1] = mod; app->num_mods += 1; - const LilvNode *uri_node = lilv_plugin_get_uri(job->mod->plug); + const LilvNode *uri_node = lilv_plugin_get_uri(mod->plug); const char *uri_str = lilv_node_as_string(uri_node); //signal to UI @@ -1427,12 +1528,12 @@ sp_app_from_worker(sp_app_t *app, uint32_t len, const void *data) transmit_module_add_t *trans = _sp_app_to_ui_request(app, size); if(trans) { - const LV2_Descriptor *descriptor = lilv_instance_get_descriptor(job->mod->inst); + const LV2_Descriptor *descriptor = lilv_instance_get_descriptor(mod->inst); data_access_t data_access = descriptor ? descriptor->extension_data : NULL; _sp_transmit_module_add_fill(&app->regs, &app->forge, trans, size, - job->mod->uid, uri_str, job->mod->handle, data_access); + mod->uid, uri_str, mod->handle, data_access); _sp_app_to_ui_advance(app, size); } @@ -1882,7 +1983,7 @@ sp_worker_from_app(sp_app_t *app, uint32_t len, const void *data) { case JOB_TYPE_MODULE_ADD: { - mod_t *mod = _sp_app_mod_add(app, job->uri); + mod_t *mod = _sp_app_mod_add(app, job->uri, 0); if(!mod) break; //TODO report @@ -2183,7 +2284,7 @@ sp_app_run_post(sp_app_t *app, uint32_t nsamples) if( (port->type == PORT_TYPE_ATOM) && (port->buffer_type == PORT_BUFFER_TYPE_SEQUENCE) && (port->direction == PORT_DIRECTION_OUTPUT) - && (mod != app->system.source) ) // don't overwirte source buffer events + && (!mod->sys.iface) ) // don't overwrite source buffer events { LV2_Atom_Sequence *seq = port->buf; seq->atom.type = app->regs.port.sequence.urid; @@ -2678,8 +2779,6 @@ sp_app_restore(sp_app_t *app, LV2_State_Retrieve_Function retrieve, int num_mods = app->num_mods; app->num_mods = 0; - app->system.source = NULL; // if host should call port_connect() - app->system.sink = NULL; // if host should call port_connect() for(int m=0; m<num_mods; m++) _sp_app_mod_del(app, app->mods[m]); @@ -2697,15 +2796,10 @@ sp_app_restore(sp_app_t *app, LV2_State_Retrieve_Function retrieve, const char *mod_uri_str = mod_uri_json->valuestring; u_id_t mod_uid = mod_uid_json->valueint; - mod_t *mod = _sp_app_mod_add(app, mod_uri_str); + mod_t *mod = _sp_app_mod_add(app, mod_uri_str, mod_uid); if(!mod) continue; - if(mod_uid == 1) - app->system.source = mod; - else if(mod_uid == 2) - app->system.sink = mod; - // inject module into module graph app->mods[app->num_mods] = mod; app->num_mods += 1; @@ -2714,10 +2808,9 @@ sp_app_restore(sp_app_t *app, LV2_State_Retrieve_Function retrieve, mod->selected = mod_selected_json ? mod_selected_json->type == cJSON_True : 0; - mod->uid = mod_uid; - if(mod->uid > app->uid) - app->uid = mod->uid; + if(mod->uid > app->uid - 1) + app->uid = mod->uid + 1; char uid [64]; sprintf(uid, "%u/state.ttl", mod_uid); diff --git a/lib/synthpod_app.h b/lib/synthpod_app.h index 68377233..2078e2b4 100644 --- a/lib/synthpod_app.h +++ b/lib/synthpod_app.h @@ -31,8 +31,11 @@ #include <lilv/lilv.h> #include <synthpod_common.h> +#include <system_port.h> typedef struct _sp_app_t sp_app_t; +typedef struct _sp_app_system_source_t sp_app_system_source_t; +typedef struct _sp_app_system_sink_t sp_app_system_sink_t; typedef struct _sp_app_driver_t sp_app_driver_t; typedef void *(*sp_to_request_t)(size_t size, void *data); @@ -41,6 +44,22 @@ typedef void (*sp_to_advance_t)(size_t size, void *data); typedef int (*sp_printf)(void *data, LV2_URID type, const char *fmt, ...); typedef int (*sp_vprintf)(void *data, LV2_URID type, const char *fmt, va_list args); +typedef void *(*sp_system_port_add)(void *data, System_Port_Type type, + const char *short_name, const char *pretty_name, int input); +typedef void (*sp_system_port_del)(void *data, void *sys_port); + +struct _sp_app_system_source_t { + System_Port_Type type; + void *sys_port; + void *buf; +}; + +struct _sp_app_system_sink_t { + System_Port_Type type; + void *sys_port; + const void *buf; +}; + struct _sp_app_driver_t { uint32_t sample_rate; uint32_t min_block_size; @@ -64,6 +83,10 @@ struct _sp_app_driver_t { // logging sp_printf log_printf; sp_vprintf log_vprintf; + + // system_port + sp_system_port_add system_port_add; + sp_system_port_del system_port_del; }; sp_app_t * @@ -72,11 +95,11 @@ sp_app_new(const LilvWorld *world, sp_app_driver_t *driver, void *data); void sp_app_activate(sp_app_t *app); -void * -sp_app_get_system_source(sp_app_t *app, uint32_t index); +const sp_app_system_source_t * +sp_app_get_system_sources(sp_app_t *app); -const void * -sp_app_get_system_sink(sp_app_t *app, uint32_t index); +const sp_app_system_sink_t * +sp_app_get_system_sinks(sp_app_t *app); void sp_app_from_ui(sp_app_t *app, const LV2_Atom *atom); |