From d1ba04724f0bfbed18690316dbe5eb977a131733 Mon Sep 17 00:00:00 2001
From: David Robillard <d@drobilla.net>
Date: Sun, 23 Sep 2007 02:03:41 +0000
Subject: Working LV2 UI control setting (including MIDI). Klaviatur
 (ll-plugins virtual keyboard) is now fully functional inside Ingen.

git-svn-id: http://svn.drobilla.net/lad/ingen@766 a436a847-0d15-0410-975c-d299462d15a1
---
 src/libs/client/ConnectionModel.hpp  |  8 ++--
 src/libs/client/DeprecatedLoader.cpp |  2 +-
 src/libs/client/NodeModel.cpp        |  9 +++-
 src/libs/client/OSCEngineSender.cpp  | 86 +++++++++++++++++++++++++++---------
 src/libs/client/OSCEngineSender.hpp  |  4 ++
 src/libs/client/PluginModel.cpp      | 42 +++++++++++-------
 src/libs/client/PluginModel.hpp      |  4 +-
 src/libs/client/PortModel.hpp        |  6 +--
 8 files changed, 113 insertions(+), 48 deletions(-)

(limited to 'src/libs/client')

diff --git a/src/libs/client/ConnectionModel.hpp b/src/libs/client/ConnectionModel.hpp
index 59dacae7..304db2b7 100644
--- a/src/libs/client/ConnectionModel.hpp
+++ b/src/libs/client/ConnectionModel.hpp
@@ -19,11 +19,11 @@
 #define CONNECTIONMODEL_H
 
 #include <string>
+#include <list>
 #include <raul/Path.hpp>
 #include <raul/SharedPtr.hpp>
 #include "PortModel.hpp"
 #include <cassert>
-using std::string;
 
 namespace Ingen {
 namespace Client {
@@ -59,8 +59,8 @@ private:
 	void set_src_port(SharedPtr<PortModel> port) { _src_port = port; _src_port_path = port->path(); }
 	void set_dst_port(SharedPtr<PortModel> port) { _dst_port = port; _dst_port_path = port->path(); }
 
-	void src_port_path(const string& s) { _src_port_path = s; }
-	void dst_port_path(const string& s) { _dst_port_path = s; }
+	void src_port_path(const std::string& s) { _src_port_path = s; }
+	void dst_port_path(const std::string& s) { _dst_port_path = s; }
 
 	Path                 _src_port_path; ///< Only used if _src_port == NULL
 	Path                 _dst_port_path; ///< Only used if _dst_port == NULL
@@ -68,7 +68,7 @@ private:
 	SharedPtr<PortModel> _dst_port;
 };
 
-typedef list<SharedPtr<ConnectionModel> > ConnectionList;
+typedef std::list<SharedPtr<ConnectionModel> > ConnectionList;
 
 
 } // namespace Client
diff --git a/src/libs/client/DeprecatedLoader.cpp b/src/libs/client/DeprecatedLoader.cpp
index 9cff9422..ce536b4f 100644
--- a/src/libs/client/DeprecatedLoader.cpp
+++ b/src/libs/client/DeprecatedLoader.cpp
@@ -259,7 +259,7 @@ DeprecatedLoader::load_patch(const Glib::ustring&  filename,
 				list<ControlModel>::const_iterator i = pm->controls().begin();
 				for ( ; i != pm->controls().end(); ++i) {
 					const float value = i->value();
-					_engine->set_port_value(i->port_path(), sizeof(float), &value);
+					_engine->set_port_value(i->port_path(), "ingen:control", sizeof(float), &value);
 				}
 			} else {
 				cerr << "WARNING: Unknown preset: \"" << pm->name() << endl;
diff --git a/src/libs/client/NodeModel.cpp b/src/libs/client/NodeModel.cpp
index 8c5892e7..2816c7fa 100644
--- a/src/libs/client/NodeModel.cpp
+++ b/src/libs/client/NodeModel.cpp
@@ -48,7 +48,13 @@ NodeModel::~NodeModel()
 void
 NodeModel::remove_port(SharedPtr<PortModel> port)
 {
-	_ports.remove(port);
+	// FIXME: slow
+	for (PortModelList::iterator i = _ports.begin(); i != _ports.end(); ++i) {
+		if ((*i) == port) {
+			_ports.erase(i);
+			break;
+		}
+	}
 	signal_removed_port.emit(port);
 }
 
@@ -56,6 +62,7 @@ NodeModel::remove_port(SharedPtr<PortModel> port)
 void
 NodeModel::remove_port(const Path& port_path)
 {
+	// FIXME: slow
 	for (PortModelList::iterator i = _ports.begin(); i != _ports.end(); ++i) {
 		if ((*i)->path() == port_path) {
 			_ports.erase(i);
diff --git a/src/libs/client/OSCEngineSender.cpp b/src/libs/client/OSCEngineSender.cpp
index 90f27676..cadb962c 100644
--- a/src/libs/client/OSCEngineSender.cpp
+++ b/src/libs/client/OSCEngineSender.cpp
@@ -351,61 +351,103 @@ OSCEngineSender::disconnect_all(const string& node_path)
 
 void
 OSCEngineSender::set_port_value(const string& port_path,
+                                const string& type_uri,
                                 uint32_t      data_size,
                                 const void*   data)
 {
 	assert(_engine_addr);
-	assert(data_size == 4);
-	lo_send(_engine_addr, "/ingen/set_port_value", "isf",
-		next_id(),
-		port_path.c_str(),
-		*(float*)data);
+	if (type_uri == "ingen:control") {
+		assert(data_size == 4);
+		lo_send(_engine_addr, "/ingen/set_port_value", "isf",
+				next_id(),
+				port_path.c_str(),
+				*(float*)data);
+	} else {
+		lo_blob b = lo_blob_new(data_size, data);
+		lo_send(_engine_addr, "/ingen/set_port_value", "isb",
+				next_id(),
+				port_path.c_str(),
+				b);
+		lo_blob_free(b);
+	}
 }
 
 
 void
 OSCEngineSender::set_port_value(const string& port_path,
+                                const string& type_uri,
                                 uint32_t      voice,
                                 uint32_t      data_size,
                                 const void*   data)
 {
 	assert(_engine_addr);
-	assert(data_size == 4);
-	lo_send(_engine_addr, "/ingen/set_port_value", "isif",
-		next_id(),
-		port_path.c_str(),
-		voice,
-		*(float*)data);
+	if (type_uri == "ingen:control") {
+		assert(data_size == 4);
+		lo_send(_engine_addr, "/ingen/set_port_value", "isf",
+				next_id(),
+				port_path.c_str(),
+				*(float*)data);
+	} else {
+		lo_blob b = lo_blob_new(data_size, data);
+		lo_send(_engine_addr, "/ingen/set_port_value", "isb",
+				next_id(),
+				port_path.c_str(),
+				b);
+		lo_blob_free(b);
+	}
 }
 
 
 void
 OSCEngineSender::set_port_value_immediate(const string& port_path,
+                                          const string& type_uri,
                                           uint32_t      data_size,
                                           const void*   data)
 {
 	assert(_engine_addr);
-	assert(data_size == 4);
-	lo_send(_engine_addr, "/ingen/set_port_value_immediate", "isf",
-		next_id(),
-		port_path.c_str(),
-		*(float*)data);
+
+	if (type_uri == "ingen:control") {
+		assert(data_size == 4);
+		lo_send(_engine_addr, "/ingen/set_port_value_immediate", "isf",
+				next_id(),
+				port_path.c_str(),
+				*(float*)data);
+	} else {
+		lo_blob b = lo_blob_new(data_size, data);
+		lo_send(_engine_addr, "/ingen/set_port_value_immediate", "isb",
+				next_id(),
+				port_path.c_str(),
+				b);
+		lo_blob_free(b);
+	}
 }
 
 
 void
 OSCEngineSender::set_port_value_immediate(const string& port_path,
+                                          const string& type_uri,
                                           uint32_t      voice,
                                           uint32_t      data_size,
                                           const void*   data)
 {
 	assert(_engine_addr);
-	assert(data_size == 4);
-	lo_send(_engine_addr, "/ingen/set_port_value_immediate", "isif",
-		next_id(),
-		port_path.c_str(),
-		voice,
-		*(float*)data);
+	
+	if (type_uri == "ingen:control") {
+		assert(data_size == 4);
+		lo_send(_engine_addr, "/ingen/set_port_value_immediate", "isif",
+				next_id(),
+				port_path.c_str(),
+				voice,
+				*(float*)data);
+	} else {
+		lo_blob b = lo_blob_new(data_size, data);
+		lo_send(_engine_addr, "/ingen/set_port_value_immediate", "isib",
+				next_id(),
+				port_path.c_str(),
+				voice,
+				b);
+		lo_blob_free(b);
+	}
 }
 
 
diff --git a/src/libs/client/OSCEngineSender.hpp b/src/libs/client/OSCEngineSender.hpp
index bdaf8337..c91dfbbd 100644
--- a/src/libs/client/OSCEngineSender.hpp
+++ b/src/libs/client/OSCEngineSender.hpp
@@ -112,19 +112,23 @@ public:
 	void disconnect_all(const string& node_path);
 
 	void set_port_value(const string& port_path,
+	                    const string& type_uri,
 	                    uint32_t      data_size,
 	                    const void*   data);
 
 	void set_port_value(const string& port_path,
+	                    const string& type_uri,
 	                    uint32_t      voice,
 	                    uint32_t      data_size,
 	                    const void*   data);
 	
 	void set_port_value_immediate(const string& port_path,
+	                              const string& type_uri,
 	                              uint32_t      data_size,
 	                              const void*   data);
 	
 	void set_port_value_immediate(const string& port_path,
+	                              const string& type_uri,
 	                              uint32_t      voice,
 	                              uint32_t      data_size,
 	                              const void*   data);
diff --git a/src/libs/client/PluginModel.cpp b/src/libs/client/PluginModel.cpp
index 6fb7e95a..cfe6d547 100644
--- a/src/libs/client/PluginModel.cpp
+++ b/src/libs/client/PluginModel.cpp
@@ -20,6 +20,7 @@
 #include "PluginModel.hpp"
 #include "PatchModel.hpp"
 
+using Ingen::Shared::EngineInterface;
 
 namespace Ingen {
 namespace Client {
@@ -53,25 +54,29 @@ PluginModel::default_node_name(SharedPtr<PatchModel> parent)
 }
 
 
+struct NodeController {
+	EngineInterface* engine;
+	NodeModel*       node;
+};
+
+
 void
 lv2_ui_write(LV2UI_Controller controller,
-              uint32_t        port,
-              uint32_t        buffer_size,
-              const void*     buffer)
+             uint32_t         port,
+             uint32_t         buffer_size,
+             const void*      buffer)
 {
-	cerr << "********* LV2 UI WRITE port " << port << ", size "
-		<< buffer_size << endl;
-	for (uint32_t i=0; i < buffer_size; ++i) {
-		fprintf(stderr, "( %X )", *((uint8_t*)buffer + i));
-	}
-	fprintf(stderr, "\n");
+	NodeController* nc = (NodeController*)controller;
+
+	nc->engine->set_port_value_immediate(nc->node->ports()[port]->path(),
+			"ingen:midi", buffer_size, buffer);
 }
 
 
 void
 lv2_ui_command(LV2UI_Controller   controller,
-                uint32_t           argc,
-                const char* const* argv)
+               uint32_t           argc,
+               const char* const* argv)
 {
 	cerr << "********* LV2 UI COMMAND" << endl;
 }
@@ -79,7 +84,7 @@ lv2_ui_command(LV2UI_Controller   controller,
 	
 void
 lv2_ui_program_change(LV2UI_Controller controller,
-                       unsigned char    program)
+                      unsigned char    program)
 {
 	cerr << "********* LV2 UI PROGRAM CHANGE" << endl;
 }
@@ -87,8 +92,8 @@ lv2_ui_program_change(LV2UI_Controller controller,
 	
 void
 lv2_ui_program_save(LV2UI_Controller controller,
-                     unsigned char    program,
-                     const char*      name)
+                    unsigned char    program,
+                    const char*      name)
 {
 	cerr << "********* LV2 UI PROGRAM SAVE" << endl;
 }
@@ -96,12 +101,17 @@ lv2_ui_program_save(LV2UI_Controller controller,
 	
 #ifdef HAVE_SLV2
 SLV2UIInstance
-PluginModel::ui()
+PluginModel::ui(EngineInterface* engine, NodeModel* node)
 {
 	if (_type != LV2)
 		return NULL;
 
 	Glib::Mutex::Lock(_rdf_world->mutex());
+
+	// FIXME: leak
+	NodeController* controller = new NodeController();
+	controller->engine = engine;
+	controller->node = node;
 	
 	SLV2UIInstance ret = NULL;
 
@@ -129,7 +139,7 @@ PluginModel::ui()
 				slv2_values_get_at(ui, 0),
 				lv2_ui_write, lv2_ui_command,
 				lv2_ui_program_change, lv2_ui_program_save,
-				NULL, NULL);
+				controller, NULL);
 	}
 
 	slv2_values_free(ui);
diff --git a/src/libs/client/PluginModel.hpp b/src/libs/client/PluginModel.hpp
index bcf2645c..444ed666 100644
--- a/src/libs/client/PluginModel.hpp
+++ b/src/libs/client/PluginModel.hpp
@@ -27,12 +27,14 @@
 #ifdef HAVE_SLV2
 #include <slv2/slv2.h>
 #endif
+#include "interface/EngineInterface.hpp"
 using std::string; using std::cerr; using std::endl;
 
 namespace Ingen {
 namespace Client {
 
 class PatchModel;
+class NodeModel;
 
 
 /** Model for a plugin available for loading.
@@ -107,7 +109,7 @@ public:
 		_slv2_plugins = slv2_world_get_all_plugins(_slv2_world);
 	}
 
-	SLV2UIInstance ui();
+	SLV2UIInstance ui(Ingen::Shared::EngineInterface* engine, NodeModel* node);
 #endif
 
 	static void set_rdf_world(Raul::RDF::World& world) {
diff --git a/src/libs/client/PortModel.hpp b/src/libs/client/PortModel.hpp
index 6b49310b..80d5e524 100644
--- a/src/libs/client/PortModel.hpp
+++ b/src/libs/client/PortModel.hpp
@@ -21,12 +21,12 @@
 #include <cstdlib>
 #include <iostream>
 #include <string>
-#include <list>
+#include <vector>
 #include <sigc++/sigc++.h>
 #include "ObjectModel.hpp"
 #include <raul/SharedPtr.hpp>
 #include <raul/Path.hpp>
-using std::string; using std::list; using std::cerr; using std::endl;
+using std::string; using std::vector; using std::cerr; using std::endl;
 
 namespace Ingen {
 namespace Client {
@@ -96,7 +96,7 @@ private:
 	size_t    _connections;
 };
 
-typedef list<SharedPtr<PortModel> > PortModelList;
+typedef vector<SharedPtr<PortModel> > PortModelList;
 
 
 } // namespace Client
-- 
cgit v1.2.1