I send a patch because I still need to refactor, review clean up and check the semantics (to do after sleep...). But it works! With this I will not need specifics osc receivers for Blender!! :-)

Using a static map to manage the needed servers by ports, and processings instances (the first configured processing on that port create the server, the last one remove it)


Cheers,
Natanael.
Index: CLAM/plugins/osc/LibloSource.hxx
===================================================================
--- CLAM/plugins/osc/LibloSource.hxx	(revision 11977)
+++ CLAM/plugins/osc/LibloSource.hxx	(working copy)
@@ -6,6 +6,7 @@
 #include <string>
 #include <cmath>
 #include <algorithm>
+#include <map>
 
 #include "lo/lo.h"
 #ifdef GetClassName // windows.h introduces that
@@ -40,15 +41,24 @@
 public:
 	LibloSource(const Config& config = Config()) 
 		: _serverThread(0)
+		, _typespec("fff")
+		, _oscPath(config.GetOscPath())
+		, _methodSetted(false)
 	{
-		_serverThreadIsRunning=false;
+//		_serverThreadIsRunning=false;
 		Configure( config );
 	}
 	
 	~LibloSource()
 	{
-		if (_serverThreadIsRunning)
-		{	
+		std::string port = _config.GetServerPort();
+		if (_methodSetted)
+		{
+			lo_server_thread_del_method(_serverThread,_oscPath.c_str(),_typespec.c_str()); //delete it
+			DecInstance(port.c_str());
+		}
+		if (IsPortUsed(port.c_str()) && GetInstances(port.c_str())==0) // if was the last instance
+		{
 			std::cout <<"LibloSource: Shutting down the server..."<<std::endl;
 			lo_server_thread_free(_serverThread);
 		}
@@ -89,48 +99,75 @@
 			nOutputs = 1;
 		}
 		// multi-port names share user-configured identifier
-		std::string path=_config.GetOscPath();
-		std::replace(path.begin(),path.end(),'/','_');
-		_outControls.Resize(nOutputs,path, this);
+		std::string oscPath=_config.GetOscPath();
+		std::replace(oscPath.begin(),oscPath.end(),'/','_');
+		_outControls.Resize(nOutputs,oscPath, this);
+		std::string port = _config.GetServerPort();
 
-		if (_serverThreadIsRunning)
-		{	
-//			return true;
-			std::cout <<"LibloSource: Restarting the server..."<<std::endl;
-			lo_server_thread_free(_serverThread);
-			_serverThreadIsRunning=false;
-		}
-
-		/* start a new server on port 7770 */
-		if (_config.GetServerPort()=="")
+		/* not defined port */
+		if (port=="")
 		{
 			std::cout << "LibloSource::ConcreteConfigure server NOT started -- default config" << std::endl;
 			return true;
 		}
 
-		std::cout << "Starting the server" << std::endl;
-		_serverThreadIsRunning=true;
-		const char * port = _config.GetServerPort().c_str();
-		std::cout << "LibloSource::ConcreteConfigure: STARTING the server. port " << port << std::endl;
-		_serverThread = lo_server_thread_new(port, error);
-		/* add method that will match any path and args */
-		lo_server_thread_add_method(_serverThread, NULL, NULL, generic_handler, this);
+		// if there are no servers on port
+		if (not IsPortUsed(port.c_str())) 
+			_serverThread = ServerStart(port.c_str(),this); // start new server
+		else 
+		{ // if exists server on port
+			_serverThread = (*ServersInstances().find(port)).second.thread;	
+			// if exists a previous method handler
+			if (_methodSetted)
+			{
+				lo_server_thread_del_method(_serverThread,_oscPath.c_str(),_typespec.c_str()); //delete it
+				DecInstance(port.c_str());
+			}
+			if (GetInstances(port.c_str())==0) // if was the last instance
+			{
+				std::cout <<"LibloSource: Restarting the server..."<<std::endl;
+				lo_server_thread_free(_serverThread);
+			}
+		}
 
+		// define processing callback catcher (floats, for now)
 		std::string typespecMask="";
 		for (int i=0;i<nOutputs;i++)
+			typespecMask+="f"; //add "f"s as arguments
+		_typespec=typespecMask;
+		_oscPath=_config.GetOscPath();
+
+		lo_server_thread_add_method(_serverThread, _oscPath.c_str(), _typespec.c_str(), controls_handler, this);
+		_methodSetted=true;
+		// add instance on map
+		IncInstance(port.c_str()); //,path,typespec
+		lo_server_thread_start(_serverThread);
+		return true; // Configuration ok
+	}
+
+	static lo_server_thread ServerStart(const char* port, void * parent)
+	{
+		if (IsPortUsed(port))
 		{
-			typespecMask+="f";
+			std::cout<<"WARNING: trying to start an existent server port!"<<std::endl;
+			ServersInstances().erase(ServersInstances().find(port));
 		}
-
-		lo_server_thread_add_method(_serverThread, _config.GetOscPath().c_str(), typespecMask.c_str(), controls_handler, this);
-
+		std::cout << "Starting the server" << std::endl;		
+		std::cout << "LibloSource::ConcreteConfigure: STARTING the server. port " << port << std::endl;
+		lo_server_thread serverThread = lo_server_thread_new(port, error);
+		ServerInstance server;
+		server.thread=serverThread;
+		server.nProcessings=0;
+		ServersInstances().insert(OscServersMap::value_type(port,server));
+		// common methods are not counted in map!:
+		/* add method that will match any path and args */
+		lo_server_thread_add_method(serverThread, NULL, NULL, generic_handler, parent);
 		/* add method that will match the path /quit with no args */
-		lo_server_thread_add_method(_serverThread, "/quit", "", quit_handler, this);
+		lo_server_thread_add_method(serverThread, "/quit", "", quit_handler, parent);
+		std::cout<<"number of servers: "<<ServersInstances().size()<<std::endl;
+		return serverThread;
+	}
 
-		lo_server_thread_start(_serverThread);
-
-		return true; // Configuration ok
-	}
 private:
 	static void error(int num, const char *m, const char *path);
 
@@ -143,9 +180,70 @@
 	static int quit_handler(const char *path, const char *types, lo_arg **argv, int argc,
 			 void *data, void *user_data);
 
-	bool _serverThreadIsRunning;
+
+	// server management related structs, methods, and attributes
+	typedef struct
+	{
+		lo_server_thread thread;
+		unsigned int nProcessings;
+	} ServerInstance;
+
+	// map key: port
+	typedef std::map<std::string,ServerInstance> OscServersMap;
+	static OscServersMap & ServersInstances()
+	{
+		static OscServersMap sOscServersMap;
+		return sOscServersMap;
+	}
+	static bool IsPortUsed(const char* port)
+	{
+		return ( ServersInstances().find(port) != ServersInstances().end() );
+	}
+	static bool IncInstance(const char* port)
+	{
+		OscServersMap::iterator itServer=ServersInstances().find(port);
+		if (itServer==ServersInstances().end())
+			return false;
+		itServer->second.nProcessings++;
+		return true;
+	}
+	static bool DecInstance(const char* port)
+	{
+		OscServersMap::iterator itServer=ServersInstances().find(port);
+		if (itServer==ServersInstances().end())
+			return false;
+		itServer->second.nProcessings--;
+		return true;
+	}
+	static const unsigned int GetInstances (const char* port)
+	{
+		OscServersMap::const_iterator itServer=ServersInstances().find(port);
+		if (itServer==ServersInstances().end())
+			return 0;
+		return itServer->second.nProcessings;
+	}
+	static bool RemoveServer(const char* port)
+	{
+		OscServersMap::iterator itServer=ServersInstances().find(port);
+		if (itServer==ServersInstances().end())
+		{
+			std::cout<<"LibloSource: can't remove an inexistent server"<<std::endl;
+			return false;
+		}
+		if (itServer->second.nProcessings>0)
+		{
+			std::cout<<"LibloSource: can't remove an used server"<<std::endl;
+			return false;
+		}
+		ServersInstances().erase(itServer);
+		return true;
+	}
+
+	lo_server_thread _serverThread;
+	std::string _typespec;
+	std::string _oscPath;
+	bool _methodSetted;
 	
-	lo_server_thread _serverThread;
 	Config _config;
 	OutControlArray _outControls;
 };
_______________________________________________
Clam-devel mailing list
[email protected]
https://llistes.projectes.lafarga.org/cgi-bin/mailman/listinfo/clam-devel

Reply via email to