5 #include "pluginlv2gui.h"
11 PluginLV2ChildGUI::PluginLV2ChildGUI()
16 PluginLV2ChildGUI::~PluginLV2ChildGUI()
21 void PluginLV2ChildGUI::run()
24 av.set_array_delete();
26 const char *exec_path = File::get_cinlib_path();
27 snprintf(arg, sizeof(arg), "%s/%s", exec_path, "lv2ui");
28 av.append(cstrdup(arg));
29 sprintf(arg, "%d", child_fd);
30 av.append(cstrdup(arg));
31 sprintf(arg, "%d", parent_fd);
32 av.append(cstrdup(arg));
34 execv(av[0], &av.values[0]);
35 fprintf(stderr, "execv failed: %s\n %m\n", av.values[0]);
36 av.remove_all_objects();
41 #define NS_EXT "http://lv2plug.in/ns/ext/"
43 PluginLV2GUI::PluginLV2GUI()
65 gtk_type = "http://lv2plug.in/ns/extensions/ui#GtkUI";
68 PluginLV2GUI::~PluginLV2GUI ()
71 if( world ) lilv_world_free(world);
74 void PluginLV2GUI::reset_gui()
76 if( inst ) lilv_instance_deactivate(inst);
77 if( uri_map ) { delete uri_map; uri_map = 0; }
78 if( ext_data ) { delete ext_data; ext_data = 0; }
79 if( inst ) { lilv_instance_free(inst); inst = 0; }
80 if( sinst ) { suil_instance_free(sinst); sinst = 0; }
81 if( ui_host ) { suil_host_free(ui_host); ui_host = 0; }
82 if( uis ) { lilv_uis_free(uis); uis = 0; }
83 if( lv2_InputPort ) { lilv_node_free(lv2_InputPort); lv2_InputPort = 0; }
84 if( lv2_ControlPort ) { lilv_node_free(lv2_ControlPort); lv2_ControlPort = 0; }
85 ui_features.remove_all_objects();
86 uri_table.remove_all_objects();
88 config.remove_all_objects();
91 int PluginLV2GUI::init_gui(const char *path)
95 world = lilv_world_new();
97 printf("lv2_gui: lilv_world_new failed");
100 lilv_world_load_all(world);
101 LilvNode *uri = lilv_new_uri(world, path);
103 printf("lv2_gui: lilv_new_uri(%s) failed", path);
107 const LilvPlugins *all_plugins = lilv_world_get_all_plugins(world);
108 lilv = lilv_plugins_get_by_uri(all_plugins, uri);
111 printf("lv2_gui: lilv_plugins_get_by_uriPlugin(%s) failed", path);
115 LilvNode *name = lilv_plugin_get_name(lilv);
116 const char *nm = lilv_node_as_string(name);
117 snprintf(title,sizeof(title),"L2_%s",nm);
118 lilv_node_free(name);
120 config.init_lv2(lilv);
122 lv2_InputPort = lilv_new_uri(world, LV2_CORE__InputPort);
123 lv2_ControlPort = lilv_new_uri(world, LV2_CORE__ControlPort);
125 for( int i=0; i<config.nb_ports; ++i ) {
126 const LilvPort *lp = lilv_plugin_get_port_by_index(lilv, i);
127 if( lilv_port_is_a(lilv, lp, lv2_InputPort) &&
128 lilv_port_is_a(lilv, lp, lv2_ControlPort) ) {
129 config.append(new PluginLV2Client_Opt(&config, i));
133 uri_map = new LV2_URI_Map_Feature();
134 uri_map->callback_data = (LV2_URI_Map_Callback_Data)this;
135 uri_map->uri_to_id = uri_to_id;
136 ui_features.append(new Lv2Feature(NS_EXT "uri-map", uri_map));
137 map.handle = (void*)&uri_table;
138 map.map = uri_table_map;
139 ui_features.append(new Lv2Feature(LV2_URID__map, &map));
140 unmap.handle = (void*)&uri_table;
141 unmap.unmap = uri_table_unmap;
142 ui_features.append(new Lv2Feature(LV2_URID__unmap, &unmap));
143 ui_features.append(0);
145 int sample_rate = 64; // cant be too low
146 inst = lilv_plugin_instantiate(lilv, sample_rate, ui_features);
148 printf("lv2_gui: lilv_plugin_instantiate failed: %s\n", title);
152 uis = lilv_plugin_get_uis(lilv);
154 LilvNode *gui_type = lilv_new_uri(world, gtk_type);
155 LILV_FOREACH(uis, i, uis) {
156 const LilvUI *gui = lilv_uis_get(uis, i);
157 if( lilv_ui_is_supported(gui, suil_ui_supported, gui_type, &ui_type)) {
162 lilv_node_free(gui_type);
165 ui = lilv_uis_get(uis, lilv_uis_begin(uis));
167 printf("lv2_gui: init_ui failed: %s\n", title);
171 lilv_instance_activate(inst);
175 void PluginLV2GUI::update_value(int idx, uint32_t bfrsz, uint32_t typ, const void *bfr)
177 if( idx >= config.nb_ports ) return;
178 for( int i=0, sz=config.size(); i<sz; ++i ) {
179 PluginLV2Client_Opt *opt = config[i];
180 if( opt->idx == idx ) {
181 opt->set_value(*(const float*)bfr);
182 //printf("set %s = %f\n", opt->get_symbol(), opt->get_value());
188 void PluginLV2GUI::write_from_ui(void *the, uint32_t idx,
189 uint32_t bfrsz, uint32_t typ, const void *bfr)
191 ((PluginLV2GUI*)the)->update_value(idx, bfrsz, typ, bfr);
195 uint32_t PluginLV2GUI::port_index(void* obj, const char* sym)
197 PluginLV2GUI *the = (PluginLV2GUI*)obj;
198 for( int i=0, sz=the->config.size(); i<sz; ++i ) {
199 PluginLV2Client_Opt *opt = the->config[i];
200 if( !strcmp(sym, opt->sym) ) return opt->idx;
205 void PluginLV2GUI::update_control(int idx, uint32_t bfrsz, uint32_t typ, const void *bfr)
207 if( !sinst || idx >= config.nb_ports ) return;
208 suil_instance_port_event(sinst, idx, bfrsz, typ, bfr);
213 void PluginLV2GUI::touch(void *obj, uint32_t pidx, bool grabbed)
215 PluginLV2GUI* the = (PluginLV2GUI*)obj;
217 if( idx >= the->config.nb_ports ) return;
218 printf("%s %s(%u)\n", (grabbed? _("press") : _("release")),
219 the->config.names[idx], idx);
223 uint32_t PluginLV2GUI::uri_to_id(LV2_URID_Map_Handle handle, const char *map, const char *uri)
225 return ((PluginLV2UriTable *)handle)->map(uri);
228 LV2_URID PluginLV2GUI::uri_table_map(LV2_URID_Map_Handle handle, const char *uri)
230 return ((PluginLV2UriTable *)handle)->map(uri);
233 const char *PluginLV2GUI::uri_table_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
235 return ((PluginLV2UriTable *)handle)->unmap(urid);
238 void PluginLV2GUI::lv2ui_instantiate(void *parent)
241 ui_host = suil_host_new(
242 PluginLV2GUI::write_from_ui,
243 PluginLV2GUI::port_index,
245 // suil_host_set_touch_func(ui_host,
246 // PluginLV2GUI::touch);
249 ui_features.remove();
250 LV2_Handle lilv_handle = lilv_instance_get_handle(inst);
251 ui_features.append(new Lv2Feature(NS_EXT "instance-access", lilv_handle));
252 const LV2_Descriptor *lilv_desc = lilv_instance_get_descriptor(inst);
253 ext_data = new LV2_Extension_Data_Feature();
254 ext_data->data_access = lilv_desc->extension_data;
255 ui_features.append(new Lv2Feature(LV2_DATA_ACCESS_URI, ext_data));
256 ui_features.append(new Lv2Feature(LV2_UI__parent, parent));
257 ui_features.append(new Lv2Feature(LV2_UI__idleInterface, 0));
258 ui_features.append(0);
260 const char* bundle_uri = lilv_node_as_uri(lilv_ui_get_bundle_uri(ui));
261 char* bundle_path = lilv_file_uri_parse(bundle_uri, NULL);
262 const char* binary_uri = lilv_node_as_uri(lilv_ui_get_binary_uri(ui));
263 char* binary_path = lilv_file_uri_parse(binary_uri, NULL);
264 sinst = suil_instance_new(ui_host, this, gtk_type,
265 lilv_node_as_uri(lilv_plugin_get_uri(lilv)),
266 lilv_node_as_uri(lilv_ui_get_uri(ui)),
267 lilv_node_as_uri(ui_type),
268 bundle_path, binary_path, ui_features);
270 lilv_free(binary_path);
271 lilv_free(bundle_path);
274 bool PluginLV2GUI::lv2ui_resizable()
276 if( !ui ) return false;
277 const LilvNode* s = lilv_ui_get_uri(ui);
278 LilvNode *p = lilv_new_uri(world, LV2_CORE__optionalFeature);
279 LilvNode *fs = lilv_new_uri(world, LV2_UI__fixedSize);
280 LilvNode *nrs = lilv_new_uri(world, LV2_UI__noUserResize);
281 LilvNodes *fs_matches = lilv_world_find_nodes(world, s, p, fs);
282 LilvNodes *nrs_matches = lilv_world_find_nodes(world, s, p, nrs);
283 lilv_nodes_free(nrs_matches);
284 lilv_nodes_free(fs_matches);
288 return !fs_matches && !nrs_matches;
291 int PluginLV2GUI::update_lv2(float *vals, int force)
294 float *ctls = (float *)config.ctls;
295 for( int i=0; i<config.size(); ++i ) {
296 int idx = config[i]->idx;
297 float val = vals[idx];
298 if( !force && ctls[idx] == val ) continue;
299 update_control(idx, sizeof(val), 0, &val);
302 for( int i=0; i<config.nb_ports; ++i ) ctls[i] = vals[i];
306 #endif /* HAVE_LV2UI */