| @@ -369,7 +369,7 @@ const CarlaCachedPluginInfo* carla_get_cached_plugin_info(PluginType ptype, uint | |||
| // features | |||
| info.hints = 0x0; | |||
| if (lilvPlugin.get_uis().size() > 0) | |||
| if (lilvPlugin.get_uis().size() > 0 || lilvPlugin.get_modgui_resources_directory().as_uri() != nullptr) | |||
| info.hints |= CB::PLUGIN_HAS_CUSTOM_UI; | |||
| { | |||
| @@ -1699,6 +1699,27 @@ lilv_ui_get_binary_uri(const LilvUI* ui); | |||
| /** | |||
| Custom calls | |||
| */ | |||
| LILV_API LilvNode* | |||
| lilv_plugin_get_modgui_resources_directory(const LilvPlugin* plugin); | |||
| LILV_API LilvNode* | |||
| lilv_plugin_get_modgui_stylesheet(const LilvPlugin* plugin); | |||
| LILV_API LilvNode* | |||
| lilv_plugin_get_modgui_icon_template(const LilvPlugin* plugin); | |||
| LILV_API LilvNode* | |||
| lilv_plugin_get_modgui_settings_template(const LilvPlugin* plugin); | |||
| LILV_API LilvNode* | |||
| lilv_plugin_get_modgui_template_data(const LilvPlugin* plugin); | |||
| LILV_API LilvNode* | |||
| lilv_plugin_get_modgui_screenshot(const LilvPlugin* plugin); | |||
| LILV_API LilvNode* | |||
| lilv_plugin_get_modgui_thumbnail(const LilvPlugin* plugin); | |||
| LILV_API const LilvNodes* | |||
| lilv_ui_get_supported_features(const LilvUI* ui); | |||
| @@ -234,6 +234,13 @@ struct Plugin { | |||
| LILV_WRAP0(Nodes, plugin, get_extension_data); | |||
| LILV_WRAP0(UIs, plugin, get_uis); | |||
| LILV_WRAP1(Nodes, plugin, get_related, Node, type); | |||
| LILV_WRAP0(Node, plugin, get_modgui_resources_directory); | |||
| LILV_WRAP0(Node, plugin, get_modgui_stylesheet); | |||
| LILV_WRAP0(Node, plugin, get_modgui_icon_template); | |||
| LILV_WRAP0(Node, plugin, get_modgui_settings_template); | |||
| LILV_WRAP0(Node, plugin, get_modgui_template_data); | |||
| LILV_WRAP0(Node, plugin, get_modgui_screenshot); | |||
| LILV_WRAP0(Node, plugin, get_modgui_thumbnail); | |||
| inline Port get_port_by_index(unsigned index) { | |||
| return Port(me, lilv_plugin_get_port_by_index(me, index)); | |||
| @@ -31,6 +31,7 @@ | |||
| #define NS_DOAP (const uint8_t*)"http://usefulinc.com/ns/doap#" | |||
| #define NS_FOAF (const uint8_t*)"http://xmlns.com/foaf/0.1/" | |||
| #define NS_MOD (const uint8_t*)"http://portalmod.com/ns/modgui#" | |||
| /** Ownership of `uri` is taken */ | |||
| LilvPlugin* | |||
| @@ -908,6 +909,131 @@ lilv_plugin_get_author_homepage(const LilvPlugin* plugin) | |||
| return NULL; | |||
| } | |||
| static const SordNode* | |||
| lilv_plugin_get_modgui(const LilvPlugin* p) | |||
| { | |||
| lilv_plugin_load_if_necessary(p); | |||
| SordNode* mod_gui = sord_new_uri( | |||
| p->world->world, NS_MOD "gui"); | |||
| SordIter* gui = lilv_world_query_internal( | |||
| p->world, | |||
| p->plugin_uri->node, | |||
| mod_gui, | |||
| NULL); | |||
| sord_node_free(p->world->world, mod_gui); | |||
| if (sord_iter_end(gui)) { | |||
| sord_iter_free(gui); | |||
| return NULL; | |||
| } | |||
| const SordNode* Gui = sord_iter_get_node(gui, SORD_OBJECT); | |||
| sord_iter_free(gui); | |||
| return Gui; | |||
| } | |||
| LILV_API LilvNode* | |||
| lilv_plugin_get_modgui_resources_directory(const LilvPlugin* plugin) | |||
| { | |||
| const SordNode* modgui = lilv_plugin_get_modgui(plugin); | |||
| if (modgui) { | |||
| SordWorld* sworld = plugin->world->world; | |||
| SordNode* modgui_res = sord_new_uri(sworld, NS_MOD "resourcesDirectory"); | |||
| LilvNode* ret = lilv_plugin_get_one(plugin, modgui, modgui_res); | |||
| sord_node_free(sworld, modgui_res); | |||
| return ret; | |||
| } | |||
| return NULL; | |||
| } | |||
| LILV_API LilvNode* | |||
| lilv_plugin_get_modgui_stylesheet(const LilvPlugin* plugin) | |||
| { | |||
| const SordNode* modgui = lilv_plugin_get_modgui(plugin); | |||
| if (modgui) { | |||
| SordWorld* sworld = plugin->world->world; | |||
| SordNode* modgui_style = sord_new_uri(sworld, NS_MOD "stylesheet"); | |||
| LilvNode* ret = lilv_plugin_get_one(plugin, modgui, modgui_style); | |||
| sord_node_free(sworld, modgui_style); | |||
| return ret; | |||
| } | |||
| return NULL; | |||
| } | |||
| LILV_API LilvNode* | |||
| lilv_plugin_get_modgui_icon_template(const LilvPlugin* plugin) | |||
| { | |||
| const SordNode* modgui = lilv_plugin_get_modgui(plugin); | |||
| if (modgui) { | |||
| SordWorld* sworld = plugin->world->world; | |||
| SordNode* modgui_tmpl = sord_new_uri(sworld, NS_MOD "iconTemplate"); | |||
| LilvNode* ret = lilv_plugin_get_one(plugin, modgui, modgui_tmpl); | |||
| sord_node_free(sworld, modgui_tmpl); | |||
| return ret; | |||
| } | |||
| return NULL; | |||
| } | |||
| LILV_API LilvNode* | |||
| lilv_plugin_get_modgui_settings_template(const LilvPlugin* plugin) | |||
| { | |||
| const SordNode* modgui = lilv_plugin_get_modgui(plugin); | |||
| if (modgui) { | |||
| SordWorld* sworld = plugin->world->world; | |||
| SordNode* modgui_tmpl = sord_new_uri(sworld, NS_MOD "settingsTemplate"); | |||
| LilvNode* ret = lilv_plugin_get_one(plugin, modgui, modgui_tmpl); | |||
| sord_node_free(sworld, modgui_tmpl); | |||
| return ret; | |||
| } | |||
| return NULL; | |||
| } | |||
| LILV_API LilvNode* | |||
| lilv_plugin_get_modgui_template_data(const LilvPlugin* plugin) | |||
| { | |||
| const SordNode* modgui = lilv_plugin_get_modgui(plugin); | |||
| if (modgui) { | |||
| SordWorld* sworld = plugin->world->world; | |||
| SordNode* modgui_tmpl = sord_new_uri(sworld, NS_MOD "templateData"); | |||
| LilvNode* ret = lilv_plugin_get_one(plugin, modgui, modgui_tmpl); | |||
| sord_node_free(sworld, modgui_tmpl); | |||
| return ret; | |||
| } | |||
| return NULL; | |||
| } | |||
| LILV_API LilvNode* | |||
| lilv_plugin_get_modgui_screenshot(const LilvPlugin* plugin) | |||
| { | |||
| const SordNode* modgui = lilv_plugin_get_modgui(plugin); | |||
| if (modgui) { | |||
| SordWorld* sworld = plugin->world->world; | |||
| SordNode* modgui_scr = sord_new_uri(sworld, NS_MOD "screenshot"); | |||
| LilvNode* ret = lilv_plugin_get_one(plugin, modgui, modgui_scr); | |||
| sord_node_free(sworld, modgui_scr); | |||
| return ret; | |||
| } | |||
| return NULL; | |||
| } | |||
| LILV_API LilvNode* | |||
| lilv_plugin_get_modgui_thumbnail(const LilvPlugin* plugin) | |||
| { | |||
| const SordNode* modgui = lilv_plugin_get_modgui(plugin); | |||
| if (modgui) { | |||
| SordWorld* sworld = plugin->world->world; | |||
| SordNode* modgui_thumb = sord_new_uri(sworld, NS_MOD "thumbnail"); | |||
| LilvNode* ret = lilv_plugin_get_one(plugin, modgui, modgui_thumb); | |||
| sord_node_free(sworld, modgui_thumb); | |||
| return ret; | |||
| } | |||
| return NULL; | |||
| } | |||
| LILV_API bool | |||
| lilv_plugin_is_replaced(const LilvPlugin* plugin) | |||
| { | |||
| @@ -221,6 +221,7 @@ typedef uint32_t LV2_Property; | |||
| #define LV2_UI_X11 7 | |||
| #define LV2_UI_EXTERNAL 8 | |||
| #define LV2_UI_OLD_EXTERNAL 9 | |||
| #define LV2_UI_MOD 10 | |||
| #define LV2_IS_UI_GTK2(x) ((x) == LV2_UI_GTK2) | |||
| #define LV2_IS_UI_GTK3(x) ((x) == LV2_UI_GTK3) | |||
| @@ -231,6 +232,7 @@ typedef uint32_t LV2_Property; | |||
| #define LV2_IS_UI_X11(x) ((x) == LV2_UI_X11) | |||
| #define LV2_IS_UI_EXTERNAL(x) ((x) == LV2_UI_EXTERNAL) | |||
| #define LV2_IS_UI_OLD_EXTERNAL(x) ((x) == LV2_UI_OLD_EXTERNAL) | |||
| #define LV2_IS_UI_MOD(x) ((x) == LV2_UI_MOD) | |||
| // Plugin Types | |||
| #define LV2_PLUGIN_DELAY 0x000001 | |||
| @@ -92,6 +92,7 @@ | |||
| #define NS_rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |||
| #define NS_rdfs "http://www.w3.org/2000/01/rdf-schema#" | |||
| #define NS_llmm "http://ll-plugins.nongnu.org/lv2/ext/midimap#" | |||
| #define NS_mod "http://portalmod.com/ns/modgui#" | |||
| #define LV2_MIDI_Map__CC "http://ll-plugins.nongnu.org/lv2/namespace#CC" | |||
| #define LV2_MIDI_Map__NRPN "http://ll-plugins.nongnu.org/lv2/namespace#NRPN" | |||
| @@ -363,9 +364,7 @@ public: | |||
| rdf_type (new_uri(NS_rdf "type")), | |||
| rdfs_label (new_uri(NS_rdfs "label")), | |||
| needsInit(true) | |||
| { | |||
| } | |||
| needsInit(true) {} | |||
| static Lv2WorldClass& getInstance() | |||
| { | |||
| @@ -1265,11 +1264,13 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets) | |||
| // ------------------------------------------------------------------- | |||
| // Set Plugin UIs | |||
| { | |||
| const bool hasMODGui(lilvPlugin.get_modgui_resources_directory().as_uri() != nullptr); | |||
| Lilv::UIs lilvUIs(lilvPlugin.get_uis()); | |||
| if (lilvUIs.size() > 0) | |||
| if (lilvUIs.size() > 0 || hasMODGui) | |||
| { | |||
| rdfDescriptor->UICount = lilvUIs.size(); | |||
| rdfDescriptor->UICount = lilvUIs.size() + (hasMODGui ? 1 : 0); | |||
| rdfDescriptor->UIs = new LV2_RDF_UI[rdfDescriptor->UICount]; | |||
| uint32_t h = 0; | |||
| @@ -1389,6 +1390,29 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets) | |||
| lilv_nodes_free(const_cast<LilvNodes*>(lilvExtensionDataNodes.me)); | |||
| } | |||
| } | |||
| for (; hasMODGui;) | |||
| { | |||
| CARLA_SAFE_ASSERT_BREAK(h == rdfDescriptor->UICount-1); | |||
| LV2_RDF_UI* const rdfUI(&rdfDescriptor->UIs[h++]); | |||
| // ------------------------------------------------------- | |||
| // Set UI Type | |||
| rdfUI->Type = LV2_UI_MOD; | |||
| // ------------------------------------------------------- | |||
| // Set UI Information | |||
| if (const char* const resDir = lilvPlugin.get_modgui_resources_directory().as_uri()) | |||
| rdfUI->URI = carla_strdup(lilv_uri_to_path(resDir)); | |||
| if (rdfDescriptor->Bundle != nullptr) | |||
| rdfUI->Bundle = carla_strdup(rdfDescriptor->Bundle); | |||
| break; | |||
| } | |||
| } | |||
| lilv_nodes_free(const_cast<LilvNodes*>(lilvUIs.me)); | |||