diff options
-rw-r--r-- | lv2/lv2plug.in/ns/ext/atom/atom-test.c | 37 | ||||
-rw-r--r-- | lv2/lv2plug.in/ns/ext/atom/atom.h | 31 | ||||
-rw-r--r-- | lv2/lv2plug.in/ns/ext/atom/atom.ttl | 26 | ||||
-rw-r--r-- | lv2/lv2plug.in/ns/ext/atom/forge.h | 32 | ||||
-rw-r--r-- | lv2/lv2plug.in/ns/ext/message/message.h | 31 | ||||
-rw-r--r-- | lv2/lv2plug.in/ns/ext/state/state.h | 11 | ||||
-rw-r--r-- | lv2/lv2plug.in/ns/ext/state/state.ttl | 23 | ||||
-rw-r--r-- | plugins/eg-sampler.lv2/sampler.c | 94 | ||||
-rw-r--r-- | plugins/eg-sampler.lv2/sampler_ui.c | 40 | ||||
-rw-r--r-- | plugins/eg-sampler.lv2/uris.h | 62 |
10 files changed, 201 insertions, 186 deletions
diff --git a/lv2/lv2plug.in/ns/ext/atom/atom-test.c b/lv2/lv2plug.in/ns/ext/atom/atom-test.c index 2cc0da9..2011f68 100644 --- a/lv2/lv2plug.in/ns/ext/atom/atom-test.c +++ b/lv2/lv2plug.in/ns/ext/atom/atom-test.c @@ -72,16 +72,17 @@ main() LV2_URID eg_four = urid_map(NULL, "http://example.org/four"); LV2_URID eg_true = urid_map(NULL, "http://example.org/true"); LV2_URID eg_false = urid_map(NULL, "http://example.org/false"); + LV2_URID eg_path = urid_map(NULL, "http://example.org/path"); LV2_URID eg_uri = urid_map(NULL, "http://example.org/uri"); LV2_URID eg_urid = urid_map(NULL, "http://example.org/urid"); LV2_URID eg_string = urid_map(NULL, "http://example.org/string"); LV2_URID eg_literal = urid_map(NULL, "http://example.org/literal"); LV2_URID eg_tuple = urid_map(NULL, "http://example.org/tuple"); LV2_URID eg_vector = urid_map(NULL, "http://example.org/vector"); - LV2_URID eg_seq = urid_map(NULL, "http://example.org/seq"); + LV2_URID eg_seq = urid_map(NULL, "http: //example.org/seq"); #define BUF_SIZE 1024 -#define NUM_PROPS 13 +#define NUM_PROPS 14 uint8_t buf[BUF_SIZE]; lv2_atom_forge_set_buffer(&forge, buf, BUF_SIZE); @@ -132,15 +133,26 @@ main() return test_fail("%ld != 0 (false)\n", f->value); } + // eg_path = (Path)"/foo/bar" + const uint8_t* pstr = (const uint8_t*)"/foo/bar"; + const size_t pstr_len = strlen((const char*)pstr); + lv2_atom_forge_property_head(&forge, eg_path, 0); + LV2_Atom_String* path = lv2_atom_forge_uri(&forge, pstr, pstr_len); + uint8_t* pbody = (uint8_t*)LV2_ATOM_BODY(path); + if (strcmp((const char*)pbody, (const char*)pstr)) { + return test_fail("%s != \"%s\"\n", + (const char*)pbody, (const char*)pstr); + } + // eg_uri = (URI)"http://example.org/value" const uint8_t* ustr = (const uint8_t*)"http://example.org/value"; const size_t ustr_len = strlen((const char*)ustr); lv2_atom_forge_property_head(&forge, eg_uri, 0); - LV2_Atom_String* uri = lv2_atom_forge_uri(&forge, ustr, ustr_len); - uint8_t* body = (uint8_t*)LV2_ATOM_BODY(uri); - if (strcmp((const char*)body, (const char*)ustr)) { + LV2_Atom_String* uri = lv2_atom_forge_uri(&forge, ustr, ustr_len); + uint8_t* ubody = (uint8_t*)LV2_ATOM_BODY(uri); + if (strcmp((const char*)ubody, (const char*)ustr)) { return test_fail("%s != \"%s\"\n", - (const char*)body, (const char*)ustr); + (const char*)ubody, (const char*)ustr); } // eg_urid = (URID)"http://example.org/value" @@ -157,7 +169,7 @@ main() &forge, (const uint8_t*)"hello", strlen("hello")); uint8_t* sbody = (uint8_t*)LV2_ATOM_BODY(string); if (strcmp((const char*)sbody, "hello")) { - return test_fail("%s != \"hello\"\n", (const char*)body); + return test_fail("%s != \"hello\"\n", (const char*)sbody); } // eg_literal = (Literal)"hello"@fr @@ -165,9 +177,9 @@ main() LV2_Atom_Literal* literal = lv2_atom_forge_literal( &forge, (const uint8_t*)"bonjour", strlen("bonjour"), 0, urid_map(NULL, "http://lexvo.org/id/term/fr")); - body = (uint8_t*)LV2_ATOM_CONTENTS(LV2_Atom_Literal, literal); - if (strcmp((const char*)body, "bonjour")) { - return test_fail("%s != \"bonjour\"\n", (const char*)body); + uint8_t* lbody = (uint8_t*)LV2_ATOM_CONTENTS(LV2_Atom_Literal, literal); + if (strcmp((const char*)lbody, "bonjour")) { + return test_fail("%s != \"bonjour\"\n", (const char*)lbody); } // eg_tuple = "foo",true @@ -267,6 +279,7 @@ main() const LV2_Atom* four; const LV2_Atom* affirmative; const LV2_Atom* negative; + const LV2_Atom* path; const LV2_Atom* uri; const LV2_Atom* urid; const LV2_Atom* string; @@ -285,6 +298,7 @@ main() { eg_four, &matches.four }, { eg_true, &matches.affirmative }, { eg_false, &matches.negative }, + { eg_path, &matches.path }, { eg_uri, &matches.uri }, { eg_urid, &matches.urid }, { eg_string, &matches.string }, @@ -312,6 +326,8 @@ main() return test_fail("Bad match true\n"); } else if (!lv2_atom_equals((LV2_Atom*)f, matches.negative)) { return test_fail("Bad match false\n"); + } else if (!lv2_atom_equals((LV2_Atom*)path, matches.path)) { + return test_fail("Bad match path\n"); } else if (!lv2_atom_equals((LV2_Atom*)uri, matches.uri)) { return test_fail("Bad match URI\n"); } else if (!lv2_atom_equals((LV2_Atom*)string, matches.string)) { @@ -333,6 +349,7 @@ main() eg_four, &matches.four, eg_true, &matches.affirmative, eg_false, &matches.negative, + eg_path, &matches.path, eg_uri, &matches.uri, eg_urid, &matches.urid, eg_string, &matches.string, diff --git a/lv2/lv2plug.in/ns/ext/atom/atom.h b/lv2/lv2plug.in/ns/ext/atom/atom.h index 66f0490..f45ba74 100644 --- a/lv2/lv2plug.in/ns/ext/atom/atom.h +++ b/lv2/lv2plug.in/ns/ext/atom/atom.h @@ -27,6 +27,37 @@ #define LV2_ATOM_URI "http://lv2plug.in/ns/ext/atom" +#define LV2_ATOM__Atom LV2_ATOM_URI "#Atom" +#define LV2_ATOM__Bang LV2_ATOM_URI "#Bang" +#define LV2_ATOM__Number LV2_ATOM_URI "#Number" +#define LV2_ATOM__Int32 LV2_ATOM_URI "#Int32" +#define LV2_ATOM__Int64 LV2_ATOM_URI "#Int64" +#define LV2_ATOM__Float LV2_ATOM_URI "#Float" +#define LV2_ATOM__Double LV2_ATOM_URI "#Double" +#define LV2_ATOM__Bool LV2_ATOM_URI "#Bool" +#define LV2_ATOM__String LV2_ATOM_URI "#String" +#define LV2_ATOM__Literal LV2_ATOM_URI "#Literal" +#define LV2_ATOM__Path LV2_ATOM_URI "#Path" +#define LV2_ATOM__URI LV2_ATOM_URI "#URI" +#define LV2_ATOM__URID LV2_ATOM_URI "#URID" +#define LV2_ATOM__Vector LV2_ATOM_URI "#Vector" +#define LV2_ATOM__Tuple LV2_ATOM_URI "#Tuple" +#define LV2_ATOM__Property LV2_ATOM_URI "#Property" +#define LV2_ATOM__Object LV2_ATOM_URI "#Object" +#define LV2_ATOM__Resource LV2_ATOM_URI "#Resource" +#define LV2_ATOM__Blank LV2_ATOM_URI "#Blank" +#define LV2_ATOM__TimeUnit LV2_ATOM_URI "#TimeUnit" +#define LV2_ATOM__AudioFrames LV2_ATOM_URI "#AudioFrames" +#define LV2_ATOM__Beats LV2_ATOM_URI "#Beats" +#define LV2_ATOM__Event LV2_ATOM_URI "#Event" +#define LV2_ATOM__Sequence LV2_ATOM_URI "#Sequence" +#define LV2_ATOM__AtomPort LV2_ATOM_URI "#AtomPort" +#define LV2_ATOM__ValuePort LV2_ATOM_URI "#ValuePort" +#define LV2_ATOM__MessagePort LV2_ATOM_URI "#MessagePort" +#define LV2_ATOM__bufferType LV2_ATOM_URI "#bufferType" +#define LV2_ATOM__supports LV2_ATOM_URI "#supports" +#define LV2_ATOM__eventTransfer LV2_ATOM_URI "#eventTransfer" + #define LV2_ATOM_REFERENCE_TYPE 0 #include <stdint.h> diff --git a/lv2/lv2plug.in/ns/ext/atom/atom.ttl b/lv2/lv2plug.in/ns/ext/atom/atom.ttl index 70a1252..677a159 100644 --- a/lv2/lv2plug.in/ns/ext/atom/atom.ttl +++ b/lv2/lv2plug.in/ns/ext/atom/atom.ttl @@ -218,22 +218,28 @@ void set_to_turtle_string(LV2_Atom_Literal* lit, const char* ttl) { </pre> """ . +atom:Path + a rdfs:Class ; + rdfs:subClassOf atom:String ; + rdfs:label "File path string" ; + lv2:documentation """ +<p>A local file path string. This is identical in format to atom:String, +except the string is a path. Since the ability to distinguish paths from plain +strings is often necessary, paths MUST NOT be transmitted as atom:String.</p> +""" . + atom:URI a rdfs:Class ; rdfs:subClassOf atom:String ; rdfs:label "URI string" ; lv2:documentation """ <p>A URI string. This is identical in format to atom:String, except the string -is a URI. This is occasionally useful when a URI is needed but mapping it is -inappropriate. URIs should never be expressed as atom:String, because this -makes it impossible to distinguish URIs from arbitrary strings, which makes -functionality like mapping or rewriting URIs impossible. Similarly, there is -deliberately no atom type for filesystem paths. To refer to a filename, use a -complete file URI, with hostname if at all possible. This allows hosts to -properly handle paths in situations like serialisation or network -transmission.</p> - -<p>Pedantically, this is an <q>IRI</q>, since UTF-8 characters are allowed.</p> +is a URI. This is useful when a URI is needed but mapping is inappropriate. +Since the ability to distinguish URIs from plain strings is often necessary, +URIs MUST NOT be transmitted as atom:String.</p> + +<p>This is not strictly a URI, since UTF-8 is allowed. Escaping and related +issues issues are the host's responsibility.</p> """ . atom:URID diff --git a/lv2/lv2plug.in/ns/ext/atom/forge.h b/lv2/lv2plug.in/ns/ext/atom/forge.h index 4db9638..06f24f5 100644 --- a/lv2/lv2plug.in/ns/ext/atom/forge.h +++ b/lv2/lv2plug.in/ns/ext/atom/forge.h @@ -85,6 +85,7 @@ typedef struct { LV2_URID Int32; LV2_URID Int64; LV2_URID Literal; + LV2_URID Path; LV2_URID Property; LV2_URID Resource; LV2_URID Sequence; @@ -172,6 +173,7 @@ lv2_atom_forge_init(LV2_Atom_Forge* forge, LV2_URID_Map* map) forge->Int32 = map->map(map->handle, LV2_ATOM_URI "#Int32"); forge->Int64 = map->map(map->handle, LV2_ATOM_URI "#Int64"); forge->Literal = map->map(map->handle, LV2_ATOM_URI "#Literal"); + forge->Path = map->map(map->handle, LV2_ATOM_URI "#Path"); forge->Property = map->map(map->handle, LV2_ATOM_URI "#Property"); forge->Resource = map->map(map->handle, LV2_ATOM_URI "#Resource"); forge->Sequence = map->map(map->handle, LV2_ATOM_URI "#Sequence"); @@ -322,13 +324,31 @@ lv2_atom_forge_uri(LV2_Atom_Forge* forge, const LV2_Atom_String a = { { forge->URI, len + 1 } }; LV2_Atom_String* out = (LV2_Atom_String*) lv2_atom_forge_write_nopad(forge, &a, sizeof(a)); - if (!out) { - return NULL; + if (out) { + if (!lv2_atom_forge_string_body(forge, uri, len)) { + out->atom.type = 0; + out->atom.size = 0; + out = NULL; + } } - if (!lv2_atom_forge_string_body(forge, uri, len)) { - out->atom.type = 0; - out->atom.size = 0; - return NULL; + return out; +} + +/** Write an atom:Path. Note that @p path need not be NULL terminated. */ +static inline LV2_Atom_String* +lv2_atom_forge_path(LV2_Atom_Forge* forge, + const uint8_t* path, + size_t len) +{ + const LV2_Atom_String a = { { forge->Path, len + 1 } }; + LV2_Atom_String* out = (LV2_Atom_String*) + lv2_atom_forge_write_nopad(forge, &a, sizeof(a)); + if (out) { + if (!lv2_atom_forge_string_body(forge, path, len)) { + out->atom.type = 0; + out->atom.size = 0; + out = NULL; + } } return out; } diff --git a/lv2/lv2plug.in/ns/ext/message/message.h b/lv2/lv2plug.in/ns/ext/message/message.h index 9c03713..728b836 100644 --- a/lv2/lv2plug.in/ns/ext/message/message.h +++ b/lv2/lv2plug.in/ns/ext/message/message.h @@ -27,21 +27,20 @@ #define LV2_MESSAGE_URI "http://lv2plug.in/ns/ext/message" -#define LV2_MESSAGE_Ack LV2_MESSAGE_URI "#Ack" -#define LV2_MESSAGE_Delete LV2_MESSAGE_URI "#Delete" -#define LV2_MESSAGE_Error LV2_MESSAGE_URI "#Error" -#define LV2_MESSAGE_Get LV2_MESSAGE_URI "#Get" -#define LV2_MESSAGE_Message LV2_MESSAGE_URI "#Message" -#define LV2_MESSAGE_Move LV2_MESSAGE_URI "#Move" -#define LV2_MESSAGE_Patch LV2_MESSAGE_URI "#Patch" -#define LV2_MESSAGE_Post LV2_MESSAGE_URI "#Post" -#define LV2_MESSAGE_Put LV2_MESSAGE_URI "#Put" -#define LV2_MESSAGE_Request LV2_MESSAGE_URI "#Request" -#define LV2_MESSAGE_Response LV2_MESSAGE_URI "#Response" -#define LV2_MESSAGE_Set LV2_MESSAGE_URI "#Set" - -#define LV2_MESSAGE_add LV2_MESSAGE_URI "#add" -#define LV2_MESSAGE_body LV2_MESSAGE_URI "#body" -#define LV2_MESSAGE_cause LV2_MESSAGE_URI "#cause" +#define LV2_MESSAGE__Ack LV2_MESSAGE_URI "#Ack" +#define LV2_MESSAGE__Delete LV2_MESSAGE_URI "#Delete" +#define LV2_MESSAGE__Error LV2_MESSAGE_URI "#Error" +#define LV2_MESSAGE__Get LV2_MESSAGE_URI "#Get" +#define LV2_MESSAGE__Message LV2_MESSAGE_URI "#Message" +#define LV2_MESSAGE__Move LV2_MESSAGE_URI "#Move" +#define LV2_MESSAGE__Patch LV2_MESSAGE_URI "#Patch" +#define LV2_MESSAGE__Post LV2_MESSAGE_URI "#Post" +#define LV2_MESSAGE__Put LV2_MESSAGE_URI "#Put" +#define LV2_MESSAGE__Request LV2_MESSAGE_URI "#Request" +#define LV2_MESSAGE__Response LV2_MESSAGE_URI "#Response" +#define LV2_MESSAGE__Set LV2_MESSAGE_URI "#Set" +#define LV2_MESSAGE__add LV2_MESSAGE_URI "#add" +#define LV2_MESSAGE__body LV2_MESSAGE_URI "#body" +#define LV2_MESSAGE__cause LV2_MESSAGE_URI "#cause" #endif /* LV2_MESSAGE_H */ diff --git a/lv2/lv2plug.in/ns/ext/state/state.h b/lv2/lv2plug.in/ns/ext/state/state.h index b450b93..aa272b7 100644 --- a/lv2/lv2plug.in/ns/ext/state/state.h +++ b/lv2/lv2plug.in/ns/ext/state/state.h @@ -36,10 +36,11 @@ extern "C" { #define LV2_STATE_URI "http://lv2plug.in/ns/ext/state" -#define LV2_STATE_INTERFACE_URI LV2_STATE_URI "#Interface" -#define LV2_STATE_PATH_URI LV2_STATE_URI "#Path" -#define LV2_STATE_MAP_PATH_URI LV2_STATE_URI "#mapPath" -#define LV2_STATE_MAKE_PATH_URI LV2_STATE_URI "#makePath" +#define LV2_STATE__Interface LV2_STATE_URI "#Interface" +#define LV2_STATE__State LV2_STATE_URI "#State" +#define LV2_STATE__state LV2_STATE_URI "#state" +#define LV2_STATE__mapPath LV2_STATE_URI "#mapPath" +#define LV2_STATE__makePath LV2_STATE_URI "#makePath" typedef void* LV2_State_Handle; typedef void* LV2_State_Map_Path_Handle; @@ -315,7 +316,7 @@ typedef struct { } LV2_State_Map_Path; /** - Feature data for state:makePath (@ref LV2_STATE_MAKE_PATH_URI). + Feature data for state:makePath (@ref LV2_STATE__makePath). */ typedef struct { diff --git a/lv2/lv2plug.in/ns/ext/state/state.ttl b/lv2/lv2plug.in/ns/ext/state/state.ttl index 6c0656a..4b86eb6 100644 --- a/lv2/lv2plug.in/ns/ext/state/state.ttl +++ b/lv2/lv2plug.in/ns/ext/state/state.ttl @@ -193,7 +193,9 @@ Map get_plugin_state(LV2_Handle instance) <p>Plugins may need to refer to files (e.g. loaded samples) in their state. This is done by storing the file's path as a property just like any other value. However, there are some rules which MUST be followed when storing -paths, see <a href="#mapPath">state:mapPath</a> for details.</p> +paths, see <a href="#mapPath">state:mapPath</a> for details. Plugins MUST +use the type <a href="http://lv2plug.in/ns/ext/atom#Path">atom:Path</a> +for all paths in their state.</p> <h3>Creating New Files or Directories</h3> @@ -267,7 +269,6 @@ state:mapPath a lv2:Feature ; rdfs:label "Support for storing paths in files" ; lv2:documentation """ - <p>This feature maps absolute paths to/from <q>abstract paths</q> which are stored in state. To support this feature a host must pass an LV2_Feature with URI LV2_STATE_MAP_PATH_URI and data pointed to an LV2_State_Map_Path to the @@ -305,7 +306,6 @@ state:makePath a lv2:Feature ; rdfs:label "Support for creating new files and directories" ; lv2:documentation """ - <p>This feature allows plugins to create new files and/or directories. To support this feature the host passes an LV2_Feature with URI LV2_STATE_MAKE_PATH_URI and data pointed to an LV2_State_Make_Path to the @@ -340,20 +340,3 @@ char* save_myfile(LV2_State_Make_Path* make_path) } </pre> """ . - -state:Path - a rdfs:Class ; - rdfs:label "Path" ; - lv2:documentation """ -<p>A path to a file or directory.</p> - -<p>The format of a state:Path is a C string, possibly escaped or otherwise -restricted in a system-specific manner. This URI (LV2_STATE_PATH_URI), mapped -to an integer, MUST be used as the <code>type</code> parameter for any files -passed to the LV2_State_Store_Function; and will likewise be returned by the -corresponding call to the LV2_State_Retrieve_Function.</p> - -<p>When storing and retrieving a path, the plugin MUST NOT assume the same path -will be restored. However, the restored path will refer to a file with -equivalent contents to the original.</p> -""" . diff --git a/plugins/eg-sampler.lv2/sampler.c b/plugins/eg-sampler.lv2/sampler.c index 904f026..043f629 100644 --- a/plugins/eg-sampler.lv2/sampler.c +++ b/plugins/eg-sampler.lv2/sampler.c @@ -63,11 +63,10 @@ enum { static const char* default_sample_file = "monosample.wav"; typedef struct { - SF_INFO info; /**< Info about sample from sndfile */ - float* data; /**< Sample data in float */ - char* uri; /**< URI of file */ - const char* path; /**< Path of file (pointer into uri) */ - size_t uri_len; /**< Length of uri. */ + SF_INFO info; /**< Info about sample from sndfile */ + float* data; /**< Sample data in float */ + char* path; /**< Path of file */ + size_t path_len; /**< Length of path */ } Sample; typedef struct { @@ -110,41 +109,10 @@ typedef struct { Sample* sample; } SampleMessage; -static bool -parse_file_uri(const char* uri, - const char** host, size_t* host_len, - const char** path, size_t* path_len) -{ - if (strncmp(uri, "file://", strlen("file://"))) { - return false; - } - - *host = uri + strlen("file://"); - const char* host_end = *host; - for (; *host_end && *host_end != '/'; ++host_end) {} - - *host_len = host_end - *host; - *path = host_end; - *path_len = (uri + strlen(uri)) - host_end; - - return true; -} - static Sample* -load_sample(Sampler* plugin, const char* uri) +load_sample(Sampler* plugin, const char* path) { - const size_t uri_len = strlen(uri); - const char* host = NULL; - const char* path = NULL; - size_t host_len = 0; - size_t path_len = 0; - if (!parse_file_uri(uri, &host, &host_len, &path, &path_len)) { - fprintf(stderr, "Request to load bad file URI %s\n", uri); - return NULL; - } - - /* Probably should check if the host is local here, but we'll just - blissfully attempt to load the path on this machine... */ + const size_t path_len = strlen(path); printf("Loading sample %s\n", path); Sample* const sample = (Sample*)malloc(sizeof(Sample)); @@ -168,11 +136,10 @@ load_sample(Sampler* plugin, const char* uri) sf_close(sndfile); /* Fill sample struct and return it. */ - sample->data = data; - sample->uri = (char*)malloc(uri_len + 1); - sample->path = sample->uri + (path - uri); - sample->uri_len = uri_len; - memcpy(sample->uri, uri, uri_len + 1); + sample->data = data; + sample->path = (char*)malloc(path_len + 1); + sample->path_len = path_len; + memcpy(sample->path, path, path_len + 1); return sample; } @@ -181,14 +148,14 @@ static bool handle_set_message(Sampler* plugin, const LV2_Atom_Object* obj) { - /* Get file URI from message */ - const LV2_Atom* file_uri = get_msg_file_uri(&plugin->uris, obj); - if (!file_uri) { + /* Get file path from message */ + const LV2_Atom* file_path = get_msg_file_path(&plugin->uris, obj); + if (!file_path) { return false; } /* Load sample. */ - Sample* sample = load_sample(plugin, LV2_ATOM_BODY(file_uri)); + Sample* sample = load_sample(plugin, LV2_ATOM_BODY(file_path)); if (sample) { /* Loaded sample, send it to run() to be applied. */ const SampleMessage msg = { @@ -206,10 +173,12 @@ handle_set_message(Sampler* plugin, void free_sample(Sample* sample) { - fprintf(stderr, "Freeing %s\n", sample->uri); - free(sample->uri); - free(sample->data); - free(sample); + if (sample) { + fprintf(stderr, "Freeing %s\n", sample->path); + free(sample->path); + free(sample->data); + free(sample); + } } void* @@ -441,23 +410,10 @@ run(LV2_Handle instance, plugin->sample = m.sample; /* Send a notification that we're using a new sample. */ - lv2_atom_forge_audio_time(&plugin->forge, 0, 0); - - LV2_Atom_Forge_Frame set_frame; - lv2_atom_forge_blank(&plugin->forge, &set_frame, 1, uris->msg_Set); - - lv2_atom_forge_property_head(&plugin->forge, uris->msg_body, 0); - LV2_Atom_Forge_Frame body_frame; - lv2_atom_forge_blank(&plugin->forge, &body_frame, 2, 0); - - lv2_atom_forge_property_head(&plugin->forge, uris->eg_file, 0); - lv2_atom_forge_uri(&plugin->forge, - (const uint8_t*)plugin->sample->uri, - plugin->sample->uri_len); - - lv2_atom_forge_pop(&plugin->forge, &body_frame); - lv2_atom_forge_pop(&plugin->forge, &set_frame); + write_set_filename_msg(&plugin->forge, uris, + plugin->sample->path, + plugin->sample->path_len); } else { fprintf(stderr, "Unknown message from worker\n"); @@ -476,7 +432,7 @@ save(LV2_Handle instance, { LV2_State_Map_Path* map_path = NULL; for (int i = 0; features[i]; ++i) { - if (!strcmp(features[i]->URI, LV2_STATE_MAP_PATH_URI)) { + if (!strcmp(features[i]->URI, LV2_STATE__mapPath)) { map_path = (LV2_State_Map_Path*)features[i]->data; } } @@ -489,7 +445,7 @@ save(LV2_Handle instance, plugin->uris.eg_file, apath, strlen(plugin->sample->path) + 1, - plugin->uris.state_Path, + plugin->uris.atom_Path, LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); free(apath); diff --git a/plugins/eg-sampler.lv2/sampler_ui.c b/plugins/eg-sampler.lv2/sampler_ui.c index 056f0bb..2c039a5 100644 --- a/plugins/eg-sampler.lv2/sampler_ui.c +++ b/plugins/eg-sampler.lv2/sampler_ui.c @@ -75,46 +75,18 @@ on_load_clicked(GtkWidget* widget, /* Got what we need, destroy the dialog. */ gtk_widget_destroy(dialog); - /* Build a complete file URI with hostname, e.g. file://hal/home/me/foo.wav - This is to precisely specify the file location, even if the plugin is - running on a different host (which is entirely possible). Plugins - should do this even though some hosts may not support such setups. - */ - const char* hostname = g_get_host_name(); - char* file_uri = g_filename_to_uri(filename, hostname, NULL); - const size_t file_uri_len = strlen(file_uri); - #define OBJ_BUF_SIZE 1024 uint8_t obj_buf[OBJ_BUF_SIZE]; lv2_atom_forge_set_buffer(&ui->forge, obj_buf, OBJ_BUF_SIZE); - /* Send [ - * a msg:Set ; - * msg:body [ - * eg-sampler:filename <file://hal/home/me/foo.wav> ; - * ] ; - * ] - */ - LV2_Atom_Forge_Frame set_frame; - LV2_Atom* set = (LV2_Atom*)lv2_atom_forge_blank( - &ui->forge, &set_frame, 1, ui->uris.msg_Set); - - lv2_atom_forge_property_head(&ui->forge, ui->uris.msg_body, 0); - LV2_Atom_Forge_Frame body_frame; - lv2_atom_forge_blank(&ui->forge, &body_frame, 2, 0); - - lv2_atom_forge_property_head(&ui->forge, ui->uris.eg_file, 0); - lv2_atom_forge_uri(&ui->forge, (const uint8_t*)file_uri, file_uri_len); - - ui->write(ui->controller, 0, lv2_atom_total_size(set), - ui->uris.atom_eventTransfer, - set); + LV2_Atom* msg = write_set_filename_msg(&ui->forge, &ui->uris, + filename, strlen(filename)); - lv2_atom_forge_pop(&ui->forge, &body_frame); - lv2_atom_forge_pop(&ui->forge, &set_frame); + ui->write(ui->controller, 0, lv2_atom_total_size(msg), + ui->uris.atom_eventTransfer, + msg); g_free(filename); - g_free(file_uri); } static LV2UI_Handle @@ -186,7 +158,7 @@ port_event(LV2UI_Handle handle, LV2_Atom* atom = (LV2_Atom*)buffer; if (atom->type == ui->uris.atom_Blank) { LV2_Atom_Object* obj = (LV2_Atom_Object*)atom; - const LV2_Atom* file_uri = get_msg_file_uri(&ui->uris, obj); + const LV2_Atom* file_uri = get_msg_file_path(&ui->uris, obj); if (!file_uri) { fprintf(stderr, "Unknown message sent to UI.\n"); return; diff --git a/plugins/eg-sampler.lv2/uris.h b/plugins/eg-sampler.lv2/uris.h index 6584c13..97cefca 100644 --- a/plugins/eg-sampler.lv2/uris.h +++ b/plugins/eg-sampler.lv2/uris.h @@ -31,6 +31,7 @@ typedef struct { LV2_URID atom_Blank; + LV2_URID atom_Path; LV2_URID atom_Resource; LV2_URID atom_eventTransfer; LV2_URID eg_applySample; @@ -39,22 +40,21 @@ typedef struct { LV2_URID midi_Event; LV2_URID msg_Set; LV2_URID msg_body; - LV2_URID state_Path; } SamplerURIs; static inline void map_sampler_uris(LV2_URID_Map* map, SamplerURIs* uris) { - uris->atom_Blank = map->map(map->handle, NS_ATOM "Blank"); - uris->atom_Resource = map->map(map->handle, NS_ATOM "Resource"); - uris->atom_eventTransfer = map->map(map->handle, NS_ATOM "eventTransfer"); + uris->atom_Blank = map->map(map->handle, LV2_ATOM__Blank); + uris->atom_Path = map->map(map->handle, LV2_ATOM__Path); + uris->atom_Resource = map->map(map->handle, LV2_ATOM__Resource); + uris->atom_eventTransfer = map->map(map->handle, LV2_ATOM__eventTransfer); uris->eg_applySample = map->map(map->handle, APPLY_SAMPLE_URI); uris->eg_file = map->map(map->handle, FILE_URI); uris->eg_freeSample = map->map(map->handle, FREE_SAMPLE_URI); uris->midi_Event = map->map(map->handle, MIDI_EVENT_URI); - uris->msg_Set = map->map(map->handle, LV2_MESSAGE_Set); - uris->msg_body = map->map(map->handle, LV2_MESSAGE_body); - uris->state_Path = map->map(map->handle, LV2_STATE_PATH_URI); + uris->msg_Set = map->map(map->handle, LV2_MESSAGE__Set); + uris->msg_body = map->map(map->handle, LV2_MESSAGE__body); } static inline bool @@ -64,15 +64,45 @@ is_object_type(const SamplerURIs* uris, LV2_URID type) || type == uris->atom_Blank; } +static inline LV2_Atom* +write_set_filename_msg(LV2_Atom_Forge* forge, + const SamplerURIs* uris, + const char* filename, + const size_t filename_len) +{ + /* Send [ + * a msg:Set ; + * msg:body [ + * eg-sampler:filename </home/me/foo.wav> ; + * ] ; + * ] + */ + LV2_Atom_Forge_Frame set_frame; + LV2_Atom* set = (LV2_Atom*)lv2_atom_forge_blank( + forge, &set_frame, 1, uris->msg_Set); + + lv2_atom_forge_property_head(forge, uris->msg_body, 0); + LV2_Atom_Forge_Frame body_frame; + lv2_atom_forge_blank(forge, &body_frame, 2, 0); + + lv2_atom_forge_property_head(forge, uris->eg_file, 0); + lv2_atom_forge_path(forge, (const uint8_t*)filename, filename_len); + + lv2_atom_forge_pop(forge, &body_frame); + lv2_atom_forge_pop(forge, &set_frame); + + return set; +} + static inline const LV2_Atom* -get_msg_file_uri(const SamplerURIs* uris, - const LV2_Atom_Object* obj) +get_msg_file_path(const SamplerURIs* uris, + const LV2_Atom_Object* obj) { /* Message should look like this: * [ * a msg:Set ; * msg:body [ - * eg-sampler:file <file://hal/home/me/foo.wav> ; + * eg-sampler:file </home/me/foo.wav> ; * ] ; * ] */ @@ -94,15 +124,15 @@ get_msg_file_uri(const SamplerURIs* uris, return NULL; } - /* Get file URI from body. */ - const LV2_Atom* file_uri = NULL; - lv2_object_getv(body, uris->eg_file, &file_uri, 0); - if (!file_uri) { - fprintf(stderr, "Ignored set message with no file URI.\n"); + /* Get file path from body. */ + const LV2_Atom* file_path = NULL; + lv2_object_getv(body, uris->eg_file, &file_path, 0); + if (!file_path) { + fprintf(stderr, "Ignored set message with no file PATH.\n"); return NULL; } - return file_uri; + return file_path; } #endif /* SAMPLER_URIS_H */ |