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