From 90386cd6f49e2e9bfb11e7596ae6ce3ac51dfe16 Mon Sep 17 00:00:00 2001
From: David Robillard <d@drobilla.net>
Date: Fri, 29 May 2009 03:48:09 +0000
Subject: Fix reconnecting to engine via various protocols (inferred from user
 URI) in GUI. Separate HTTP client receiver and sender sanely.

git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@2048 a436a847-0d15-0410-975c-d299462d15a1
---
 src/client/HTTPClientReceiver.cpp | 63 ++++++++++++++++++++++++++-------------
 src/client/HTTPClientReceiver.hpp |  5 ++--
 src/client/HTTPEngineSender.cpp   | 28 +++++++++--------
 src/client/HTTPEngineSender.hpp   |  3 +-
 src/gui/ConnectWindow.cpp         | 50 ++++++++++++++++++++++---------
 5 files changed, 98 insertions(+), 51 deletions(-)

(limited to 'src')

diff --git a/src/client/HTTPClientReceiver.cpp b/src/client/HTTPClientReceiver.cpp
index 285e797c..b8229998 100644
--- a/src/client/HTTPClientReceiver.cpp
+++ b/src/client/HTTPClientReceiver.cpp
@@ -30,9 +30,13 @@ using namespace std;
 using namespace Raul;
 
 namespace Ingen {
+
 using namespace Serialisation;
+
 namespace Client {
 
+static SoupSession*        client_session  = NULL;
+static HTTPClientReceiver* client_receiver = NULL;
 
 HTTPClientReceiver::HTTPClientReceiver(
 		Shared::World*                     world,
@@ -41,15 +45,17 @@ HTTPClientReceiver::HTTPClientReceiver(
 	: _target(target)
 	, _world(world)
 	, _url(url)
-	, _session(NULL)
 {
 	start(false);
+	client_receiver = this;
 }
 
 
 HTTPClientReceiver::~HTTPClientReceiver()
 {
 	stop();
+	if (client_receiver == this)
+		client_receiver = NULL;
 }
 
 
@@ -65,7 +71,7 @@ HTTPClientReceiver::Listener::Listener(HTTPClientReceiver* receiver, const std::
 	string port_str = uri.substr(uri.find_last_of(":")+1);
 	int port = atoi(port_str.c_str());
 
-	cout << "HTTP listen URI: " << uri << " port: " << port << endl;
+	cout << "Client HTTP listen: " << uri << " (port " << port << ")" << endl;
 
 	struct sockaddr_in servaddr;
 
@@ -96,6 +102,28 @@ HTTPClientReceiver::Listener::Listener(HTTPClientReceiver* receiver, const std::
 	}
 }
 
+
+void
+HTTPClientReceiver::send(SoupMessage* msg)
+{
+	if (!client_session)
+		client_session = soup_session_sync_new();
+
+	soup_session_queue_message(client_session, msg, message_callback, client_receiver);
+}
+
+
+void
+HTTPClientReceiver::close_session()
+{
+	if (client_session) {
+		SoupSession* s = client_session;
+		client_session = NULL;
+		soup_session_abort(s);
+	}
+}
+
+
 void
 HTTPClientReceiver::update(const std::string& str)
 {
@@ -134,12 +162,20 @@ HTTPClientReceiver::Listener::_run()
 void
 HTTPClientReceiver::message_callback(SoupSession* session, SoupMessage* msg, void* ptr)
 {
+	if (ptr == NULL)
+		return;
+
 	HTTPClientReceiver* me = (HTTPClientReceiver*)ptr;
 	const string path = soup_message_get_uri(msg)->path;
 
 	/*cerr << "HTTP MESSAGE " << path << endl;
 	cerr << msg->response_body->data << endl;*/
 
+	if (msg->response_body->data == NULL) {
+		cerr << "EMPTY CLIENT MESSAGE" << endl;
+		return;
+	}
+
 	if (path == Path::root_uri) {
 		me->_target->response_ok(0);
 
@@ -199,31 +235,16 @@ HTTPClientReceiver::start(bool dump)
 		}
 	}
 
-	_session = soup_session_sync_new();
-	SoupMessage* msg;
-
-	msg = soup_message_new("GET", _url.c_str());
-	soup_session_queue_message(_session, msg, message_callback, this);
-
-	msg = soup_message_new("GET", (_url + "/plugins").c_str());
-	soup_session_queue_message(_session, msg, message_callback, this);
-
-	msg = soup_message_new("GET", (_url + "/patch").c_str());
-	soup_session_queue_message(_session, msg, message_callback, this);
-
-	msg = soup_message_new("GET", (_url + "/stream").c_str());
-	soup_session_queue_message(_session, msg, message_callback, this);
+	SoupMessage* msg = soup_message_new("GET", (_url + "/stream").c_str());
+	soup_session_queue_message(client_session, msg, message_callback, this);
 }
 
 
 void
 HTTPClientReceiver::stop()
 {
-	if (_session != NULL) {
-		//unregister_client();
-		soup_session_abort(_session);
-		_session = NULL;
-	}
+	//unregister_client();
+	close_session();
 }
 
 
diff --git a/src/client/HTTPClientReceiver.hpp b/src/client/HTTPClientReceiver.hpp
index a35215b6..6d589b3a 100644
--- a/src/client/HTTPClientReceiver.hpp
+++ b/src/client/HTTPClientReceiver.hpp
@@ -31,7 +31,6 @@
 namespace Ingen {
 namespace Client {
 
-
 class HTTPClientReceiver : public boost::noncopyable, public Raul::Deletable
 {
 public:
@@ -41,6 +40,9 @@ public:
 
 	~HTTPClientReceiver();
 
+	static void send(SoupMessage* msg);
+	static void close_session();
+
 	std::string uri() const { return _url; }
 
 	void start(bool dump);
@@ -70,7 +72,6 @@ private:
 
 	Shared::World*                   _world;
 	const std::string                _url;
-	SoupSession*                     _session;
 	SharedPtr<Serialisation::Parser> _parser;
 };
 
diff --git a/src/client/HTTPEngineSender.cpp b/src/client/HTTPEngineSender.cpp
index abf51a56..1d0cd846 100644
--- a/src/client/HTTPEngineSender.cpp
+++ b/src/client/HTTPEngineSender.cpp
@@ -21,6 +21,7 @@
 #include "redlandmm/Model.hpp"
 #include "module/World.hpp"
 #include "HTTPEngineSender.hpp"
+#include "HTTPClientReceiver.hpp"
 
 
 using namespace std;
@@ -46,15 +47,11 @@ HTTPEngineSender::~HTTPEngineSender()
 	soup_session_abort(_session);
 }
 
-
 void
 HTTPEngineSender::attach(int32_t ping_id, bool block)
 {
-	/*SoupMessage *msg;
-	msg = soup_message_new ("GET", _engine_url.c_str());
-	int status = soup_session_send_message (_session, msg);
-	cout << "STATUS: " << status << endl;
-	cout << "RESPONSE: " << msg->response_body->data << endl;*/
+	SoupMessage* msg = soup_message_new ("GET", _engine_url.c_str());
+	HTTPClientReceiver::send(msg);
 }
 
 
@@ -70,6 +67,8 @@ HTTPEngineSender::attach(int32_t ping_id, bool block)
 void
 HTTPEngineSender::register_client(ClientInterface* client)
 {
+	/*SoupMessage* msg = soup_message_new("GET", (_engine_url.str() + "/stream").c_str());
+	HTTPClientReceiver::send(msg);*/
 }
 
 
@@ -83,6 +82,8 @@ HTTPEngineSender::unregister_client(const URI& uri)
 void
 HTTPEngineSender::load_plugins()
 {
+	SoupMessage* msg = soup_message_new("GET", (_engine_url.str() + "/plugins").c_str());
+	HTTPClientReceiver::send(msg);
 }
 
 
@@ -108,12 +109,6 @@ HTTPEngineSender::quit()
 // Object commands
 
 
-void
-HTTPEngineSender::message_callback(SoupSession* session, SoupMessage* msg, void* ptr)
-{
-	cerr << "HTTP CALLBACK" << endl;
-}
-
 
 void
 HTTPEngineSender::put(const URI&                  uri,
@@ -216,30 +211,39 @@ HTTPEngineSender::set_property(const URI&  subject,
 void
 HTTPEngineSender::ping()
 {
+	SoupMessage* msg = soup_message_new("GET", "");
+	HTTPClientReceiver::send(msg);
 }
 
 
 void
 HTTPEngineSender::get(const URI& uri)
 {
+	SoupMessage* msg = soup_message_new("GET", uri.c_str());
+	HTTPClientReceiver::send(msg);
 }
 
 
 void
 HTTPEngineSender::request_property(const URI& object_path, const URI& key)
 {
+	cerr << "HTTP REQUEST PROPERTY" << endl;
 }
 
 
 void
 HTTPEngineSender::request_plugins()
 {
+	SoupMessage* msg = soup_message_new("GET", (_engine_url.str() + "/plugins").c_str());
+	HTTPClientReceiver::send(msg);
 }
 
 
 void
 HTTPEngineSender::request_all_objects()
 {
+	SoupMessage* msg = soup_message_new("GET", (_engine_url.str() + "/patch").c_str());
+	HTTPClientReceiver::send(msg);
 }
 
 
diff --git a/src/client/HTTPEngineSender.hpp b/src/client/HTTPEngineSender.hpp
index b5f8cfa5..60b8345e 100644
--- a/src/client/HTTPEngineSender.hpp
+++ b/src/client/HTTPEngineSender.hpp
@@ -31,6 +31,7 @@ namespace Shared { class World; }
 
 namespace Client {
 
+class HTTPClientReceiver;
 
 /* HTTP (via libsoup) interface to the engine.
  *
@@ -120,8 +121,6 @@ public:
 	void request_all_objects();
 
 protected:
-	static void message_callback(SoupSession* session, SoupMessage* msg, void* ptr);
-
 	SoupSession*    _session;
 	Redland::World& _world;
 	const Raul::URI _engine_url;
diff --git a/src/gui/ConnectWindow.cpp b/src/gui/ConnectWindow.cpp
index e68f020e..80ac0de3 100644
--- a/src/gui/ConnectWindow.cpp
+++ b/src/gui/ConnectWindow.cpp
@@ -31,6 +31,7 @@
 #include "engine/Driver.hpp"
 #ifdef HAVE_SOUP
 #include "client/HTTPClientReceiver.hpp"
+#include "client/HTTPEngineSender.hpp"
 #endif
 #ifdef HAVE_LIBLO
 #include "client/OSCClientReceiver.hpp"
@@ -164,30 +165,51 @@ ConnectWindow::connect(bool existing)
 
 	Ingen::Shared::World* world = App::instance().world();
 
-#ifdef HAVE_LIBLO
+#if defined(HAVE_LIBLO) || defined(HAVE_SOUP)
 	if (_mode == CONNECT_REMOTE) {
-		if (!existing) {
-			Raul::URI engine_url("http://localhost:16180");
-			if (_widgets_loaded) {
-				const std::string& url_str = _url_entry->get_text();
-				if (Raul::URI::is_valid(url_str))
-					engine_url = url_str;
-			}
-			world->engine = SharedPtr<EngineInterface>(new OSCEngineSender(engine_url));
+#ifdef HAVE_LIBLO
+		string uri = "osc.udp://localhost:16180";
+#else
+		string uri = "http://localhost:16180";
+#endif
+		if (_widgets_loaded) {
+			const std::string& user_uri = _url_entry->get_text();
+			if (Raul::URI::is_valid(user_uri))
+				uri = user_uri;
 		}
 
+		if (existing)
+			uri = world->engine->uri().str();
+
+		// Create client-side listener
 		SharedPtr<ThreadedSigClientInterface> tsci(new ThreadedSigClientInterface(1024));
 		SharedPtr<Raul::Deletable> client;
 
-		const string& uri = world->engine->uri().str();
-		const string& scheme = uri.substr(0, uri.find(":"));
+		string scheme = uri.substr(0, uri.find(":"));
+
+#ifdef HAVE_LIBLO
 		if (scheme == "osc.udp" || scheme == "osc.tcp")
-			client = SharedPtr<OSCClientReceiver>(new OSCClientReceiver(16181, tsci)); // FIXME: port
+			client = SharedPtr<OSCClientReceiver>(new OSCClientReceiver(16181, tsci));
+#endif
 #ifdef HAVE_SOUP
-		else if (scheme == "http")
+		if (scheme == "http")
 			client = SharedPtr<HTTPClientReceiver>(new HTTPClientReceiver(world, uri, tsci));
 #endif
 
+		if (!existing) {
+#ifdef HAVE_LIBLO
+			if (scheme == "osc.udp" || scheme == "osc.tcp")
+				world->engine = SharedPtr<EngineInterface>(new OSCEngineSender(uri));
+#endif
+#ifdef HAVE_SOUP
+			if (scheme == "http")
+				world->engine = SharedPtr<EngineInterface>(new HTTPEngineSender(world, uri));
+#endif
+		} else {
+			uri = world->engine->uri().str();
+			scheme = uri.substr(0, uri.find(":"));
+		}
+
 		App::instance().attach(tsci, client);
 		App::instance().register_callbacks();
 
@@ -220,7 +242,7 @@ ConnectWindow::connect(bool existing)
 		}
 
 	} else
-#endif
+#endif // defined(HAVE_LIBLO) || defined(HAVE_SOUP)
 	if (_mode == INTERNAL) {
 		if ( ! world->local_engine) {
 			assert(_new_engine);
-- 
cgit v1.2.1