diff options
-rw-r--r-- | src/plugininstance.c | 31 | ||||
-rw-r--r-- | src/world.c | 141 |
2 files changed, 72 insertions, 100 deletions
diff --git a/src/plugininstance.c b/src/plugininstance.c index ffe9b2b..a968e2b 100644 --- a/src/plugininstance.c +++ b/src/plugininstance.c @@ -78,35 +78,27 @@ slv2_plugin_instantiate(SLV2Plugin plugin, dlclose(lib); break; // return NULL } else { - // FIXME: duplicated/common code, put this in serd - SerdURI uri; - if (!serd_uri_parse((const uint8_t*)ld->URI, &uri)) { - SLV2_ERROR("Failed to parse library URI\n"); + // Parse bundle URI to use as base URI + const SLV2Value bundle_uri = slv2_plugin_get_bundle_uri(plugin); + const char* bundle_uri_str = slv2_value_as_uri(bundle_uri); + SerdURI base_uri; + if (!serd_uri_parse((const uint8_t*)bundle_uri_str, &base_uri)) { dlclose(lib); break; } - SerdURI base_uri; - if (!serd_uri_parse( - (const uint8_t*)slv2_value_as_uri(slv2_plugin_get_bundle_uri(plugin)), - &base_uri)) { + // Resolve library plugin URI against base URI + SerdURI abs_uri; + SerdNode abs_uri_node = serd_node_new_uri_from_string( + (const uint8_t*)ld->URI, &base_uri, &abs_uri); + if (!abs_uri_node.buf) { + SLV2_ERRORF("Failed to parse library plugin URI `%s'\n", ld->URI); dlclose(lib); break; } - SerdURI abs_uri; - if (!serd_uri_resolve(&uri, &base_uri, &abs_uri)) { - fprintf(stderr, "error: failed to resolve new base URI\n"); - return false; - } - - SerdNode abs_uri_node = serd_node_new_uri(&abs_uri, &base_uri); - if (!strcmp((const char*)abs_uri_node.buf, slv2_value_as_uri(slv2_plugin_get_uri(plugin)))) { - assert(plugin->plugin_uri); - assert(ld->instantiate); - // Create SLV2Instance to return result = malloc(sizeof(struct _Instance)); result->lv2_descriptor = ld; @@ -115,7 +107,6 @@ slv2_plugin_instantiate(SLV2Plugin plugin, struct _InstanceImpl* impl = malloc(sizeof(struct _InstanceImpl)); impl->lib_handle = lib; result->pimpl = impl; - serd_node_free(&abs_uri_node); break; } else { diff --git a/src/world.c b/src/world.c index 775bc64..0a8ab36 100644 --- a/src/world.c +++ b/src/world.c @@ -161,23 +161,13 @@ slv2_world_find_statements(SLV2World world, static SerdNode slv2_new_uri_relative_to_base(const uint8_t* uri_str, const uint8_t* base_uri_str) { - SerdURI uri; - if (!serd_uri_parse(uri_str, &uri)) { - return SERD_NODE_NULL; - } - SerdURI base_uri; if (!serd_uri_parse(base_uri_str, &base_uri)) { return SERD_NODE_NULL; } - SerdURI abs_uri; - if (!serd_uri_resolve(&uri, &base_uri, &abs_uri)) { - return SERD_NODE_NULL; - } - SerdURI ignored; - return serd_node_new_uri(&abs_uri, &ignored); + return serd_node_new_uri_from_string(uri_str, &base_uri, &ignored); } const uint8_t* @@ -397,27 +387,53 @@ slv2_world_load_bundle(SLV2World world, SLV2Value bundle_uri) slv2_match_end(spec_results); } -/** Load all bundles under a directory. - * Private. - */ -void -slv2_world_load_directory(SLV2World world, const char* dir) +// Expand POSIX things in path (particularly ~) +static char* +expand(const char* path) { - DIR* pdir = opendir(dir); - if (!pdir) + char* ret = NULL; + wordexp_t p; + + wordexp(path, &p, 0); + if (p.we_wordc == 0) { + // Literal directory path (e.g. no variables or ~) + ret = strdup(path); + } else if (p.we_wordc == 1) { + // Directory path expands (e.g. contains ~ or $FOO) + ret = strdup(p.we_wordv[0]); + } else { + // Multiple expansions in a single directory path? + fprintf(stderr, "lv2config: malformed path `%s' ignored\n", path); + } + + wordfree(&p); + return ret; +} + +/** Load all bundles in the directory at @a dir_path. */ +static void +slv2_world_load_directory(SLV2World world, const char* dir_path) +{ + char* path = expand(dir_path); + if (!path) { return; + } + + DIR* pdir = opendir(path); + if (!pdir) { + free(path); + return; + } struct dirent* pfile; while ((pfile = readdir(pdir))) { if (!strcmp(pfile->d_name, ".") || !strcmp(pfile->d_name, "..")) continue; - char* uri = slv2_strjoin("file://", dir, "/", pfile->d_name, "/", NULL); + char* uri = slv2_strjoin("file://", path, "/", pfile->d_name, "/", NULL); - // FIXME: Probably a better way to check if a dir exists - DIR* bundle_dir = opendir(uri + 7); - - if (bundle_dir != NULL) { + DIR* const bundle_dir = opendir(uri + 7); + if (bundle_dir) { closedir(bundle_dir); SLV2Value uri_val = slv2_value_new_uri(world, uri); slv2_world_load_bundle(world, uri_val); @@ -427,6 +443,7 @@ slv2_world_load_directory(SLV2World world, const char* dir) free(uri); } + free(path); closedir(pdir); } @@ -434,22 +451,22 @@ void slv2_world_load_path(SLV2World world, const char* lv2_path) { - char* path = slv2_strjoin(lv2_path, ":", NULL); - char* dir = path; // Pointer into path - - // Go through string replacing ':' with '\0', using the substring, - // then replacing it with 'X' and moving on. i.e. strtok on crack. - while (strchr(path, ':') != NULL) { - char* delim = strchr(path, ':'); - *delim = '\0'; - - slv2_world_load_directory(world, dir); - - *delim = 'X'; - dir = delim + 1; + static const char SLV2_PATH_SEP = ':'; + while (lv2_path[0] != '\0') { + const char* const sep = strchr(lv2_path, SLV2_PATH_SEP); + if (sep) { + const size_t dir_len = sep - lv2_path; + char* const dir = malloc(dir_len + 1); + memcpy(dir, lv2_path, dir_len); + dir[dir_len] = '\0'; + slv2_world_load_directory(world, dir); + free(dir); + lv2_path += dir_len + 1; + } else { + slv2_world_load_directory(world, lv2_path); + lv2_path = "\0"; + } } - - free(path); } void @@ -565,51 +582,15 @@ slv2_world_load_plugin_classes(SLV2World world) void slv2_world_load_all(SLV2World world) { - char* lv2_path = getenv("LV2_PATH"); - - /* 1. Read all manifest files into model */ + const char* lv2_path = getenv("LV2_PATH"); + if (!lv2_path) + lv2_path = SLV2_DEFAULT_LV2_PATH; - if (lv2_path) { - slv2_world_load_path(world, lv2_path); - } else { - char default_path[sizeof(SLV2_DEFAULT_LV2_PATH)]; - memcpy(default_path, SLV2_DEFAULT_LV2_PATH, sizeof(SLV2_DEFAULT_LV2_PATH)); - char* dir = default_path; - size_t lv2_path_len = 0; - while (*dir != '\0') { - char* colon = strchr(dir, ':'); - if (colon) - *colon = '\0'; - wordexp_t p; - wordexp(dir, &p, 0); - for (unsigned i = 0; i < p.we_wordc; i++) { - const size_t word_len = strlen(p.we_wordv[i]); - if (!lv2_path) { - lv2_path = strdup(p.we_wordv[i]); - lv2_path_len = word_len; - } else { - lv2_path = (char*)realloc(lv2_path, lv2_path_len + word_len + 2); - *(lv2_path + lv2_path_len) = ':'; - strcpy(lv2_path + lv2_path_len + 1, p.we_wordv[i]); - lv2_path_len += word_len + 1; - } - } - wordfree(&p); - if (colon) - dir = colon + 1; - else - *dir = '\0'; - } - - slv2_world_load_path(world, lv2_path); - - free(lv2_path); - } - - /* 2. Query out things to cache */ + // Discover bundles and read all manifest files into model + slv2_world_load_path(world, lv2_path); + // Query out things to cache slv2_world_load_specifications(world); - slv2_world_load_plugin_classes(world); /* FIXME: move this to slv2_world_load_bundle |