feature: Add SPIT-Source as is
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
idf_component_register(
|
||||
SRC_DIRS "src"
|
||||
INCLUDE_DIRS "include"
|
||||
)
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: MySPITApp.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 17. April 2019, 18:24
|
||||
*/
|
||||
|
||||
#ifndef MYSPITAPP_H
|
||||
#define MYSPITAPP_H
|
||||
|
||||
#include "SPIT_Client.h"
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
int main();
|
||||
|
||||
class MyApp : SPIT_ClientInterface {
|
||||
public:
|
||||
MyApp();
|
||||
virtual ~MyApp();
|
||||
|
||||
//Client's infos is set by the client
|
||||
static string s_ClientName;
|
||||
static string s_ClientProjectID;
|
||||
static string s_ClientProjectName;
|
||||
static int s_ClientDefaultFramesPerSecond;
|
||||
|
||||
void loadClientProject();
|
||||
|
||||
private:
|
||||
SPIT_Client* m_SPIT_Client; //pointer to an instance of the SPIT_Client, which do the main work for you
|
||||
|
||||
//MySPITApp client project infos they are transferred after the server send his project infos, see eventProjectReport
|
||||
string m_ClientProjectID; //can be an id or simple the project's name
|
||||
string m_ClientProjectName; //the name of the client's (this) project
|
||||
|
||||
//Server's info filled by eventConnectionStatus when SPIT_Client::CONNECTION_OK
|
||||
string m_ServerID;
|
||||
string m_ServerName;
|
||||
string m_ServerComputerName;
|
||||
int m_ServerStepTime;
|
||||
|
||||
//Server's project infos filled by eventProjectReport
|
||||
string m_ServerProjectID;
|
||||
string m_ServerProjectName;
|
||||
int m_ServerFramesPerSecond; //set when the server reports his project, see eventProjectReport
|
||||
|
||||
//Reconnect to the server when connection is lost see eventConnectionStatus and eventServerDetected
|
||||
bool m_FlagReconnect; //true = on eventServerDetected connect to the server identified by m_ServerID
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
//---------- SPIT_ClientInterface -------------
|
||||
string getClientProjectID(); //should return the client's project id, maybe the same as project name
|
||||
string getClientProjectName(); //should return the client's project name
|
||||
|
||||
//----- ServerAutoDetection -----
|
||||
void startServerAutoDetect(); //starts the autodetection of SPITServers in the local network area (see eventServerDetected)
|
||||
void stopServerAutoDetect(); //stopps the autodetection
|
||||
void eventServerDetected(const SAD_DetectedServer& p_DetectedServer); //a SPITServer is detected
|
||||
void eventServerLost(const SAD_DetectedServer& p_DetectedServer); //a prior detected SPITServer is lost
|
||||
|
||||
//----- Connection -----
|
||||
void eventConnectionStatus(string p_ServerID, string p_ServerComputerName, string p_ServerName, int p_ServerStepTime, int p_ConnectionStatus, int p_OldConnectionStatus);
|
||||
|
||||
//----- Project -----
|
||||
void eventProjectReport(string p_ProjectID, string p_ProjectName, int p_FramesPerSeoond);
|
||||
void eventProjectClosed(string p_ProjectID);
|
||||
|
||||
void eventStartProjectTransfer();
|
||||
void eventEndProjectTransfer();
|
||||
|
||||
|
||||
//----- SPITType -----
|
||||
|
||||
void eventSPITType(bool p_New, const SPITType& p_SPITType);
|
||||
void eventSPITTypeRemote(bool p_New, const SPITType& p_SPITType);
|
||||
void eventSPITTypeRemoved(const SPITType& p_SPITType);
|
||||
void eventSPITTypeRemoteRemoved(const SPITType& p_SPITType);
|
||||
|
||||
//----- SPITObject -----
|
||||
void eventSPITObject(bool p_New, const SPITType& p_SPITType, const SPITObject& p_SPITObject);
|
||||
void eventSPITObjectRemote(bool p_New, const SPITType& p_SPITType, const SPITObject& p_SPITObject);
|
||||
void eventSPITObjectRemoved(const SPITType& p_SPITType, const SPITObject& p_SPITObject);
|
||||
void eventSPITObjectRemoteRemoved(const SPITType& p_SPITType, const SPITObject& p_SPITObject);
|
||||
|
||||
//----- Play SPITObjects -----
|
||||
void eventPlay(string p_PlayerID, string p_PlayerName, char p_PlayerType, bool p_PlayerIsRunning, long long p_TimeFrames);
|
||||
void eventPlayObject(string p_PlayerID, bool p_Started, bool p_Stopped, const SPITType& p_SPITType, const SPITObject& p_SPITObject, const SPITPlayer::PlayObject& p_PlayObject);
|
||||
|
||||
|
||||
//----- Server changes status of one of his REMOTE SPITObjects -----
|
||||
//REMOTE only Server->Client RemoteObject's play status
|
||||
void eventPlayRemoteObjectStatus(const SPITType& p_SPITType, const SPITObject& p_SPITObject, long long p_FrameInsideObject, int p_Value);
|
||||
|
||||
void sendRemoteObject(string p_SPITObjectID, int p_Valueppm = 0, char p_ValueFlag = 0x00);
|
||||
//-----
|
||||
void testLiveShowRemote();
|
||||
|
||||
//------ User's options normally should not be used, the server is master of things ------
|
||||
public:
|
||||
//----- SPITType -----
|
||||
int removeSPITType(string p_SPITTypeID);
|
||||
int changeSPITType(SPITType* p_SPITType);
|
||||
|
||||
//----- SPITObject -----
|
||||
int removeSPITObject(string p_SPITObjectID);
|
||||
int changeSPITObject(SPITObject* p_SPITObject);
|
||||
|
||||
};
|
||||
|
||||
#endif /* MYSPITAPP_H */
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: ServerAutoDetetc_Client.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 16. April 2019, 08:57
|
||||
*/
|
||||
#ifndef SERVERAUTODETETC_CLIENT_H
|
||||
#define SERVERAUTODETETC_CLIENT_H
|
||||
#include "_SPITMACROS.h"
|
||||
#include "SPIT_Handler.h"
|
||||
#include "SPITSocket.h"
|
||||
#include "SAD_DetectedServer.h"
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
|
||||
static const string SERVERAUTODETECT_PRECODE = "#SAD#";
|
||||
static const string SERVERAUTODETECT_SEPERATOR = "#,#";
|
||||
static const string SERVERAUTODETECT_TASKID = "#spit#";
|
||||
static const string SERVERAUTODETECT_PORT = "15110";
|
||||
|
||||
|
||||
|
||||
class SAD_Client {
|
||||
|
||||
//----- SAD Client Interface ------
|
||||
private:
|
||||
static recursive_mutex s_MutexClientInterface;
|
||||
static SAD_ClientInterface* s_SADClientInterface;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//----- SAD_Client -----
|
||||
public:
|
||||
private:
|
||||
static mutex s_MutexSAD;
|
||||
static condition_variable s_ConditionStopSAD;
|
||||
static bool s_StopSAD;
|
||||
static thread* s_ThreadSend;
|
||||
static thread* s_ThreadReceiveIP4;
|
||||
static thread* s_ThreadReceiveIP6;
|
||||
|
||||
static recursive_mutex s_MutexSocket;
|
||||
static SPITSocket* s_SPITSocket;
|
||||
|
||||
static void sendAutoDetectServer();
|
||||
static void cycleStart();
|
||||
static void cycleEnd();
|
||||
static void receiveAutoDetectServer_IP4();
|
||||
static void receiveAutoDetectServer_IP6();
|
||||
|
||||
public:
|
||||
static void startAutoDetectServer(SAD_ClientInterface* p_SADClientInterface, SPITSocket* p_SPITSocket);
|
||||
static void stopAutoDetectServer(SAD_ClientInterface* p_SADClientInterface);
|
||||
};
|
||||
|
||||
#endif /* SERVERAUTODETETC_CLIENT_H */
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: SAD_ClientInterface.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 16. April 2019, 13:08
|
||||
*/
|
||||
|
||||
#ifndef SAD_CLIENTINTERFACE_H
|
||||
#define SAD_CLIENTINTERFACE_H
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class SAD_ClientInterface {
|
||||
public:
|
||||
/**
|
||||
* If a new server was found by the ServerAutoDetect mechanism, this function is called.<br>
|
||||
* To do so the SAD_Client ServerAutoDetect has to be startet - see SAD_Client::startServerAutoDetect.<br>
|
||||
* If a server can be reached via several IP addresses, the IP address is selected according to the following preference:<br>
|
||||
* 1.) If a loopback address is available, it is used.<br>
|
||||
* 2.) If an IP4 address is available, it is used.<br>
|
||||
* 3.) In the other cases the IP6 address is used.<br>
|
||||
* @param p_ID the id of the server (every started server should generate an id)
|
||||
* @param p_Name the name of the SPIT server
|
||||
* @param p_ComputerName the Hostname of the cpmputer on which the SPIT server is running
|
||||
* @param p_IP the selected ip address of the SPIT server
|
||||
* @param p_Port the port of the SPIT server
|
||||
* @param p_Addition sometimes server may have additional informations
|
||||
* @param p_isLoopback the server ip is a loopback address
|
||||
* @param p_IsIP4 the server ip is a ip4 address
|
||||
* @param p_IsIP6 the server ip is a ip6 address
|
||||
*/
|
||||
virtual void eventServerDetected(string p_ID, string p_Name, string p_ComputerName, string p_IP, string p_Port, string p_Addition, string p_CLientIP, bool p_isLoopback, bool p_IsIP4, bool p_IsIP6) = 0;
|
||||
/**
|
||||
* If a SPITServer is not more found, this function is called.
|
||||
* To do so the SAD_Client ServerAutoDetect has to be startet - see SAD_Client::startServerAutoDetect.<br>
|
||||
* @param p_ID the id of the server (every started server should generate an id)
|
||||
* @param p_Name the name of the SPIT server
|
||||
* @param p_ComputerName the Hostname of the cpmputer on which the SPIT server is running
|
||||
* @param p_IP the selected ip address of the SPIT server
|
||||
* @param p_Port the port of the SPIT server
|
||||
* @param p_Addition sometimes server may have additional informations
|
||||
* @param p_isLoopback the server ip is a loopback address
|
||||
* @param p_IsIP4 the server ip is a ip4 address
|
||||
* @param p_IsIP6 the server ip is a ip6 address
|
||||
*/
|
||||
virtual void eventServerLost(string p_ID, string p_Name, string p_ComputerName, string p_IP, string p_Port, string p_Addition, string p_CLientIP, bool p_isLoopback, bool p_IsIP4, bool p_IsIP6) = 0;
|
||||
};
|
||||
|
||||
#endif /* SAD_CLIENTINTERFACE_H */
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This class describes a detected SPITServer, found by SAD_Client.<br>
|
||||
* File: SAD_DetectedServer.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 4. Mai 2019, 13:51
|
||||
*/
|
||||
|
||||
#ifndef SAD_DETECTEDSERVER_H
|
||||
#define SAD_DETECTEDSERVER_H
|
||||
|
||||
#include "SAD_ClientInterface.h"
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <list>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
class SAD_DetectedServer {
|
||||
|
||||
public:
|
||||
SAD_DetectedServer();
|
||||
SAD_DetectedServer(const SAD_DetectedServer& orig) {
|
||||
m_ID = orig.getID();
|
||||
m_Name = orig.getName();
|
||||
m_ComputerName = orig.getComputerName();
|
||||
m_IP = orig.getIP();
|
||||
m_IPIsLoopback = orig.getIpIsLoopback();
|
||||
m_IPIsIP4 = orig.getIpIsIP4();
|
||||
m_IPIsIP6 = orig.getIpIsIP6();
|
||||
m_ClientIP = orig.getClientIP();
|
||||
m_Port = orig.getPort();
|
||||
m_Additions = orig.getAdditions();
|
||||
}
|
||||
~SAD_DetectedServer();
|
||||
|
||||
private:
|
||||
string m_ID;
|
||||
string m_Name;
|
||||
string m_ComputerName;
|
||||
string m_IP;
|
||||
bool m_IPIsLoopback;
|
||||
bool m_IPIsIP4;
|
||||
bool m_IPIsIP6;
|
||||
string m_ClientIP;
|
||||
string m_Port;
|
||||
string m_Additions;
|
||||
bool m_New;
|
||||
bool m_Changed;
|
||||
bool m_FoundAgain;
|
||||
|
||||
public:
|
||||
/**
|
||||
*
|
||||
* @return ID of the SPITServer
|
||||
*/
|
||||
string getID() const {
|
||||
return m_ID;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return name of the SPITServer
|
||||
*/
|
||||
string getName() const {
|
||||
return m_Name;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return name of the computer where the SPITServer runs
|
||||
*/
|
||||
string getComputerName() const {
|
||||
return m_ComputerName;
|
||||
}
|
||||
/**
|
||||
* @return IP address at which the server can be reached
|
||||
*/
|
||||
string getIP() const {
|
||||
return m_IP;
|
||||
}
|
||||
/**
|
||||
* @return true = the SPITServer's IP address is a loopback address
|
||||
*/
|
||||
bool getIpIsLoopback() const {
|
||||
return m_IPIsLoopback;
|
||||
}
|
||||
/**
|
||||
* @return true = the SPITServer's IP address is an IP4 address
|
||||
*/
|
||||
bool getIpIsIP4() const {
|
||||
return m_IPIsIP4;
|
||||
}
|
||||
/**
|
||||
* @return true = the SPITServer's IP address is an IP6 address
|
||||
*/
|
||||
bool getIpIsIP6() const {
|
||||
return m_IPIsIP6;
|
||||
}
|
||||
/**
|
||||
* @return port of the SPITServer
|
||||
*/
|
||||
string getPort() const {
|
||||
return m_Port;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return The IP address of the client under which this client reached the server.
|
||||
*/
|
||||
string getClientIP() const {
|
||||
return m_ClientIP;
|
||||
}
|
||||
/**
|
||||
* Sometimes the SPITServer has additional informations
|
||||
* @return
|
||||
*/
|
||||
string getAdditions() const {
|
||||
return m_Additions;
|
||||
}
|
||||
private:
|
||||
void setID(string p_ID);
|
||||
void setName(string p_Name);
|
||||
void setComputerName(string p_ComputerName);
|
||||
void setIP(string p_IP);
|
||||
void setClientIP(string p_IP);
|
||||
void setPort(string p_Port);
|
||||
void setAdditions(string p_Additions);
|
||||
|
||||
void setIPIsLoopback(bool p_IsLoopback) {
|
||||
m_IPIsLoopback = p_IsLoopback;
|
||||
}
|
||||
void setIPIsIP4(bool p_IsIP4) {
|
||||
m_IPIsIP4 = p_IsIP4;
|
||||
}
|
||||
void setIPIsIP6(bool p_IsIP6) {
|
||||
m_IPIsIP6 = p_IsIP6;
|
||||
}
|
||||
|
||||
bool getNew() const {
|
||||
return m_New;
|
||||
}
|
||||
bool getChanged() const {
|
||||
return m_Changed;
|
||||
}
|
||||
bool getFoundAgain() const {
|
||||
return m_FoundAgain;
|
||||
}
|
||||
|
||||
void setChanged() {
|
||||
m_Changed = true;
|
||||
}
|
||||
void setNew(bool p_New) {
|
||||
m_New = p_New;
|
||||
}
|
||||
void setFoundAgain() {
|
||||
m_FoundAgain = true;
|
||||
}
|
||||
//SAD_Client m_ThreadSend will send to Multicast addresses
|
||||
void startCycleSAD() {
|
||||
m_IPIsLoopback = false;
|
||||
m_IPIsIP4 = false;
|
||||
m_IPIsIP6 = false;
|
||||
m_Changed = false;
|
||||
m_FoundAgain = false;
|
||||
}
|
||||
//SAD_Client m_Thread_Send has paused in the meantime m_ThreadReceive may received messages from servers
|
||||
void endCycleSAD() {
|
||||
|
||||
}
|
||||
private:
|
||||
static recursive_mutex s_MutexDetectedServer;
|
||||
static unordered_map<string, SAD_DetectedServer*> s_DetectedServers;
|
||||
public:
|
||||
static const int PARAMINDEX_PRECODE = 0;
|
||||
static const int PARAMINDEX_SPITTASKID = 1;
|
||||
static const int PARAMINDEX_NAME = 2;
|
||||
static const int PARAMINDEX_ID = 3;
|
||||
static const int PARAMINDEX_COMPUTERNAME = 4;
|
||||
static const int PARAMINDEX_PORT = 5;
|
||||
static const int PARAMINDEX_CLIENTIP = 6;
|
||||
static const int PARAMINDEX_ADDITIONS = 7;
|
||||
static const int PARAMINDEX_IP = 8;
|
||||
/**
|
||||
* Used by SAD_Client to add a found SPITServer - don't use this manually
|
||||
* @param p_IsIP4 true = the server is reached via a IP4 address<br>false = the server is reahed via a IP6 address
|
||||
* @param p_ServerID the id of the server, every instance of a SPITServer has an own id
|
||||
* @param p_ServerParams the server's parameter
|
||||
*/
|
||||
static void addDetectedServer(bool p_IsIP4, string p_ServerID, string p_ServerParams[]);
|
||||
/**
|
||||
* Used by SAD_Client to remove a SPITServer - don't use this manually
|
||||
* @param p_DetectedServer
|
||||
*/
|
||||
static void removeDetectedServer(SAD_DetectedServer* p_DetectedServer);
|
||||
/**
|
||||
* Used by SAD_Client to clear all found SPITServers - don't use this manually
|
||||
*/
|
||||
static void clearDetectedServers();
|
||||
/**
|
||||
* Used by SAD_Client internally - don't use this manually
|
||||
*/
|
||||
static void cycleStart();
|
||||
/**
|
||||
* Used by SAD_Client internally -don't use this manually
|
||||
* @param p_SADClientInterface
|
||||
*/
|
||||
static void cycleEnd(SAD_ClientInterface* p_SADClientInterface);
|
||||
|
||||
/**
|
||||
* Returns a reference of the DetectedServer with the id p_ServerID.<br>
|
||||
* If no DetectedServer is found an eyception is thrown.
|
||||
* @param p_ServerID the id of the SPITServer
|
||||
* @return the reference of the SAD_DetectedServer instance with getID() == p_ServerID
|
||||
*/
|
||||
static const SAD_DetectedServer& getRefDetectedServer(string p_ServerID) {
|
||||
SAD_DetectedServer* ptrDetectedServer = NULL;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_Lock(s_MutexDetectedServer);
|
||||
auto i = s_DetectedServers.find(p_ServerID);
|
||||
if (i != s_DetectedServers.end()) {
|
||||
ptrDetectedServer = i->second;
|
||||
}
|
||||
if (ptrDetectedServer != NULL) {
|
||||
return *ptrDetectedServer;
|
||||
}
|
||||
|
||||
throw new exception();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* SAD_DETECTEDSERVER_H */
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: SPITObject.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 9. April 2019, 12:11
|
||||
*/
|
||||
|
||||
#ifndef SPITOBJECT_H
|
||||
#define SPITOBJECT_H
|
||||
|
||||
//#include "_SPITMACROS.h"
|
||||
#include "SPIT_Message.h"
|
||||
#include "SPITType.h"
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <mutex>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class SPITObjectListener;
|
||||
|
||||
class SPITObject {
|
||||
private:
|
||||
|
||||
static recursive_mutex s_MutexSPITObject;
|
||||
static unordered_map<string, SPITObject*> s_SPITObjects;
|
||||
static unordered_map<string, SPITObject*> s_SPITObjectsRemote;
|
||||
public:
|
||||
static recursive_mutex* getMutex() {
|
||||
return &s_MutexSPITObject;
|
||||
}
|
||||
static SPITObject* getSPITObject(string p_ID);
|
||||
static const SPITObject& getSPITObjectRef(string p_ID);
|
||||
static bool addSPITObject(SPITObject* p_ptrSpitObject);
|
||||
static bool removeSPITObject(SPITObject* p_ptrSpitObject);
|
||||
static int getSPITObjectCount();
|
||||
static SPITObject* getSPITObject(int p_Index);
|
||||
static const SPITObject& getSPITObjectRef(int p_Index);
|
||||
static void clearSPITObjects();
|
||||
static void setConfirmedFalse();
|
||||
|
||||
static SPITObject* getSPITObjectRemote(string p_ID);
|
||||
static const SPITObject& getSPITObjectRemoteRef(string p_ID);
|
||||
static bool addSPITObjectRemote(SPITObject* p_ptrSpitObject);
|
||||
static bool removeSPITObjectRemote(SPITObject* p_ptrSpitObject);
|
||||
static int getSPITObjectRemoteCount();
|
||||
static SPITObject* getSPITObjectRemote(int p_Index);
|
||||
static const SPITObject& getSPITObjectRemoteRef(int p_Index);
|
||||
static void clearSPITObjectsRemote();
|
||||
|
||||
SPITObject();
|
||||
// SPITObject(const SPITObject& orig);
|
||||
~SPITObject();
|
||||
private:
|
||||
string m_ID;
|
||||
string m_Name;
|
||||
string m_SPITTypeID;
|
||||
string m_ServerParams;
|
||||
string m_Remark;
|
||||
bool m_Confirmed;
|
||||
bool m_Fixed;
|
||||
bool m_ServerRemote;
|
||||
bool m_ActionAssigned;
|
||||
bool m_ActionAssignedType; //Virtual construct
|
||||
long long m_FrameStart;
|
||||
long long m_FrameLength;
|
||||
long long m_FrameFadeInLength;
|
||||
long long m_FrameFadeOutLength;
|
||||
char m_ValueUse;
|
||||
int m_ValueFactor;
|
||||
int m_Track;
|
||||
long long m_Delay;
|
||||
long long m_Duration;
|
||||
|
||||
bool m_PlayPrePosition;
|
||||
long long m_PlayTimeInsideFrames;
|
||||
int m_PlayValue;
|
||||
char m_PlayValueFlag;
|
||||
|
||||
|
||||
void initMembers();
|
||||
public:
|
||||
string getID() const {
|
||||
return m_ID;
|
||||
}
|
||||
string getName() const {
|
||||
return m_Name;
|
||||
}
|
||||
string getRemark() const {
|
||||
return m_Remark;
|
||||
}
|
||||
string getSPITTypeID() const {
|
||||
return m_SPITTypeID;
|
||||
}
|
||||
string getServerParams() const {
|
||||
return m_ServerParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the SPITType triggers an action on the Server or on the client.
|
||||
* @return false = the action is triggered on the client The client waits for the server to play objects of this SPITType<br>
|
||||
* true = the action is triggered on the server. The server waits for the client to play objects of this SPITType.
|
||||
*/
|
||||
bool getServerRemote() const {
|
||||
return m_ServerRemote;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used by the server and client to tell if the other side has registered the changes.
|
||||
* @return true = other side has registered the changes.
|
||||
*/
|
||||
bool getConfirmed() const {
|
||||
return m_Confirmed;
|
||||
}
|
||||
bool getFixed() const {
|
||||
return m_Fixed;
|
||||
}
|
||||
/**
|
||||
* This is a virtual construct - ActionAssignedType is not implemented in the SPITProtocol.<br>
|
||||
* This is used when an action is associated with a SPITType. <br>
|
||||
* Then this action is done for every SPITObject with the SPITType.
|
||||
* @return true = an action is assigned for the SPITType.
|
||||
*/
|
||||
bool getActionAssignedType() const {
|
||||
return m_ActionAssignedType;
|
||||
}
|
||||
/** Returns if this SPITObject has an associated action or not.<br>
|
||||
* @return true = the user has asscociated an action with this SPITObject or <br>
|
||||
* the user has asscociated an action with the SPITType of this SPITObject
|
||||
*/
|
||||
bool getActionAssigned() const {
|
||||
return m_ActionAssigned || m_ActionAssignedType;
|
||||
}
|
||||
|
||||
long long getFrameStart() const {
|
||||
return m_FrameStart;
|
||||
}
|
||||
long long getFrameLength() const {
|
||||
return m_FrameLength;
|
||||
}
|
||||
long long getFrameFadeInLength() const {
|
||||
return m_FrameFadeInLength;
|
||||
}
|
||||
long long getFrameFadeOutLength() const {
|
||||
return m_FrameFadeOutLength;
|
||||
}
|
||||
char getValueUse() const {
|
||||
return m_ValueUse;
|
||||
}
|
||||
int getValueFactor() const {
|
||||
return m_ValueFactor;
|
||||
}
|
||||
int getTrack() const {
|
||||
return m_Track;
|
||||
}
|
||||
|
||||
long long getDelay() const {
|
||||
return m_Delay;
|
||||
}
|
||||
long long getDuration() const {
|
||||
return m_Duration;
|
||||
}
|
||||
|
||||
|
||||
void setID(string p_ID);
|
||||
bool setConfirmed(bool p_Confirmed);
|
||||
bool setName(string p_Name);
|
||||
bool setRemark(string p_Remark);
|
||||
bool setServerParams(string p_ServerParams);
|
||||
bool setSPITTypeID(string p_GroupName);
|
||||
bool setServerRemote(bool p_BelongstoServer);
|
||||
bool setActionAssignedType(bool p_ActionAssigned);
|
||||
bool setActionAssigned(bool p_ActionAssigned);
|
||||
bool setFixed(bool p_Fixed);
|
||||
bool setFrameStart(long long p_FrameStart);
|
||||
bool setFrameLength(long long p_FrameLength);
|
||||
bool setFrameFadeInLength(long long p_FrameFadeInLength);
|
||||
bool setFrameFadeOutLength(long long p_FrameFadeOutLength);
|
||||
bool setValueUse(char p_ValueUse);
|
||||
bool setValueFactor(int p_ValueFactor);
|
||||
bool setTrack(int p_Track);
|
||||
bool setDelay(long long p_Delay);
|
||||
bool setDuration(long long p_Duration);
|
||||
|
||||
void setMessageOP(SPIT_Message::ReportSPITObject* p_ReportSPITObject);
|
||||
void fillMessageOP(SPIT_Message::ReportSPITObject* p_ReportSPITObject);
|
||||
void fillMessageOP(SPIT_Message::RemoveSPITObject* p_RemoveSPITObject);
|
||||
};
|
||||
|
||||
|
||||
#endif /* SPITOBJECT_H */
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: SPITPLayer.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 30. April 2019, 11:44
|
||||
*/
|
||||
|
||||
#ifndef SPITPLAYER_H
|
||||
#define SPITPLAYER_H
|
||||
|
||||
#include "SPITObject.h"
|
||||
#include <unordered_map>
|
||||
|
||||
class SPITPlayer {
|
||||
|
||||
//----- PlayObject used in PlaySequences: PlaySPITStart, PlaySPITObject,..., PlaySPITEnd ------
|
||||
public:
|
||||
class PlayObject {
|
||||
public:
|
||||
PlayObject();
|
||||
PlayObject(SPITPlayer* p_SPITPlayer, string p_SPITObjectID);
|
||||
PlayObject(const PlayObject& orig);
|
||||
|
||||
string getSPITObjectID() const {
|
||||
return m_SPITObjectID;
|
||||
}
|
||||
|
||||
void startPlaySequence();
|
||||
bool getIsNew() const {
|
||||
return m_IsNew;
|
||||
}
|
||||
void setIsNew(bool p_IsNew) {
|
||||
m_IsNew = p_IsNew;
|
||||
}
|
||||
bool getIsPlayed() const {
|
||||
return m_IsPlayed;
|
||||
}
|
||||
void setIsPlayed(bool p_IsFound) {
|
||||
m_IsPlayed = p_IsFound;
|
||||
}
|
||||
|
||||
|
||||
string getPlayerID() const {
|
||||
return m_PlayerID;
|
||||
}
|
||||
string getPlayerName() const {
|
||||
return m_PlayerName;
|
||||
}
|
||||
bool getPlayerIsRunning() const {
|
||||
return m_PlayerRuns;
|
||||
}
|
||||
void setPlayerIsRunning(bool p_PlayerRuns) {
|
||||
m_PlayerRuns = p_PlayerRuns;
|
||||
}
|
||||
|
||||
void setValue(int p_Value, bool p_PlayPrePosition) {
|
||||
if (p_PlayPrePosition) m_ValuePrePosition = p_Value;
|
||||
else m_Value = p_Value;
|
||||
}
|
||||
|
||||
int getValue() const {
|
||||
return m_ValuePrePosition + m_Value;
|
||||
}
|
||||
int getValueFadePrePosition() const {
|
||||
return m_ValuePrePosition;
|
||||
}
|
||||
int getValueFade() const {
|
||||
return m_Value;
|
||||
}
|
||||
void setValueFactor(int p_ValueFactor) {
|
||||
m_ValueFactor = p_ValueFactor;
|
||||
}
|
||||
void setValueFlag(char p_ValueFlag) {
|
||||
m_ValueFlag = p_ValueFlag;
|
||||
}
|
||||
int getValueFactor() const {
|
||||
return m_ValueFactor;
|
||||
}
|
||||
char getValueFlag() const {
|
||||
return m_ValueFlag;
|
||||
}
|
||||
void setFrameInside(long long p_FrameInside, bool p_PlayPrePosition) {
|
||||
if (p_PlayPrePosition) m_FrameInsidePrePosition = p_FrameInside;
|
||||
else m_FrameInside = p_FrameInside;
|
||||
}
|
||||
long long getFrameInside() const {
|
||||
return m_FrameInside;
|
||||
}
|
||||
long long getFrameInsidePrePosition() const {
|
||||
return m_FrameInsidePrePosition;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
string m_PlayerID;
|
||||
string m_PlayerName;
|
||||
bool m_PlayerRuns;
|
||||
string m_SPITObjectID;
|
||||
bool m_IsPlayed;
|
||||
bool m_IsNew;
|
||||
|
||||
int m_Value;
|
||||
int m_ValuePrePosition;
|
||||
int m_ValueFactor;
|
||||
char m_ValueFlag;
|
||||
long long m_FrameInsidePrePosition;
|
||||
long long m_FrameInside;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//----- SPITPlayer ------
|
||||
public:
|
||||
static recursive_mutex s_Mutex;
|
||||
static recursive_mutex* getMutex() {
|
||||
return &s_Mutex;
|
||||
}
|
||||
//list the SPITPlayers
|
||||
static unordered_map<string, SPITPlayer*> s_SPITPlayers; //all actual played objects
|
||||
static SPITPlayer* getSPITPlayer(string p_PlayerID); //if a player does not exist creates a new one
|
||||
static void clearPlayers();
|
||||
|
||||
|
||||
|
||||
SPITPlayer(string p_PlayerID);
|
||||
virtual ~SPITPlayer();
|
||||
|
||||
|
||||
void startPlaySequence(); //called by SPIT_Client::parsePlaySPITStart
|
||||
PlayObject* addSPITObject_Playing (string p_SPITObjectID); //called by SPIT_Client::parsePlaySPITStart
|
||||
void endPlaySequence(); //called by SPIT_Client::parsePlaySPITEnd
|
||||
|
||||
string getID() {
|
||||
return m_ID;
|
||||
}
|
||||
|
||||
unordered_map<string, PlayObject*>* getPlayObjects();
|
||||
|
||||
void setIsRunning(bool p_IsRunning);
|
||||
bool getIsRunning() {
|
||||
return m_IsRunning;
|
||||
}
|
||||
void setName(string p_Name);
|
||||
string getName() {
|
||||
return m_Name;
|
||||
}
|
||||
void setType(char p_Type);
|
||||
char getType() {
|
||||
return m_Type;
|
||||
}
|
||||
void setTime(long long p_Frames);
|
||||
long long getTime() {
|
||||
return m_TimeFrames;
|
||||
}
|
||||
|
||||
PlayObject* getPlayObject(string p_SPITObjectID);
|
||||
|
||||
private:
|
||||
string m_ID;
|
||||
string m_Name;
|
||||
char m_Type;
|
||||
unordered_map<string, PlayObject*> m_PlayObjects;
|
||||
bool m_IsRunning;
|
||||
long long m_TimeFrames;
|
||||
};
|
||||
|
||||
#endif /* SPITPLAYER_H */
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPITSocket is the base class for WindowsSocket, UnixSocket,..<br>
|
||||
* Used by SPIT_Client and SAD_Client.
|
||||
* File: SPITSocket.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 12. April 2019, 15:40
|
||||
*/
|
||||
|
||||
#ifndef SPITSOCKET_H
|
||||
#define SPITSOCKET_H
|
||||
#include "_SPITMACROS.h"
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class SPITSocket{
|
||||
public:
|
||||
static int FAMILY_IP4;
|
||||
static int FAMILY_IP6;
|
||||
|
||||
//-------- nested classes --------------
|
||||
|
||||
public:
|
||||
/**
|
||||
* IPAddress class is used to fetch all available IP addresses of the computer.<br>
|
||||
* This is for internal usage.<br>
|
||||
*/
|
||||
class IPAddress {
|
||||
public:
|
||||
IPAddress();
|
||||
~IPAddress();
|
||||
private:
|
||||
string m_IPAddress;
|
||||
string m_SubnetMask;
|
||||
bool m_Found;
|
||||
public:
|
||||
const string& getIPAddress() {
|
||||
return m_IPAddress;
|
||||
}
|
||||
const string& getSubnetMask() {
|
||||
return m_SubnetMask;
|
||||
}
|
||||
bool getFound() {
|
||||
return m_Found;
|
||||
}
|
||||
|
||||
void setIPAddress(const string& p_IPAddress);
|
||||
void setSubnetMask(const string& p_SubnetMask);
|
||||
void setFound(bool p_Found);
|
||||
};
|
||||
|
||||
private:
|
||||
static recursive_mutex s_MutexIPAddresses;
|
||||
public:
|
||||
static unordered_map<string, IPAddress*> s_IPAddresses;
|
||||
static void addIPAddress(string p_IPAddress, string p_SubnetMask);
|
||||
static void removeIPAddress(string p_IPAddress);
|
||||
static int getIPAddressCount();
|
||||
static IPAddress* getIPAddress(int p_Index);
|
||||
static void clearIPAddresses();
|
||||
static void resetFoundIPAddresses();
|
||||
static void removeNotFoundIPAddresses();
|
||||
|
||||
|
||||
//-------- class --------------
|
||||
|
||||
SPITSocket();
|
||||
virtual ~SPITSocket();
|
||||
private:
|
||||
string m_ServerIP;
|
||||
string m_ServerPort;
|
||||
string m_ClientIP;
|
||||
string m_ClientPort; //port given by the user maybe "0"
|
||||
string m_BoundClientPort; //port set after bind
|
||||
int m_BoundClientFamily;
|
||||
bool m_IsBound;
|
||||
recursive_mutex m_MutexSocket;
|
||||
public:
|
||||
/**
|
||||
* Sets the ip address and port for server and client.
|
||||
* @param p_ServerIP
|
||||
* @param p_ServerPort
|
||||
* @param p_ClientIP
|
||||
* @param p_ClientPort
|
||||
*/
|
||||
void setConnectionParams(string p_ServerIP, string p_ServerPort, string p_ClientIP, string p_ClientPort);
|
||||
|
||||
/**
|
||||
* Send a message to the server as set by setConnectionParams.<br>
|
||||
* @param p_MessageBytes byte buffer containing the message
|
||||
* @param p_MessageLength length of the messaeg
|
||||
* @return
|
||||
*/
|
||||
int sendMessage(const char* p_MessageBytes, int p_MessageLength);
|
||||
/**
|
||||
* Call this for receiving a message.<br>
|
||||
* This will block until a message is received or the underlying socket is closed.<br>
|
||||
* @param p_InetFamily either AF_INET or AF_INET6<br>
|
||||
* The SPITSocket creates two udp sockets, one for IP4 and one for IP6.<br>
|
||||
* This parameter decides from which socket should a message recieved.<br>
|
||||
* @param p_Buffer the buffer containing the received message later.
|
||||
* @param p_BufferLength the size of the buffer
|
||||
* @param p_ServerIP a pointer to a string, when a messages is received the string will contain the ip address of the sender/server.<br>
|
||||
* if p_ServerIP is NULL - no detection of the server will be done.
|
||||
* @return
|
||||
*/
|
||||
virtual int receiveMessage(int p_InetFamily, char* p_Buffer, int p_BufferLength, string* p_ServerIP) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the broadcast address of an ip4 address.<br>
|
||||
* @param p_IPAdress
|
||||
* @return
|
||||
*/
|
||||
virtual string getBroadcastIP4(IPAddress* p_IPAdress) = 0;
|
||||
/**
|
||||
* Set whether the sockat are brodcast sockets or not
|
||||
* @param p_Broadcast true = the sockets are broadcast sockets
|
||||
* @return 0 = ok, -1 = error
|
||||
*/
|
||||
virtual int setBroadcast(bool p_Broadcast) = 0;
|
||||
/**
|
||||
* Bind the client's udp socket to an ip address and port.<br>
|
||||
* @param p_ClientIP the ip address either IP4 or IP6
|
||||
* @param p_ClientPort the client port number.<br>
|
||||
* "0" = bind to any free port.<br>
|
||||
* @return
|
||||
*/
|
||||
virtual int bindSocket(string p_ClientIP, string p_ClientPort) = 0;
|
||||
/**
|
||||
* Internal usage - don't use this manually.<br>
|
||||
* Use sendMessage instead.<br>
|
||||
* @param p_InetFamily
|
||||
* @param p_ServerIP
|
||||
* @param p_Port
|
||||
* @param p_MessageBytes
|
||||
* @param p_MessageLength
|
||||
* @return
|
||||
*/
|
||||
virtual int sendMessageTo(int p_InetFamily, string p_ServerIP, string p_Port, const char* p_MessageBytes, int p_MessageLength) = 0;
|
||||
/**
|
||||
* Internal usage - don't use this manually.<br>
|
||||
*/
|
||||
virtual void getAdaptersInfo() = 0;
|
||||
|
||||
|
||||
string getServerIP();
|
||||
string getServerPort();
|
||||
string getClientIP();
|
||||
string getClientPort();
|
||||
string getBoundClientPort();
|
||||
void setBoundClientPort(string p_Port);
|
||||
void setBoundClientFamily(int p_Family);
|
||||
int getBoundClientFamily();
|
||||
void setIsBound(bool p_IsBound);
|
||||
bool getIsBound();
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* SPITSOCKET_H */
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: SPITType.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 8. April 2019, 08:40
|
||||
*/
|
||||
|
||||
#ifndef SPITTYPE_H
|
||||
#define SPITTYPE_H
|
||||
|
||||
#include "_SPITMACROS.h"
|
||||
#include "SPIT_Message.h"
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <mutex>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
class SPITTypeListener;
|
||||
|
||||
class SPITType {
|
||||
private:
|
||||
static recursive_mutex s_MutexSPITType;
|
||||
static unordered_map<string, SPITType*> s_SPITTypes;
|
||||
static unordered_map<string, SPITType*> s_SPITTypesRemote;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
static recursive_mutex* getMutex() {
|
||||
return &s_MutexSPITType;
|
||||
}
|
||||
static SPITType* getSPITType(string p_ID);
|
||||
static const SPITType& getSPITTypeRef(string p_ID);
|
||||
static bool addSPITType(SPITType* p_ptrSpitType);
|
||||
static bool removeSPITType(SPITType* p_ptrSpitType);
|
||||
static int getSPITTypeCount();
|
||||
static SPITType* getSPITType(int p_Index);
|
||||
static const SPITType& getSPITTypeRef(int p_Index);
|
||||
static void clearSPITTypes();
|
||||
static void setConfirmedFalse();
|
||||
|
||||
static SPITType* getSPITTypeRemote(string p_ID);
|
||||
static const SPITType& getSPITTypeRemoteRef(string p_ID);
|
||||
static bool addSPITTypeRemote(SPITType* p_ptrSpitType);
|
||||
static bool removeSPITTypeRemote(SPITType* p_ptrSpitType);
|
||||
static int getSPITTypeRemoteCount();
|
||||
static SPITType* getSPITTypeRemote(int p_Index);
|
||||
static const SPITType& getSPITTypeRemoteRef(int p_Index);
|
||||
static void clearSPITTypesRemote();
|
||||
|
||||
|
||||
SPITType();
|
||||
SPITType(string p_ID, string p_GroupName, string p_Name, bool p_Fixed, bool p_ProjectIndepended,long long p_DefaultDelay, long long p_DefaultDuration);
|
||||
// SPITType(const SPITType& orig);
|
||||
~SPITType();
|
||||
private:
|
||||
|
||||
bool m_Confirmed;
|
||||
string m_ID;
|
||||
bool m_Fixed;
|
||||
bool m_ServerRemote;
|
||||
bool m_ServerProjectIndepended;
|
||||
string m_GroupName;
|
||||
string m_Name;
|
||||
long long m_DefaultDelay;
|
||||
long long m_DefaultDuration;
|
||||
|
||||
bool m_CreatedByClient; //flag true = the SPITTyype is created by the client
|
||||
//false = the SPITType is received from the server
|
||||
|
||||
bool m_ActionAssigned; //This is a virtual flag if user associates an action with a SPITType.
|
||||
//Can be used to setActionAssigned for all SPITObjects with this SPITType
|
||||
|
||||
void initMembers();
|
||||
|
||||
public:
|
||||
string getID() const{
|
||||
return m_ID;
|
||||
}
|
||||
string getGroupName() const {
|
||||
return m_GroupName;
|
||||
}
|
||||
string getName() const {
|
||||
return m_Name;
|
||||
}
|
||||
/**
|
||||
* Returns if the SPITType triggers an action on the Server or on the client.
|
||||
* @return false = the action is triggered on the client The client waits for the server to play objects of this SPITType<br>
|
||||
* true = the action is triggered on the server. The server waits for the client to play objects of this SPITType.
|
||||
*/
|
||||
bool getServerRemote() const {
|
||||
return m_ServerRemote;
|
||||
}
|
||||
|
||||
bool getProjectIndepended() const {
|
||||
return m_ServerProjectIndepended;
|
||||
}
|
||||
/**
|
||||
* This is used by the server and client to tell if the other side has registered the changes.
|
||||
* @return true = other side has registered the changes.
|
||||
*/
|
||||
bool getConfirmed() const {
|
||||
return m_Confirmed;
|
||||
}
|
||||
bool getFixed() const {
|
||||
return m_Fixed;
|
||||
}
|
||||
long long getDefaultDelay() const {
|
||||
return m_DefaultDelay;
|
||||
}
|
||||
long long getDefaultDuration() const {
|
||||
return m_DefaultDuration;
|
||||
}
|
||||
|
||||
bool getCreatedByClient() const {
|
||||
return m_CreatedByClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Virtual construct - means ActionAssigned for SPITTypes is is not implemented in SPITProtocol.<br>
|
||||
* This can used to setActionAssigned to all SPITObjects with this SPITType.<br>
|
||||
* This may be used in the case when the same action should be done for every SPITObject with this SPITType associated.<br>
|
||||
* @return true = the user has associated an action with this SPITType.
|
||||
*/
|
||||
bool getActionAssigned() const {
|
||||
return m_ActionAssigned;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
void setID(string p_ID);
|
||||
bool setGroupName(string p_GroupName);
|
||||
bool setName(string p_Name);
|
||||
bool setServerRemote(bool p_BelongstoServer);
|
||||
bool setProjectIndepended(bool p_ProjectIndepeneded);
|
||||
bool setConfirmed(bool p_Confirmed);
|
||||
bool setFixed(bool p_Fixed);
|
||||
bool setDefaultDelay(long long p_Delay);
|
||||
bool setDefaultDuration(long long p_Duration);
|
||||
|
||||
void setCreatedByClient(bool p_CreatedByClient);
|
||||
|
||||
/**
|
||||
* Virtual construct - means ActionAssigned for SPITTypes is is not implemented in SPITProtocol.<br>
|
||||
* This can used to setActionAssigned to all SPITObjects with this SPITType.<br>
|
||||
* This may be used in the case when the same action should be done for every SPITObject with this SPITType associated.<br>
|
||||
* @return true = the m_ActionAssigned has changed.
|
||||
*/
|
||||
bool setActionAssigned(bool p_ActionAssigned);
|
||||
|
||||
bool setMessageOP(SPIT_Message::ReportSPITType* p_ReportSPITType);
|
||||
void fillMessageOP(SPIT_Message::ReportSPITType* p_ReportSPITType);
|
||||
void fillMessageOP(SPIT_Message::RemoveSPITType* p_RemoveSPITType);
|
||||
// static char* stringCopy(const char* p_String);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* SPITTYPE_H */
|
||||
|
||||
@@ -0,0 +1,648 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: SPIT_Client.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 7. April 2019, 08:50
|
||||
*/
|
||||
|
||||
#ifndef SPIT_CLIENT_H
|
||||
#define SPIT_CLIENT_H
|
||||
|
||||
#include "_SPITMACROS.h"
|
||||
#if defined OS_WINDOWS
|
||||
#include "WindowsSocket.h"
|
||||
#endif
|
||||
#if defined OS_MAC || defined OS_LINUX
|
||||
#include "UnixSocket.h"
|
||||
#endif
|
||||
|
||||
#include "SPITSocket.h"
|
||||
#include "SAD_Client.h"
|
||||
#include "SAD_ClientInterface.h"
|
||||
#include "SAD_DetectedServer.h"
|
||||
#include "SPIT_ClientInterface.h"
|
||||
#include "SPIT_Message.h"
|
||||
#include "Watchdog.h"
|
||||
#include "SPITType.h"
|
||||
#include "SPITObject.h"
|
||||
#include "SPIT_Handler.h"
|
||||
#include "SPITPlayer.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
//#include <thread>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//static char nullChar[] = "\0";
|
||||
|
||||
class SPIT_Client : SAD_ClientInterface, Watchdog::Listener {
|
||||
public:
|
||||
/** Maximal length of a SPITMessage*/
|
||||
static const int MAXSPITMESSAGEBYTECOUNT = 512;
|
||||
|
||||
//----- Connection Status -----
|
||||
public:
|
||||
/** No Connection established.<br>Either no connect tried or disconnected*/
|
||||
static const int CONNECTION_NONE = 0;
|
||||
/** Server has disconnected*/
|
||||
static const int CONNECTION_NONESERVER = 1;
|
||||
/** The connection is lost<br>Either because of a network crash or because the server no longer responds.*/
|
||||
static const int CONNECTION_LOST = 2;
|
||||
/** Connection to the server is established.*/
|
||||
static const int CONNECTION_OK = 3;
|
||||
/** A connection to the server is tried.*/
|
||||
static const int CONNECTION_TRYCONNECTION = 4;
|
||||
|
||||
//------ PlayerType ------
|
||||
public:
|
||||
/** continous main player, time value can be used like a timecode.<br>The time value is the position in server's project.<br>A server should use only one main player.*/
|
||||
static const char PLAYERTYPE_MAIN = 0x02;
|
||||
/** continous player. This player plays SPIT objects sometime during the project.*/
|
||||
static const char PLAYERTYPE_CONTINOUS = 0x01;
|
||||
/** diescrete player. This player is used to transmit single discrete values.*/
|
||||
static const char PLAYERTYPE_DISCRETE = 0x00;
|
||||
|
||||
//------ Value Flag ------
|
||||
//------ used by sendRemoteObject
|
||||
public:
|
||||
/**Set the given value directly*/
|
||||
static const char VALUEFLAG_DIRECT = 0x00;
|
||||
/**Increase the existing value by the given value.<br>This is usefull e.g. when instead of a fader a endless wheel is used*/
|
||||
static const char VALUEFLAG_INCREASE = 0x01;
|
||||
/**Decrease the existing value by the given value.<br>This is usefull e.g. when instead of a fader a endless wheel is used*/
|
||||
static const char VALUEFLAG_DECREASE = 0x02;
|
||||
|
||||
//----- SPIT_Client -----
|
||||
public:
|
||||
static SPITSocket* createSPITSocket();
|
||||
public:
|
||||
SPIT_Client(SPIT_ClientInterface* p_SPITClientInterface);
|
||||
virtual ~SPIT_Client();
|
||||
private:
|
||||
/** SPITClientInterface, normally the user app should implement this*/
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
SPITSocket* m_SPITSocket;
|
||||
recursive_mutex m_MutexSPITSocket;
|
||||
thread* m_ThreadReceive;
|
||||
bool m_StopReceiveSPITMessages;
|
||||
|
||||
int m_ConnectionStatus;
|
||||
bool m_DisconnectedByServer; //flag true = when server disconnects
|
||||
string m_ID;
|
||||
string m_Name;
|
||||
string m_ComputerName;
|
||||
|
||||
//Server's info filled by parseConnectAnswer
|
||||
string m_ServerID;
|
||||
string m_ServerName;
|
||||
string m_ServerComputerName;
|
||||
int m_ServerStepTime;
|
||||
|
||||
|
||||
Watchdog* m_Watchdog;
|
||||
|
||||
//--- Server Project ---
|
||||
string m_ServerProjectID;
|
||||
string m_ServerProjectName;
|
||||
int m_ServerFramesPerSecond;
|
||||
|
||||
public:
|
||||
SPIT_ClientInterface* getSPITClientInterface() {
|
||||
return m_SPITClientInterface;
|
||||
}
|
||||
|
||||
public:
|
||||
/** The ID of the client.<br>Every client instance should set an unique id*/
|
||||
string getID();
|
||||
/** Set the name of the client, should be done by the user app*/
|
||||
void setName(string p_Name);
|
||||
/** The name of the client, should be set by the user app*/
|
||||
string getName();
|
||||
//----- Computer Params -----
|
||||
/** The name of the client's host computer*/
|
||||
string getComputerName();
|
||||
|
||||
//connected Server Infos
|
||||
/** The ID of the connected SPITServer*/
|
||||
string getServerID();
|
||||
/** The host computername of the connected SPITServer*/
|
||||
string getServerComputerName();
|
||||
/** The name of the connected SPITServer*/
|
||||
string getServerName();
|
||||
/** Expected Refreah Rate of the connectd SPITServer.<br>
|
||||
* When the server plays objects, it will do so at discrete time steps.<br>
|
||||
* Play events will take place in these time steps..
|
||||
*/
|
||||
int getServerStepTime();
|
||||
|
||||
/** Should be called when the client wants to close his project*/
|
||||
void clientProjectClose();
|
||||
/**
|
||||
* Should be called whenever the client has a project loaded
|
||||
*/
|
||||
void clientProjectLoaded();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param p_SPITTypeID
|
||||
* @param p_ActionAssigned
|
||||
*/
|
||||
void setActionSPITType(string p_SPITTypeID, bool p_ActionAssigned);
|
||||
void setActionSPITObject(string p_SPITObjectID, bool p_ActionAssigned);
|
||||
|
||||
//--------------- SPITMessage ---------------
|
||||
private:
|
||||
bool startReceiveSPITMessages();
|
||||
void stopReceiveSPITMessages();
|
||||
void receiveSPITMessage();
|
||||
int sendSPITMessage(SPIT_Message::OPPart* p_SPITMessageOPPart);
|
||||
void fillHeader(SPIT_Message::Header* p_Header);
|
||||
|
||||
|
||||
//--------------- ServerAutoDetection SAD ---------------
|
||||
public:
|
||||
/** Starts the autodetection of SPITServers in the local network. If a connection is tried, the autodetection should be stopped before.*/
|
||||
void startServerAutoDetect();
|
||||
/** Stops the autodetection of SPITServers in the local network*/
|
||||
void stopServerAutoDetect();
|
||||
/** Called every time a new SPITServer is detetced in the local network */
|
||||
void eventServerDetected(string p_ID, string p_Name, string p_ComputerName, string p_IP, string p_Port, string p_Addition, string p_ClientIP, bool p_isLoopback, bool p_IsIP4, bool p_IsIP6);
|
||||
/** Called every time a prior detected SPITServer is is no longer found.*/
|
||||
void eventServerLost(string p_ID, string p_Name, string p_ComputerName, string p_IP, string p_Port, string p_Addition, string p_ClientIP, bool p_isLoopback, bool p_IsIP4, bool p_IsIP6);
|
||||
|
||||
public:
|
||||
/** Helper class to notify the SPITClientInterface/user's app*/
|
||||
class NotifyServerDetected: virtual public SPIT_Handler::Runnable {
|
||||
private:
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
SAD_DetectedServer m_DetectedServer;
|
||||
public:
|
||||
NotifyServerDetected(SPIT_ClientInterface* p_SPITClientInterface, const SAD_DetectedServer& p_DetetctedServer) {
|
||||
m_SPITClientInterface = p_SPITClientInterface;
|
||||
m_DetectedServer = p_DetetctedServer;
|
||||
}
|
||||
~NotifyServerDetected(){}
|
||||
void run() {
|
||||
if (m_SPITClientInterface != NULL) {
|
||||
m_SPITClientInterface->eventServerDetected(m_DetectedServer);
|
||||
}
|
||||
}
|
||||
};
|
||||
public:
|
||||
/** Helper class to notify the SPITClientInterface/user's app*/
|
||||
class NotifyServerLost: virtual public SPIT_Handler::Runnable {
|
||||
private:
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
SAD_DetectedServer m_DetectedServer;
|
||||
public:
|
||||
NotifyServerLost(SPIT_ClientInterface* p_SPITClientInterface, const SAD_DetectedServer& p_DetetctedServer) {
|
||||
m_SPITClientInterface = p_SPITClientInterface;
|
||||
m_DetectedServer = p_DetetctedServer;
|
||||
}
|
||||
~NotifyServerLost() {}
|
||||
void run() {
|
||||
if (m_SPITClientInterface != NULL) {
|
||||
m_SPITClientInterface->eventServerLost(m_DetectedServer);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------- Connection ---------------
|
||||
public:
|
||||
/**
|
||||
* Tries a connection to the SPITServer
|
||||
* @param p_ServerIP ip address of the SPITServer
|
||||
* @param p_ServerPort port of the SPITServer
|
||||
* @param p_ClientIP IP of the client
|
||||
* @param p_ClientPort if "0" any free port will be used
|
||||
* @param p_LoginName maybe some SPITServer need a login - liveSHOWsoftware will not.
|
||||
* @param p_LoginPassword maybe some SPITServer need a login - liveSHOWsoftware will not
|
||||
* @return true = the connection try is ok, SPITServer will answer with COnnectAnswer and an eventConnectionStatus will occur.<br>
|
||||
* false = something is going wrong. (client could not bind)
|
||||
*/
|
||||
bool connect(string p_ServerIP, string p_ServerPort, string p_ClientIP, string p_ClientPort, string p_LoginName = "", string p_LoginPassword = "");
|
||||
/**
|
||||
* Terminates the connection to the SPITServer.
|
||||
*/
|
||||
void disconnect();
|
||||
|
||||
private:
|
||||
void disconnectInternal(int p_Cause);
|
||||
void parseSPIT_Message(SPIT_Message* p_SPITMessage);
|
||||
void parseConnectAnswer(SPIT_Message::ConnectAnswer* p_ConnectAnswer);
|
||||
void parseDisconnect(SPIT_Message::Disconnect* p_Disconnect);
|
||||
void parseWatchdog(SPIT_Message::Watchdog* p_Watchdog);
|
||||
void parseWatchdogAnswer(SPIT_Message::WatchdogAnswer* p_WatchdogAnswer);
|
||||
public:
|
||||
/** Used internally*/
|
||||
void sendWatchdog();
|
||||
/** Used internally. When the connection to the SPITServer is lost an eventConnectionStatus will occur*/
|
||||
void eventWatchdogLost();
|
||||
public:
|
||||
/** Helper class to notify the SPITClientInterface/user's app*/
|
||||
class NotifyConnectionStatus : public SPIT_Handler::Runnable {
|
||||
public:
|
||||
NotifyConnectionStatus(SPIT_ClientInterface* p_SPITClientInterface, string p_ServerID, string p_ServerComputerName, string p_ServerName, int p_ServerStepTime,
|
||||
int p_NewConnectionStatus, int p_OldConnectionStatus) {
|
||||
m_SPITClientInterface = p_SPITClientInterface;
|
||||
m_ServerID = p_ServerID;
|
||||
m_ServerComputerName = p_ServerComputerName;
|
||||
m_ServerName = p_ServerName;
|
||||
m_ServerStepTime = p_ServerStepTime;
|
||||
m_NewConnectionStatus = p_NewConnectionStatus;
|
||||
m_OldConnectionStatus = p_OldConnectionStatus;
|
||||
}
|
||||
~NotifyConnectionStatus() {}
|
||||
void run (){
|
||||
if (m_SPITClientInterface != NULL) {
|
||||
m_SPITClientInterface->eventConnectionStatus(m_ServerComputerName, m_ServerID, m_ServerName, m_ServerStepTime, m_NewConnectionStatus, m_OldConnectionStatus);
|
||||
}
|
||||
}
|
||||
private:
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
string m_ServerID;
|
||||
string m_ServerComputerName;
|
||||
string m_ServerName;
|
||||
int m_ServerStepTime;
|
||||
int m_NewConnectionStatus;
|
||||
int m_OldConnectionStatus;
|
||||
};
|
||||
|
||||
//--------------- SPIT Project ---------------
|
||||
private:
|
||||
void parseReportSPITProject(SPIT_Message::ReportSPITProject* p_ReportSPITProject);
|
||||
void parseCloseSPITProject(SPIT_Message::CloseSPITProject* p_CloseSPITProject);
|
||||
public:
|
||||
/** Returns the SPITServer's project ID - may be the same as the project's name*/
|
||||
string getServerProjectID();
|
||||
/** Returns the SPITServer's project name*/
|
||||
string getServerProjectName();
|
||||
/** Returns frame rate per second. This is the time resolution in which the server transmits time data. The unit of time data is always frames.*/
|
||||
int getServerFramesPerSecond();
|
||||
|
||||
public:
|
||||
/** Helper class to notify the SPITClientInterface/user's app*/
|
||||
class NotifyReportProject : public SPIT_Handler::Runnable {
|
||||
public:
|
||||
NotifyReportProject(SPIT_ClientInterface* p_SPITClientInterface, string p_ProjectID, string p_ProjectName, int p_FramesPerSecond) {
|
||||
m_SPITClientInterface = p_SPITClientInterface;
|
||||
m_ProjectID = p_ProjectID;
|
||||
m_ProjectName = p_ProjectName;
|
||||
m_FramesPerSecond = p_FramesPerSecond;
|
||||
}
|
||||
~NotifyReportProject() {}
|
||||
void run() {
|
||||
if (m_SPITClientInterface != NULL) {
|
||||
m_SPITClientInterface->eventProjectReport(m_ProjectID, m_ProjectName, m_FramesPerSecond);
|
||||
}
|
||||
}
|
||||
private:
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
string m_ProjectID;
|
||||
string m_ProjectName;
|
||||
int m_FramesPerSecond;
|
||||
};
|
||||
public:
|
||||
/** Helper class to notify the SPITClientInterface/user's app*/
|
||||
class NotifyProjectClosed : public SPIT_Handler::Runnable {
|
||||
public:
|
||||
NotifyProjectClosed(SPIT_ClientInterface* p_SPITClientInterface, string p_ProjectID) {
|
||||
m_SPITClientInterface = p_SPITClientInterface;
|
||||
m_ProjectID = p_ProjectID;
|
||||
}
|
||||
~NotifyProjectClosed() {}
|
||||
void run() {
|
||||
if (m_SPITClientInterface != NULL) {
|
||||
m_SPITClientInterface->eventProjectClosed(m_ProjectID);
|
||||
}
|
||||
}
|
||||
private:
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
string m_ProjectID;
|
||||
};
|
||||
|
||||
private:
|
||||
void parseRequestProjectTransfer(SPIT_Message::RequestProjectTransfer* p_RequestProjectTransfer);
|
||||
void parseStartProjectTransfer(SPIT_Message::StartProjectTransfer* p_StartProjectTransfer);
|
||||
void parseEndProjectTransfer(SPIT_Message::EndProjectTransfer* p_EndProjectTransfer);
|
||||
public:
|
||||
/** Helper class to notify the SPITClientInterface/user's app*/
|
||||
class NotifyStartProjectTransfer : public SPIT_Handler::Runnable {
|
||||
public:
|
||||
NotifyStartProjectTransfer(SPIT_ClientInterface* p_SPITClientInterface) {
|
||||
m_SPITClientInterface = p_SPITClientInterface;
|
||||
}
|
||||
~NotifyStartProjectTransfer() {}
|
||||
void run() {
|
||||
if (m_SPITClientInterface != NULL) {
|
||||
m_SPITClientInterface->eventStartProjectTransfer();
|
||||
}
|
||||
}
|
||||
private:
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
};
|
||||
public:
|
||||
/** Helper class to notify the SPITClientInterface/user's app*/
|
||||
class NotifyEndProjectTransfer : public SPIT_Handler::Runnable {
|
||||
public:
|
||||
NotifyEndProjectTransfer(SPIT_ClientInterface* p_SPITClientInterface) {
|
||||
m_SPITClientInterface = p_SPITClientInterface;
|
||||
}
|
||||
~NotifyEndProjectTransfer() {}
|
||||
void run() {
|
||||
if (m_SPITClientInterface != NULL) {
|
||||
m_SPITClientInterface->eventEndProjectTransfer();
|
||||
}
|
||||
}
|
||||
private:
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
};
|
||||
|
||||
|
||||
// --------------- SPIT Types ---------------
|
||||
public:
|
||||
/**
|
||||
* Creates a fixed SPITType for application actions that are always present and project independent.<br>
|
||||
* Fixed SPIT types cannot be changed or deleted by the server.<br>
|
||||
* These SPITTypes will be automatically added to the SPITType-List and sended to the server.
|
||||
* @param p_ID an unique of the SPITType, these are always the same per client approach. Different client approaches should use different ids.
|
||||
* @param p_GroupName a name which groups the actions/SPITTypes
|
||||
* @param p_Name the name of the Action/SPITType
|
||||
* @param p_DefaultDelay maybe there is an default delay until the action starts, this is only used for graphical representations, 0 is allowd
|
||||
* @param p_DefaultDuration maybe the action has a default duration, this is only used for graphical representations, 0 is allowd
|
||||
* @return the pointer to the new SPITType.
|
||||
*/
|
||||
SPITType* createSPITTypeFixed(string p_ID, string p_GroupName, string p_Name, long long p_DefaultDelay, long long p_DefaultDuration);
|
||||
|
||||
/**
|
||||
* Creates a SPITType for application actions.<br>
|
||||
* These SPITTypes will be automatically added to the SPITType-List and sended to the server.
|
||||
* @param p_ID an unique of the SPITType, these are always the same per client approach. Different client approaches should use different ids.
|
||||
* @param p_GroupName a name which groups the actions/SPITTypes
|
||||
* @param p_Name the name of the Action/SPITType
|
||||
* @param p_DefaultDelay maybe there is an default delay until the action starts, this is only used for graphical representations, 0 is allowd
|
||||
* @param p_DefaultDuration maybe the action has a default duration, this is only used for graphical representations, 0 is allowd
|
||||
* @param p_Fixed true = the server is not allowed to change this SPITType, false = the server may change or delete this SPITType
|
||||
* @param p_ProjectIndepended true = the SPITType belongs to a specific project, false = the SpitType always exists for every project
|
||||
* @return the pointer to the new SPITType.
|
||||
*/
|
||||
SPITType* createSPITType(string p_ID, string p_GroupName, string p_Name, long long p_DefaultDelay, long long p_DefaultDuration, bool p_Fixed, bool p_ProjectIndepended);
|
||||
private:
|
||||
//receive SPITTypes
|
||||
void parseReportSPITType(SPIT_Message::ReportSPITType* p_ReportSPITType);
|
||||
void parseRemoveSPITType(SPIT_Message::RemoveSPITType* p_RemoveSPITType);
|
||||
int sendSPITTypeInternal(SPITType* p_SPITType);
|
||||
public:
|
||||
/**
|
||||
* If a client wants to change a SPITType, he should send it to the server.<br>
|
||||
* If the SPITTye is a fixed one and not created by the client himself, then an eventSPITType can be sent from the server, which cancels the change.<br>
|
||||
* @param p_SPITTypeID the id of the SPITType to remove.
|
||||
* @return 0 = is sended, -1 = is not sended
|
||||
*/
|
||||
bool changeSPITType(SPITType* p_SPITType);
|
||||
/**
|
||||
* If a client wants to remove a SPITType, he should send it to the server.<br>
|
||||
* If the SPITTye is a fixed one and not created by the client himself, then an eventSPITType can be sent from the server, which cancels the deletion.<br>
|
||||
* @param p_SPITTypeID the id of the SPITType to remove.
|
||||
* @return 0 = is sended, -1 = is not sended
|
||||
*/
|
||||
int removeSPITType(string p_SPITTypeID);
|
||||
public:
|
||||
/** Helper class to notify the SPITClientInterface/user's app*/
|
||||
class NotifyReportSPITType : public SPIT_Handler::Runnable {
|
||||
public:
|
||||
NotifyReportSPITType(bool p_Remote, bool p_New, SPIT_ClientInterface* p_SPITClientInterface, const SPITType& p_SPITType) {
|
||||
m_SPITClientInterface = p_SPITClientInterface;
|
||||
m_Remote = p_Remote;
|
||||
m_New = p_New;
|
||||
m_SPITType = p_SPITType;
|
||||
}
|
||||
~NotifyReportSPITType() {}
|
||||
void run() {
|
||||
if (m_SPITClientInterface != NULL) {
|
||||
if (m_Remote == false) {
|
||||
m_SPITClientInterface->eventSPITType(m_New, m_SPITType);
|
||||
}
|
||||
else {
|
||||
m_SPITClientInterface->eventSPITTypeRemote(m_New, m_SPITType);
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
bool m_Remote;
|
||||
bool m_New;
|
||||
SPITType m_SPITType;
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
/** Helper class to notify the SPITClientInterface/user's app*/
|
||||
class NotifyRemoveSPITType : public SPIT_Handler::Runnable {
|
||||
public:
|
||||
NotifyRemoveSPITType(bool p_Remote, SPIT_ClientInterface* p_SPITClientInterface, const SPITType& p_SPITType) {
|
||||
m_SPITClientInterface = p_SPITClientInterface;
|
||||
m_Remote = p_Remote;
|
||||
m_SPITType = p_SPITType;
|
||||
}
|
||||
~NotifyRemoveSPITType() {}
|
||||
void run() {
|
||||
if (m_SPITClientInterface != NULL) {
|
||||
if (m_Remote == false) {
|
||||
m_SPITClientInterface->eventSPITTypeRemoved(m_SPITType);
|
||||
}
|
||||
else {
|
||||
m_SPITClientInterface->eventSPITTypeRemoteRemoved(m_SPITType);
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
bool m_Remote;
|
||||
SPITType m_SPITType;
|
||||
};
|
||||
|
||||
|
||||
//--------------- SPIT Objects ---------------
|
||||
private:
|
||||
void parseReportSPITObject(SPIT_Message::ReportSPITObject* p_ReportSPITObject);
|
||||
void parseRemoveSPITObject(SPIT_Message::RemoveSPITObject* p_RemoveSPITObject);
|
||||
int sendSPITObjectInternal(SPITObject* ptrSPITObject);
|
||||
public:
|
||||
/**
|
||||
* When the client changes a SPITObject (normally the client should not do this), then it should send the changes to the SPITServer.<br>
|
||||
* The SPITServer may discard the changes and an eventSPITObject occurs.<br>
|
||||
* @param p_SPITObject the pointer to the changed SPITObject.
|
||||
* @return 0 = sended, -1 = not sended
|
||||
*/
|
||||
bool changeSPITObject(SPITObject* p_SPITObject);
|
||||
/**
|
||||
* When the client removes a SPITObject (normally the client should not do this), then he should send it to the SPITServer.<br>
|
||||
* The SPITServer may discard the deletion and an eventSPITObject occurs.<br>
|
||||
* @param p_SPITObjectID the id of the SPITObject to remove.
|
||||
* @return 0 = sended, -1 = not sended
|
||||
*/
|
||||
int removeSPITObject(string p_SPITObjectID);
|
||||
public:
|
||||
/** Helper class to notify the SPITClientInterface/user's app*/
|
||||
class NotifyReportSPITObject : public SPIT_Handler::Runnable {
|
||||
public:
|
||||
NotifyReportSPITObject(bool p_Remote, bool p_New, SPIT_ClientInterface* p_SPITClientInterface, const SPITType& p_SPITType, const SPITObject& p_SPITObject) {
|
||||
m_SPITClientInterface = p_SPITClientInterface;
|
||||
m_Remote = p_Remote;
|
||||
m_New = p_New;
|
||||
m_SPITType = p_SPITType;
|
||||
m_SPITObject = p_SPITObject;
|
||||
}
|
||||
~NotifyReportSPITObject() {}
|
||||
void run() {
|
||||
if (m_SPITClientInterface != NULL) {
|
||||
if (m_Remote == false) {
|
||||
m_SPITClientInterface->eventSPITObject(m_New, m_SPITType, m_SPITObject);
|
||||
}
|
||||
else {
|
||||
m_SPITClientInterface->eventSPITObjectRemote(m_New, m_SPITType, m_SPITObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
bool m_Remote;
|
||||
bool m_New;
|
||||
SPITType m_SPITType;
|
||||
SPITObject m_SPITObject;
|
||||
};
|
||||
public:
|
||||
/** Helper class to notify the SPITClientInterface/user's app*/
|
||||
class NotifyRemoveSPITObject : public SPIT_Handler::Runnable {
|
||||
public:
|
||||
NotifyRemoveSPITObject(bool p_Remote, SPIT_ClientInterface* p_SPITClientInterface, const SPITType& p_SPITType, const SPITObject& p_SPITObject) {
|
||||
m_SPITClientInterface = p_SPITClientInterface;
|
||||
m_Remote = p_Remote;
|
||||
m_SPITType = p_SPITType;
|
||||
m_SPITObject = p_SPITObject;
|
||||
}
|
||||
~NotifyRemoveSPITObject() {}
|
||||
void run() {
|
||||
if (m_SPITClientInterface != NULL) {
|
||||
if (m_Remote == false) {
|
||||
m_SPITClientInterface->eventSPITObjectRemoved(m_SPITType, m_SPITObject);
|
||||
}
|
||||
else {
|
||||
m_SPITClientInterface->eventSPITObjectRemoteRemoved(m_SPITType, m_SPITObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
bool m_Remote;
|
||||
SPITType m_SPITType;
|
||||
SPITObject m_SPITObject;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------- Play SPIT Objects ---------------
|
||||
private:
|
||||
void parsePlaySPITStart(SPIT_Message::PlaySPITStart* p_PlaySPITStart);
|
||||
void parsePlaySPITObject(SPIT_Message::PlaySPITObject* p_PlaySPITObject);
|
||||
void parsePlaySPITEnd(SPIT_Message::PlaySPITEnd* p_PlaySPITEnd);
|
||||
void parseReportPlayStatus(SPIT_Message::ReportPlayStatus* p_ReportPlayStatus);
|
||||
|
||||
public:
|
||||
/** Helper class to notify the SPITClientInterface/user's app*/
|
||||
class NotifyPlaySPITStart : public SPIT_Handler::Runnable {
|
||||
public:
|
||||
NotifyPlaySPITStart(SPIT_ClientInterface* p_SPITClientInterface, string p_PlayerID, string p_PlayerName, char p_PlayerType, bool p_IsRunning, long long p_TimeFrame) {
|
||||
m_SPITClientInterface = p_SPITClientInterface;
|
||||
m_PlayerID = p_PlayerID;
|
||||
m_PlayerName = p_PlayerName;
|
||||
m_PlayerType = p_PlayerType;
|
||||
m_IsRunning = p_IsRunning;
|
||||
m_TimeFrames = p_TimeFrame;
|
||||
}
|
||||
~NotifyPlaySPITStart() {}
|
||||
void run() {
|
||||
if (m_SPITClientInterface != NULL) {
|
||||
m_SPITClientInterface->eventPlay(m_PlayerID, m_PlayerName, m_PlayerType, m_IsRunning, m_TimeFrames);
|
||||
}
|
||||
}
|
||||
private:
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
string m_PlayerID;
|
||||
string m_PlayerName;
|
||||
char m_PlayerType;
|
||||
bool m_IsRunning;
|
||||
long long m_TimeFrames;
|
||||
};
|
||||
public:
|
||||
/** Helper class to notify the SPITClientInterface/user's app*/
|
||||
class NotifyPlaySPITObject : public SPIT_Handler::Runnable {
|
||||
public:
|
||||
NotifyPlaySPITObject(bool p_Started, bool p_Stopped,
|
||||
SPIT_ClientInterface* p_SPITClientInterface, const SPITType& p_SPITType, const SPITObject& p_SPITObject, const SPITPlayer::PlayObject& p_PlayObject) {
|
||||
m_Started = p_Started;
|
||||
m_Stopped = p_Stopped;
|
||||
m_SPITClientInterface = p_SPITClientInterface;
|
||||
m_SPITType = p_SPITType;
|
||||
m_SPITObject = p_SPITObject;
|
||||
m_PlayObject = p_PlayObject;
|
||||
}
|
||||
~NotifyPlaySPITObject() {}
|
||||
void run() {
|
||||
if (m_SPITClientInterface != NULL) {
|
||||
m_SPITClientInterface->eventPlayObject(m_PlayObject.getPlayerID(), m_Started, m_Stopped, m_SPITType, m_SPITObject, m_PlayObject);
|
||||
}
|
||||
}
|
||||
private:
|
||||
bool m_Started;
|
||||
bool m_Stopped;
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
SPITObject m_SPITObject;
|
||||
SPITType m_SPITType;
|
||||
SPITPlayer::PlayObject m_PlayObject;
|
||||
|
||||
};
|
||||
public:
|
||||
/** Helper class to notify the SPITClientInterface/user's app*/
|
||||
class NotifyReportPlayStatus: public SPIT_Handler::Runnable {
|
||||
public:
|
||||
NotifyReportPlayStatus(SPIT_ClientInterface* p_SPITClientInterface, const SPITType& p_SPITType, const SPITObject& p_SPITObject,
|
||||
long long p_FrameInsideObject, int p_Value) {
|
||||
m_SPITClientInterface = p_SPITClientInterface;
|
||||
m_SPITObject = p_SPITObject;
|
||||
m_SPITType = p_SPITType;
|
||||
m_FrameInsideObject = p_FrameInsideObject;
|
||||
m_Value = p_Value;
|
||||
}
|
||||
~NotifyReportPlayStatus() {}
|
||||
private:
|
||||
SPIT_ClientInterface* m_SPITClientInterface;
|
||||
SPITObject m_SPITObject;
|
||||
SPITType m_SPITType;
|
||||
long long m_FrameInsideObject;
|
||||
int m_Value;
|
||||
public:
|
||||
void run() {
|
||||
if (m_SPITClientInterface != NULL) {
|
||||
m_SPITClientInterface->eventPlayRemoteObjectStatus(m_SPITType, m_SPITObject, m_FrameInsideObject, m_Value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//--------- Remote ----------
|
||||
void sendRemoteObject(string p_SPITObjectID, int p_Valueppm = 0, char p_ValueFlag = 0x00);
|
||||
};
|
||||
|
||||
#endif /* SPIT_CLIENT_H */
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: SPIT_ClientInterface.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 17. April 2019, 16:15
|
||||
*/
|
||||
|
||||
#ifndef SPIT_CLIENTINTERFACE_H
|
||||
#define SPIT_CLIENTINTERFACE_H
|
||||
|
||||
//#include <string>
|
||||
|
||||
#include "SPITType.h"
|
||||
#include "SPITObject.h"
|
||||
#include "SPITPlayer.h"
|
||||
#include "SAD_DetectedServer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class SPIT_ClientInterface {
|
||||
public:
|
||||
|
||||
virtual string getClientProjectID() = 0;
|
||||
virtual string getClientProjectName() = 0;
|
||||
|
||||
/**
|
||||
* If a new server was found by the ServerAutoDetect mechanism, this function is called.
|
||||
* If a server can be reached via several IP addresses, the IP address is selected according to the following preference:<br>
|
||||
* 1.) If a loopback address is available, it is used.<br>
|
||||
* 2.) If an IP4 address is available, it is used.<br>
|
||||
* 3.) In the other cases the IP6 address is used.<br>
|
||||
* @param p_ID the id of the server (every started server should generate an id)
|
||||
* @param p_Name the name of the SPIT server
|
||||
* @param p_ComputerName the Hostname of the cpmputer on which the SPIT server is running
|
||||
* @param p_IP the selected ip address of the SPIT server
|
||||
* @param p_Port the port of the SPIT server
|
||||
* @param p_Addition sometimes server may have additional informations
|
||||
* @param p_isLoopback the server ip is a loopback address
|
||||
* @param p_IsIP4 the server ip is a ip4 address
|
||||
* @param p_IsIP6 the server ip is a ip6 address
|
||||
*/
|
||||
virtual void eventServerDetected(const SAD_DetectedServer& p_DetectedServer) = 0;
|
||||
virtual void eventServerLost(const SAD_DetectedServer& p_DetectedServer) = 0;
|
||||
|
||||
virtual void eventConnectionStatus(string p_ServerID, string p_ServerComputerName, string p_ServerName, int p_ServerStepTime, int p_ConnectionStatus, int p_OldConnectionStatus) = 0;
|
||||
|
||||
virtual void eventProjectReport(string p_ProjectID, string p_ProjectName, int p_FramesPerSeoond) = 0;
|
||||
virtual void eventProjectClosed(string p_ProjectID) = 0;
|
||||
|
||||
|
||||
virtual void eventStartProjectTransfer() = 0;
|
||||
virtual void eventEndProjectTransfer() = 0;
|
||||
|
||||
virtual void eventSPITType(bool p_New, const SPITType& p_SPITType) = 0;
|
||||
virtual void eventSPITTypeRemote(bool p_New, const SPITType& p_SPITType) = 0;
|
||||
|
||||
virtual void eventSPITTypeRemoved(const SPITType& p_SPITType) = 0;
|
||||
virtual void eventSPITTypeRemoteRemoved(const SPITType& p_SPITType) = 0;
|
||||
|
||||
|
||||
virtual void eventSPITObject(bool p_New, const SPITType& p_SPITType, const SPITObject& p_SPITObject) = 0;
|
||||
virtual void eventSPITObjectRemote(bool p_New, const SPITType& p_SPITType, const SPITObject& p_SPITObject) = 0;
|
||||
virtual void eventSPITObjectRemoved(const SPITType& p_SPITType, const SPITObject& p_SPITObject) = 0;
|
||||
virtual void eventSPITObjectRemoteRemoved(const SPITType& p_SPITType, const SPITObject& p_SPITObject) = 0;
|
||||
|
||||
virtual void eventPlay(string p_PlayerID, string p_PlayerName, char p_PlayerType, bool p_PlayerIsRunning, long long p_TimeFrames) = 0;
|
||||
|
||||
virtual void eventPlayObject(string p_PlayerID, bool p_Started, bool p_Stopped, const SPITType& p_SPITType, const SPITObject& p_SPITObject, const SPITPlayer::PlayObject& p_PlayObject) = 0;
|
||||
|
||||
|
||||
//REMOTE Server->Client
|
||||
virtual void eventPlayRemoteObjectStatus(const SPITType& p_SPITType, const SPITObject& p_SPITObject, long long p_FrameInsideObject, int p_Value) = 0;
|
||||
};
|
||||
|
||||
#endif /* SPIT_CLIENTINTERFACE_H */
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: SPIT_Handler.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 24. April 2019, 11:17
|
||||
*/
|
||||
|
||||
#ifndef SPIT_HANDLER_H
|
||||
#define SPIT_HANDLER_H
|
||||
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
#include <list>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class SPIT_Handler {
|
||||
public:
|
||||
class Runnable {
|
||||
public:
|
||||
Runnable() {};
|
||||
virtual ~Runnable();
|
||||
virtual void run() = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
static list<Runnable*> s_Runnables;
|
||||
static mutex s_MutexLock;
|
||||
static condition_variable s_ConditionVariable;
|
||||
static thread s_HandlerThread;
|
||||
|
||||
static bool s_WakeUp;
|
||||
static bool s_Close;
|
||||
static void run();
|
||||
public:
|
||||
static void addRunnable(Runnable* p_Runnable);
|
||||
static void closeHandler();
|
||||
};
|
||||
|
||||
#endif /* SPIT_HANDLER_H */
|
||||
|
||||
@@ -0,0 +1,950 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: SPIT_Message.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 3. April 2019, 08:51
|
||||
*/
|
||||
|
||||
#ifndef SPIT_MESSAGE_H
|
||||
#define SPIT_MESSAGE_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
static const string SPITID = "#spit#";
|
||||
//static char stringEmpty[] = "";
|
||||
static char nullChar[] = "\0";
|
||||
|
||||
class SPIT_Message {
|
||||
//----------- Header -----------
|
||||
public:
|
||||
|
||||
class Header {
|
||||
public:
|
||||
static const int BYTESLENGTH = 99;
|
||||
virtual ~Header();
|
||||
Header(const Header& orig);
|
||||
Header();
|
||||
//Members
|
||||
private:
|
||||
string m_SPITID;
|
||||
int m_SPITVersion;
|
||||
unsigned char m_MessageNumber;
|
||||
int m_BytesCount;
|
||||
string m_ServerID;
|
||||
string m_ClientID;
|
||||
int m_OPFlag;
|
||||
int m_ParseOffset = 0;
|
||||
|
||||
void initMembers();
|
||||
|
||||
public:
|
||||
const string getSPITID() const {
|
||||
return m_SPITID;
|
||||
}
|
||||
int getSPITVersion() const {
|
||||
return m_SPITVersion;
|
||||
}
|
||||
unsigned char getMessageNumber() const {
|
||||
return m_MessageNumber;
|
||||
}
|
||||
int getBytesCount() const {
|
||||
return m_BytesCount;
|
||||
}
|
||||
const string getServerID() const {
|
||||
return m_ServerID;
|
||||
}
|
||||
const string getClientID() const {
|
||||
return m_ClientID;
|
||||
}
|
||||
int getOPFlag() const {
|
||||
return m_OPFlag;
|
||||
}
|
||||
|
||||
//Receive
|
||||
public:
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
|
||||
//Send
|
||||
public:
|
||||
Header(int p_SPITVersion, int p_OPFlag);
|
||||
void setMessageNumber(unsigned char p_MessageNumber);
|
||||
void setServerID(string p_ServerID);
|
||||
void setClientID(string p_ID);
|
||||
void setOPFlag(int p_OPFlag);
|
||||
bool fillBytes(char* p_Bytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//----------- OPPart -----------
|
||||
public:
|
||||
class OPPart {
|
||||
|
||||
//Members
|
||||
protected:
|
||||
Header* m_Header;
|
||||
int m_ParseOffset;
|
||||
int m_BytesCount;
|
||||
private:
|
||||
void initMembers();
|
||||
public:
|
||||
virtual ~OPPart();
|
||||
// OPPart(const OPPart& orig);
|
||||
Header* getHeader() const {
|
||||
return m_Header;
|
||||
}
|
||||
|
||||
int getBytesCount() const {
|
||||
return m_BytesCount;
|
||||
}
|
||||
const string getServerID() const {
|
||||
if (m_Header == NULL) return "";
|
||||
return m_Header->getServerID();
|
||||
}
|
||||
const string getClientID() const {
|
||||
if (m_Header == NULL) return "";
|
||||
return m_Header->getClientID();
|
||||
}
|
||||
|
||||
int getOPFlag() const {
|
||||
if (m_Header == NULL) return -1;
|
||||
return m_Header->getOPFlag();
|
||||
}
|
||||
|
||||
//Receive
|
||||
public:
|
||||
OPPart(Header* p_Header, int p_OPFlag);
|
||||
void setHeader(Header* p_Header);
|
||||
virtual bool parse(char* p_Bytes, int p_ByteCounth)=0;
|
||||
|
||||
//Send
|
||||
public:
|
||||
OPPart();
|
||||
virtual bool fillBytes(char* p_Bytes, int p_ByteCount)=0;
|
||||
};
|
||||
|
||||
|
||||
//----------- SPIT_Message -----------
|
||||
|
||||
public:
|
||||
static const int SPITVERSION = 1;
|
||||
|
||||
//SPIT_Object value usage
|
||||
static const char VALUEUSE_DISCARD = 0x00; //value of SPITObejct is not used
|
||||
static const char VALUEUSE_INRANGE = 0x01; //value of SPITOBject in range 0 - 1000000ppm
|
||||
static const char VALUEUSE_OVERRIDE = 0x02; //value can be overridden
|
||||
|
||||
//SPIT Player type
|
||||
static const char PLAYERTYPE_MAIN = 0x02;
|
||||
static const char PLAYERTYPE_CONTINIOUS = 0x01;
|
||||
static const char PLAYERTYPE_DISCRETE = 0x00;
|
||||
|
||||
//PlayObject value usage
|
||||
static const char VALUEFLAG_DIRECT = 0x00; //use the vlue direct
|
||||
static const char VALUEFLAG_INCREASE = 0x01; //increase the value
|
||||
static const char VALUEFLAG_DECREASE = 0x02; //decrease the value
|
||||
|
||||
|
||||
SPIT_Message();
|
||||
virtual ~SPIT_Message();
|
||||
// SPIT_Message(const SPIT_Message& orig);
|
||||
|
||||
//Members
|
||||
private:
|
||||
char* m_MessageBytes;
|
||||
int m_MessageByteCount;
|
||||
Header* m_Header;
|
||||
OPPart* m_OPPart;
|
||||
bool m_MessageBytesCreated;
|
||||
|
||||
void initMembers();
|
||||
|
||||
//Receive
|
||||
public:
|
||||
SPIT_Message(char* p_MessageBytes, int p_MessageBytesLength);
|
||||
|
||||
// SPIT_Message(const SPIT_Message& orig);
|
||||
const Header* getHeader() const {
|
||||
return m_Header;
|
||||
}
|
||||
int getOPFlag() const {
|
||||
if (m_Header == NULL) return -1;
|
||||
return m_Header->getOPFlag();
|
||||
}
|
||||
const OPPart* getOPPart() const {
|
||||
return m_OPPart;
|
||||
}
|
||||
int getMesageByteCount() const {
|
||||
return m_MessageByteCount;
|
||||
}
|
||||
|
||||
OPPart* parse();
|
||||
|
||||
//Send
|
||||
public:
|
||||
SPIT_Message(OPPart* p_OPPart);
|
||||
bool fillBytes();
|
||||
const char* getMessageBytes();
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------ Connection ----------------------------------
|
||||
|
||||
//----------- Connect -----------
|
||||
public:
|
||||
class Connect : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 1;
|
||||
static const int BYTESLENGTH = 304;
|
||||
|
||||
private:
|
||||
string m_ClientComputerName;
|
||||
string m_ClientName;
|
||||
string m_LoginName;
|
||||
string m_LoginPassword;
|
||||
string m_ServerIP;
|
||||
int m_ServerPort;
|
||||
void initMembers();
|
||||
public:
|
||||
~Connect();
|
||||
// Connect(const Connect& orig);
|
||||
//Receive
|
||||
public:
|
||||
Connect(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
|
||||
const string getClientComputerName() const {
|
||||
return m_ClientComputerName;
|
||||
}
|
||||
const string getClientName() const {
|
||||
return m_ClientName;
|
||||
}
|
||||
const string getLoginName() const {
|
||||
return m_LoginName;
|
||||
}
|
||||
const string getLoginPassword() const {
|
||||
return m_LoginPassword;
|
||||
}
|
||||
const string getServerIP() const {
|
||||
return m_ServerIP;
|
||||
}
|
||||
int getServerPort() const {
|
||||
return m_ServerPort;
|
||||
}
|
||||
|
||||
//Send
|
||||
public:
|
||||
Connect();
|
||||
void setClientComputerName(string p_ComputerName);
|
||||
void setClientName(string p_ClientName);
|
||||
void setLoginName(string p_LoginName);
|
||||
void setLoginPassword(string p_LoginPassword);
|
||||
void setServerIP(string p_ServerIP);
|
||||
void setServerPort(int p_ServerPort);
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//----------- ConnectAnswer -----------
|
||||
|
||||
class ConnectAnswer : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 2;
|
||||
static const int BYTESLENGTH = 137;
|
||||
private:
|
||||
string m_ServerComputerName;
|
||||
string m_ServerName;
|
||||
bool m_Connected;
|
||||
int m_StepTime; //ms step size the Server will send play sequences
|
||||
|
||||
void initMembers();
|
||||
public:
|
||||
~ConnectAnswer();
|
||||
ConnectAnswer(const ConnectAnswer& orig);
|
||||
//Receive
|
||||
ConnectAnswer(Header* p_Header);
|
||||
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
|
||||
const string getServerComputerName() const {
|
||||
return m_ServerComputerName;
|
||||
}
|
||||
const string getServerName() const {
|
||||
return m_ServerName;
|
||||
}
|
||||
bool getConnected() const {
|
||||
return m_Connected;
|
||||
}
|
||||
int getStepTime() const {
|
||||
return m_StepTime;
|
||||
}
|
||||
|
||||
//Send
|
||||
public:
|
||||
ConnectAnswer();
|
||||
void setServerComputerName(string p_ServerComputerName);
|
||||
void setServerName(string p_ContollerName);
|
||||
void setConnected(bool p_Connected);
|
||||
void setStepTime(int p_StepTime_ms);
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//----------- Disconnect -----------
|
||||
|
||||
class Disconnect : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 3;
|
||||
static const int BYTESLENGTH = 4;
|
||||
|
||||
private:
|
||||
void initMembers();
|
||||
public:
|
||||
~Disconnect();
|
||||
Disconnect(const Disconnect& orig);
|
||||
//Receive
|
||||
Disconnect(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
|
||||
// Send
|
||||
public:
|
||||
Disconnect();
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//----------- Watchdog -----------
|
||||
|
||||
class Watchdog : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 8;
|
||||
static const int BYTESLENGTH = 4;
|
||||
private:
|
||||
void initMembers();
|
||||
public:
|
||||
~Watchdog();
|
||||
Watchdog(const Watchdog& orig);
|
||||
//Receive
|
||||
Watchdog(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
|
||||
// Send
|
||||
public:
|
||||
Watchdog();
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//----------- WatchdogAnswer -----------
|
||||
|
||||
class WatchdogAnswer : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 9;
|
||||
static const int BYTESLENGTH = 4;
|
||||
private:
|
||||
void initMembers();
|
||||
//Receive
|
||||
public:
|
||||
~WatchdogAnswer();
|
||||
WatchdogAnswer(const WatchdogAnswer& orig);
|
||||
WatchdogAnswer(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
|
||||
// Send
|
||||
public:
|
||||
WatchdogAnswer();
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
|
||||
//------------------------------ SPITProject ----------------------------------
|
||||
|
||||
//----------- ReportSPITProject -----------
|
||||
|
||||
class ReportSPITProject : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 11;
|
||||
static const int BYTESLENGTH = 113;
|
||||
private:
|
||||
string m_ProjectID;
|
||||
string m_ProjectName;
|
||||
int m_FramesPerSecond; //Frames per second
|
||||
|
||||
void initMembers();
|
||||
//Receive
|
||||
public:
|
||||
~ReportSPITProject();
|
||||
ReportSPITProject(const ReportSPITProject& orig);
|
||||
ReportSPITProject(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
const string getProjectID() const {
|
||||
return m_ProjectID;
|
||||
}
|
||||
const string getProjectName() const {
|
||||
return m_ProjectName;
|
||||
}
|
||||
int getFramesPerSecond() const {
|
||||
return m_FramesPerSecond;
|
||||
}
|
||||
// Send
|
||||
ReportSPITProject();
|
||||
|
||||
void setProjectID(string p_ClientID);
|
||||
void setProjectName(string p_ClientName);
|
||||
void setFramesPerSecond(const int p_FramesPerSecond);
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//----------- CloseSPITProject -----------
|
||||
|
||||
class CloseSPITProject : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 13;
|
||||
static const int BYTESLENGTH = 45;
|
||||
private:
|
||||
string m_ProjectID;
|
||||
|
||||
void initMembers();
|
||||
public:
|
||||
~CloseSPITProject();
|
||||
CloseSPITProject(const CloseSPITProject& orig);
|
||||
//Receive
|
||||
CloseSPITProject(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
const string getProjectID() const {
|
||||
return m_ProjectID;
|
||||
}
|
||||
// Send
|
||||
public:
|
||||
CloseSPITProject();
|
||||
|
||||
void setProjectID(string p_ClientID);
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//----------- StartProjectTransfer -----------
|
||||
class RequestProjectTransfer : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 15;
|
||||
static const int BYTESLENGTH = 4;
|
||||
private:
|
||||
void initMembers();
|
||||
public:
|
||||
~RequestProjectTransfer();
|
||||
RequestProjectTransfer(const RequestProjectTransfer& orig);
|
||||
//Receive
|
||||
RequestProjectTransfer(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
// Send
|
||||
public:
|
||||
RequestProjectTransfer();
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//----------- StartProjectTransfer -----------
|
||||
|
||||
class StartProjectTransfer : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 16;
|
||||
static const int BYTESLENGTH = 4;
|
||||
|
||||
private:
|
||||
void initMembers();
|
||||
public:
|
||||
~StartProjectTransfer();
|
||||
StartProjectTransfer(const StartProjectTransfer& orig);
|
||||
//Receive
|
||||
StartProjectTransfer(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
// Send
|
||||
public:
|
||||
StartProjectTransfer();
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//----------- EndProjectTransfer -----------
|
||||
class EndProjectTransfer : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 17;
|
||||
static const int BYTESLENGTH = 4;
|
||||
private:
|
||||
void initMembers();
|
||||
public:
|
||||
~EndProjectTransfer();
|
||||
EndProjectTransfer(const EndProjectTransfer& orig);
|
||||
//Receive
|
||||
EndProjectTransfer(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
// Send
|
||||
EndProjectTransfer();
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//---------------------------- SPIT_Types ----------------------------------
|
||||
|
||||
//----------- ReportSPITType -----------
|
||||
class ReportSPITType : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 21;
|
||||
static const int BYTESLENGTH = 168;
|
||||
private:
|
||||
bool m_Confirmed;
|
||||
string m_SPITTypeID;
|
||||
bool m_Fixed;
|
||||
bool m_ServerRemote;
|
||||
bool m_ServerProjectIndepended;
|
||||
string m_SPITTypeGroupName;
|
||||
string m_SPITTypeName;
|
||||
long long m_Delay;
|
||||
long long m_Duration;
|
||||
|
||||
void initMembers();
|
||||
public:
|
||||
~ReportSPITType();
|
||||
ReportSPITType(const ReportSPITType& orig);
|
||||
//Receive
|
||||
ReportSPITType(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
|
||||
bool getConfirmed() const {
|
||||
return m_Confirmed;
|
||||
}
|
||||
const string getID() const {
|
||||
return m_SPITTypeID;
|
||||
}
|
||||
bool getFixed() const {
|
||||
return m_Fixed;
|
||||
}
|
||||
bool getServerRemote() const {
|
||||
return m_ServerRemote;
|
||||
}
|
||||
bool getServerProjectIndepended() const {
|
||||
return m_ServerProjectIndepended;
|
||||
}
|
||||
const string getGroupName() const {
|
||||
return m_SPITTypeGroupName;
|
||||
}
|
||||
const string getName() const {
|
||||
return m_SPITTypeName;
|
||||
}
|
||||
long long getDelay() const {
|
||||
return m_Delay;
|
||||
}
|
||||
long long getDuration() const {
|
||||
return m_Duration;
|
||||
}
|
||||
// Send
|
||||
public:
|
||||
ReportSPITType();
|
||||
|
||||
void setConfirmed(bool p_Confirmed);
|
||||
void setID(string p_ID);
|
||||
void setFixed(bool p_Fixed);
|
||||
void setServerRemote(bool p_IsServerRemote);
|
||||
void setServerProjectIndepended(bool p_ProjectIndpended);
|
||||
void setGroupName(string p_GroupName);
|
||||
void setName(string p_Name);
|
||||
void setDelay(long long p_Delay);
|
||||
void setDuration(long long p_Duration);
|
||||
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//----------- RemoveSPITType -----------
|
||||
|
||||
class RemoveSPITType : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 23;
|
||||
static const int BYTESLENGTH = 45;
|
||||
private:
|
||||
string m_SPITTypeID;
|
||||
|
||||
void initMembers();
|
||||
public:
|
||||
~RemoveSPITType();
|
||||
RemoveSPITType(const RemoveSPITType& orig);
|
||||
//Receive
|
||||
RemoveSPITType(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
|
||||
const string getID() const {
|
||||
return m_SPITTypeID;
|
||||
}
|
||||
// Send
|
||||
RemoveSPITType();
|
||||
|
||||
void setID(string p_ID);
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
|
||||
|
||||
//---------------------------- SPITObjects ----------------------------------
|
||||
|
||||
//----------- ReportSPITObject -----------
|
||||
|
||||
class ReportSPITObject : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 31;
|
||||
static const int BYTESLENGTH = 339;
|
||||
private:
|
||||
bool m_Confirmed;
|
||||
string m_SPITObjectID;
|
||||
bool m_Fixed;
|
||||
bool m_ServerRemote;
|
||||
string m_SPITObjectName;
|
||||
string m_SPITTypeID;
|
||||
string m_ServerParams;
|
||||
long long m_FrameStart;
|
||||
long long m_FrameLength;
|
||||
long long m_FrameFadeInLength;
|
||||
long long m_FrameFadeOutLength;
|
||||
int m_ValueFactor;
|
||||
char m_ValueUse;
|
||||
int m_Track;
|
||||
string m_Remark;
|
||||
long long m_Delay;
|
||||
long long m_Duration;
|
||||
bool m_ActionAssigned;
|
||||
|
||||
void initMembers();
|
||||
public:
|
||||
~ReportSPITObject();
|
||||
ReportSPITObject(const ReportSPITObject& orig);
|
||||
//Receive
|
||||
ReportSPITObject(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
|
||||
bool getConfirmed() const {
|
||||
return m_Confirmed;
|
||||
}
|
||||
const string getID() const {
|
||||
return m_SPITObjectID;
|
||||
}
|
||||
bool getFixed() const {
|
||||
return m_Fixed;
|
||||
}
|
||||
bool getServerRemote() const {
|
||||
return m_ServerRemote;
|
||||
}
|
||||
const string getName() const {
|
||||
return m_SPITObjectName;
|
||||
}
|
||||
const string getSPITTypeID() const {
|
||||
return m_SPITTypeID;
|
||||
}
|
||||
const string getServerParams() const {
|
||||
return m_ServerParams;
|
||||
}
|
||||
long long getFrameStart() const {
|
||||
return m_FrameStart;
|
||||
}
|
||||
long long getFrameLength() const {
|
||||
return m_FrameLength;
|
||||
}
|
||||
long long getFrameFadeInLength() const {
|
||||
return m_FrameFadeInLength;
|
||||
}
|
||||
long long getFrameFadeOutLength() const {
|
||||
return m_FrameFadeOutLength;
|
||||
}
|
||||
int getValueFactor() const {
|
||||
return m_ValueFactor;
|
||||
}
|
||||
char getValueUse() const {
|
||||
return m_ValueUse;
|
||||
}
|
||||
int getTrack() const {
|
||||
return m_Track;
|
||||
}
|
||||
const string getRemark() const {
|
||||
return m_Remark;
|
||||
}
|
||||
long long getDelay() const {
|
||||
return m_Delay;
|
||||
}
|
||||
long long getDuration() const {
|
||||
return m_Duration;
|
||||
}
|
||||
bool getActionAssigned() const {
|
||||
return m_ActionAssigned;
|
||||
}
|
||||
// Send
|
||||
public:
|
||||
ReportSPITObject();
|
||||
|
||||
void setConfirmed(bool p_Confirmed);
|
||||
void setID(string p_ID);
|
||||
void setFixed(bool p_Fixed);
|
||||
void setServerRemote(bool p_IsRemote);
|
||||
void setName(string p_Name);
|
||||
void setSPITTypeID(string p_ID);
|
||||
void setServerParams(string p_Parameters);
|
||||
void setFrameStart(long long p_StartTime);
|
||||
void setFrameLength(long long p_Length);
|
||||
void setFrameFadeInLength(long long p_FadeInTime);
|
||||
void setFrameFadeOutLength(long long p_FadeOutTime);
|
||||
void setValueFactor(int p_Volume);
|
||||
void setValueUse(char p_ValueUse);
|
||||
void setTrack(int p_Track);
|
||||
void setRemark(string p_Description);
|
||||
void setDelay(long long p_Delay);
|
||||
void setDuration(long long p_Duration);
|
||||
void setActionAssigned(bool p_ActionAssigned);
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//----------- RemoveSPITObject -----------
|
||||
|
||||
class RemoveSPITObject : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 33;
|
||||
static const int BYTESLENGTH = 45;
|
||||
private:
|
||||
string m_SPITObjectID;
|
||||
|
||||
void initMembers();
|
||||
public:
|
||||
~RemoveSPITObject();
|
||||
RemoveSPITObject(const RemoveSPITObject& orig);
|
||||
//Receive
|
||||
RemoveSPITObject(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
|
||||
const string getID() const {
|
||||
return m_SPITObjectID;
|
||||
}
|
||||
// Send
|
||||
public:
|
||||
RemoveSPITObject();
|
||||
void setID(string p_ID);
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//---------------------------- SPITPlayer ----------------------------------
|
||||
|
||||
//----------- PlaySPITStart -----------
|
||||
|
||||
class PlaySPITStart : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 37;
|
||||
static const int BYTESLENGTH = 119;
|
||||
private:
|
||||
string m_PlayerID;
|
||||
string m_PlayerName;
|
||||
char m_PlayerType;
|
||||
bool m_PlayerIsRunning;
|
||||
long long m_Time; //Frames
|
||||
|
||||
void initMembers();
|
||||
public:
|
||||
~PlaySPITStart();
|
||||
PlaySPITStart(const PlaySPITStart& orig);
|
||||
//Receive
|
||||
PlaySPITStart(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
|
||||
const string getPlayerID() const {
|
||||
return m_PlayerID;
|
||||
}
|
||||
const string getPlayerName() const {
|
||||
return m_PlayerName;
|
||||
}
|
||||
char getPlayerType() const {
|
||||
return m_PlayerType;
|
||||
}
|
||||
bool getPlayerIsRunning() const {
|
||||
return m_PlayerIsRunning;
|
||||
}
|
||||
long long getTime() const {
|
||||
return m_Time;
|
||||
}
|
||||
|
||||
// Send
|
||||
public:
|
||||
PlaySPITStart();
|
||||
|
||||
void setPlayerID(string p_PlayerID);
|
||||
void setPlayerName(string p_PlayerName);
|
||||
void setPlayerType(char p_PlayerType);
|
||||
void setPlayerIsRunning(bool p_IsPlaying);
|
||||
void setTime(long long p_Time);
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//----------- PlaySPITObject -----------
|
||||
|
||||
class PlaySPITObject : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 38;
|
||||
static const int BYTESLENGTH = 100;
|
||||
private:
|
||||
string m_PlayerID;
|
||||
string m_SPITObjectID;
|
||||
long long m_FrameInsideObject; //Frames
|
||||
bool m_PlayPrePosition;
|
||||
int m_Value;
|
||||
char m_ValueFlag;
|
||||
|
||||
void initMembers();
|
||||
public:
|
||||
~PlaySPITObject();
|
||||
PlaySPITObject(const PlaySPITObject& orig);
|
||||
//Receive
|
||||
PlaySPITObject(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
|
||||
const string getPlayerID() const {
|
||||
return m_PlayerID;
|
||||
}
|
||||
const string getSPITObjectID() const {
|
||||
return m_SPITObjectID;
|
||||
}
|
||||
long long getFrameInsideObject() const {
|
||||
return m_FrameInsideObject;
|
||||
}
|
||||
bool getPlayPrePosition() const {
|
||||
return m_PlayPrePosition;
|
||||
}
|
||||
int getValue() const {
|
||||
return m_Value;
|
||||
}
|
||||
char getValueFlag() const {
|
||||
return m_ValueFlag;
|
||||
}
|
||||
// Send
|
||||
PlaySPITObject();
|
||||
|
||||
void setPlayerID(string p_PlayerID);
|
||||
void setID(string p_ID);
|
||||
void setFrameInsideObject(long long p_TimeInside);
|
||||
void setPlayPrePosition(bool p_PlayOldPosition);
|
||||
void setValue(int p_Value);
|
||||
void setValueFlag(char p_ValueFlag);
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
//----------- PlaySPITEnd -----------
|
||||
class PlaySPITEnd : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 39;
|
||||
static const int BYTESLENGTH = 45;
|
||||
private:
|
||||
string m_PlayerID;
|
||||
|
||||
void initMembers();
|
||||
public:
|
||||
~PlaySPITEnd();
|
||||
PlaySPITEnd(const PlaySPITEnd& orig);
|
||||
//Receive
|
||||
PlaySPITEnd(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
|
||||
const string getPlayerID() const {
|
||||
return m_PlayerID;
|
||||
}
|
||||
// Send
|
||||
public:
|
||||
PlaySPITEnd();
|
||||
void setPlayerID(string p_PlayerID);
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
|
||||
//----------- ReportPlayStatus -----------
|
||||
|
||||
class ReportPlayStatus : public OPPart {
|
||||
public:
|
||||
static const int OPFLAG = 40;
|
||||
static const int BYTESLENGTH = 57;
|
||||
private:
|
||||
string m_SPITObjectID;
|
||||
long long m_FrameInsideObject; //Frames
|
||||
int m_Value;
|
||||
|
||||
void initMembers();
|
||||
public:
|
||||
~ReportPlayStatus();
|
||||
ReportPlayStatus(const ReportPlayStatus& orig);
|
||||
//Receive
|
||||
ReportPlayStatus(Header* p_Header);
|
||||
bool parse(char* p_Bytes, int p_ByteCount);
|
||||
|
||||
const string getID() const {
|
||||
return m_SPITObjectID;
|
||||
}
|
||||
long long getFrameInsideObject() const {
|
||||
return m_FrameInsideObject;
|
||||
}
|
||||
int getValue() const {
|
||||
return m_Value;
|
||||
}
|
||||
// Send
|
||||
ReportPlayStatus();
|
||||
|
||||
void setID(string p_ID);
|
||||
void setFrameInsideObject(long long p_TimeInside);
|
||||
void setValue(int p_Value);
|
||||
bool fillBytes(char* p_MessageBytes, int p_ByteCount);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------- static helper functions ----------------------------
|
||||
public:
|
||||
static bool isSystemLittleEndian();
|
||||
static int getInt(char* p_Bytes, int p_ByteCount, int p_Offset);
|
||||
static int setInt(int p_Value, char* p_Bytes, int p_ByteCount, int p_Offset);
|
||||
static long long getLong(char* p_Bytes, int p_ByteCount, int p_Offset);
|
||||
static int setLong(long long p_Value, char* p_Bytes, int p_ByteCount, int p_Offset);
|
||||
static bool getBoolean(char* p_Bytes, int p_ByteCount, int p_Offset);
|
||||
static int setBoolean(bool p_Value, char* p_Bytes, int p_ByteCount, int p_Offset);
|
||||
static char getByte(char* p_Bytes, int p_ByteCount, int p_Offset);
|
||||
static int setByte(int p_Value, char* p_Bytes, int p_ByteCount, int p_Offset);
|
||||
/**
|
||||
* Returns the string char* of the part of the byte sequence (0x00 null terminated).
|
||||
* @param p_Bytes the byte array
|
||||
* @param p_Offset the startposition of strings bytes
|
||||
* @param p_Length the length of the string included the null terminate byte (0x00).<br>
|
||||
* The length of the string will be p_Length -1.
|
||||
* @return the String char*
|
||||
* @throws Exception if p_Bytes == null<br>
|
||||
* p_Offset less than 0<br>
|
||||
* p_Bytes.length less than p_Offset + p_Length<br>
|
||||
* No 0x00 null terminate byte is found
|
||||
*/
|
||||
static string getString(char* p_Bytes, int p_ByteCount, int p_Offset, int p_Length);
|
||||
|
||||
/**
|
||||
* Fill the p_String in the byte array.<br>
|
||||
* If p_String length is greater than p_Length -1, the p_String will be truncated.
|
||||
* CAUTION the return value should be freed after use.
|
||||
* @param p_String the string
|
||||
* @param p_Bytes the byte array where the string is filled
|
||||
* @param p_Offset the offset inside the byte array
|
||||
* @param p_Length the maximal length of the string included the null character.<br>
|
||||
* @throws Exception if p_String == NULL, p_Bytes == NULL<br>
|
||||
* p_Offset less than 0<br>
|
||||
* p_ByteCount less than p_Offset + p_Length
|
||||
* @return p_Length
|
||||
*/
|
||||
static int setString(string p_String, char* p_Bytes, int p_ByteCount, int p_Offset, int p_Length);
|
||||
/**
|
||||
* Compares two strings for equality.
|
||||
* @param p_String1 string terminated by null character
|
||||
* @param p_String2 string terminated by null character
|
||||
* @return true if both strings are equal<br>
|
||||
* false if the strings are NULL or not equal or not terminated by "\0"
|
||||
*/
|
||||
// static bool stringEqual(const char* p_String1, const char* p_String2);
|
||||
// static char* stringCopy(const char* p_String);
|
||||
static char* createByteArray(const OPPart* p_OPPart, int* p_BytesCount);
|
||||
};
|
||||
#endif /* SPIT_MESSAGE_H */
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: UnixSocket.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 12. April 2019, 15:58
|
||||
*/
|
||||
|
||||
#ifndef UNIXSOCKET_H
|
||||
#define UNIXSOCKET_H
|
||||
|
||||
#include "_SPITMACROS.h"
|
||||
#if defined(OS_MAC) || defined(OS_LINUX)
|
||||
|
||||
#include <ifaddrs.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <thread>
|
||||
|
||||
#include "SPITSocket.h"
|
||||
|
||||
class UnixSocket : public SPITSocket{
|
||||
public:
|
||||
static const int INVALID_SOCKET = -1;
|
||||
public:
|
||||
UnixSocket();
|
||||
virtual ~UnixSocket();
|
||||
private:
|
||||
int m_UDPSocketIP4;
|
||||
int m_UDPSocketIP6;
|
||||
public:
|
||||
void getAdaptersInfo();
|
||||
string getBroadcastIP4(IPAddress* p_IPAdress);
|
||||
int setBroadcast(bool p_Broadcast);
|
||||
|
||||
static int init();
|
||||
static int cleanUp();
|
||||
bool createSocket_UDP();
|
||||
int bindSocket(string p_ClientIP, string p_ClientPort);
|
||||
int sendMessageTo(int p_InetFamily, string p_ServerIP, string p_ServerPort, const char* p_MessageBytes, int p_MessageLength);
|
||||
int receiveMessage(int p_InetFamily, char* p_Buffer, int p_BufferLength, string* p_ServerIP);
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* UNIXSOCKET_H */
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: Watchdog.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 22. April 2019, 13:02
|
||||
*/
|
||||
|
||||
#ifndef WATCHDOG_H
|
||||
#define WATCHDOG_H
|
||||
|
||||
#include "_SPITMACROS.h"
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
class Watchdog {
|
||||
public:
|
||||
class Listener {
|
||||
public:
|
||||
virtual void sendWatchdog()=0;
|
||||
virtual void eventWatchdogLost()=0;
|
||||
};
|
||||
|
||||
static int WATCHDOGTIME;
|
||||
static bool s_StopWatchdog;
|
||||
|
||||
Watchdog(Listener* p_Listener);
|
||||
virtual ~Watchdog();
|
||||
|
||||
private:
|
||||
Listener* m_Listener;
|
||||
|
||||
mutex m_MutexLock;
|
||||
condition_variable m_ConditionVariable;
|
||||
thread* m_WatchdogThread;
|
||||
|
||||
bool m_Answered;
|
||||
|
||||
void runWatchdog();
|
||||
public:
|
||||
void startWatchdog();
|
||||
void answerWatchdog();
|
||||
void stopWatchdog();
|
||||
};
|
||||
|
||||
#endif /* WATCHDOG_H */
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: WindowsSocket.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 11. April 2019, 08:36
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef WINDOWSSOCKET_H
|
||||
#define WINDOWSSOCKET_H
|
||||
|
||||
#include "_SPITMACROS.h"
|
||||
#if defined(OS_WINDOWS)
|
||||
#include "WindowsSocket.h"
|
||||
|
||||
#include <WinSock2.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <thread>
|
||||
|
||||
#include "SPITSocket.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class WindowsSocket : public SPITSocket{
|
||||
public:
|
||||
WindowsSocket();
|
||||
virtual ~WindowsSocket();
|
||||
private:
|
||||
SOCKET m_UDPSocketIP4;
|
||||
SOCKET m_UDPSocketIP6;
|
||||
public:
|
||||
void getAdaptersInfo();
|
||||
string getBroadcastIP4(IPAddress* p_IPAdress);
|
||||
int setBroadcast(bool p_Broadcast);
|
||||
static int init();
|
||||
static int cleanUp();
|
||||
bool createSocket_UDP();
|
||||
int bindSocket(string p_ClientIP, string p_ClientPort);
|
||||
int sendMessageTo(int p_InetFamily, string p_ServerIP, string p_ServerPort, const char* p_MessageBytes, int p_MessageLength);
|
||||
int receiveMessage(int p_InetFamily, char* p_Buffer, int p_BufferLength, string* p_ServerIP);
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* WINDOWSSOCKET_H */
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: _SPITMACROS.h
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 13. April 2019, 13:37
|
||||
*/
|
||||
|
||||
#ifndef _SPITMACROS_H
|
||||
#define _SPITMACROS_H
|
||||
|
||||
//To compile for a specific operating system, you must change the precompiler comments.
|
||||
|
||||
//In windows Ws2_32.lib Iphlpapi.lib (in gcc: -liphlpapi -lole32) should be added to the linker options
|
||||
#ifndef OS_WINDOWS
|
||||
// #define OS_WINDOWS
|
||||
// #include <WinSock2.h> //include this here, because it must be included before string.h .. is included
|
||||
#endif
|
||||
#ifndef OS_MAC
|
||||
// #define OS_MAC
|
||||
// #include <unistd.h>
|
||||
// #include<uuid/uuid.h>
|
||||
#endif
|
||||
#ifndef OS_LINUX
|
||||
#define OS_LINUX
|
||||
#include <unistd.h>
|
||||
#include<uuid/uuid.h>
|
||||
#endif
|
||||
|
||||
//To output debug information (printf calls in the code)
|
||||
//you must set or comment out this precompiler definition
|
||||
#ifndef DEBUGOUTPUT
|
||||
#define DEBUGOUTPUT
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//--------- OS specific functions ---------
|
||||
/** Returns an guid */
|
||||
string createGUID();
|
||||
/** Returns the name of the client's host computer*/
|
||||
string getClientHostName();
|
||||
|
||||
|
||||
|
||||
#endif /* _SPITMACROS_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,933 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: MySPITApp.cpp
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 17. April 2019, 06:24 pm
|
||||
* Changed on 01. May 2020, 12:00 am
|
||||
*
|
||||
* Description:
|
||||
* A SPITClient defines actions (functions) and connects to a SPITServer.
|
||||
* The actions are assigned to SPITTypes.
|
||||
* The client may create its own SPITTypes, which are sended to the server or receives SPITTypes from the server.
|
||||
* Each SPIType can trigger exactly one action.
|
||||
* The server may use this SPITTypes to create and play SPITObjects, he can create several SPITObjects from one SPITType.
|
||||
* Each SPITObject is assigned exactly one SPITType.
|
||||
* When the server plays a SPITObject, an event function (eventPlayObject) is called in the client.
|
||||
* The client can then trigger the action for the assigned SPITType.
|
||||
* --------------------------------------------------------------------------------------------------
|
||||
* all event.. functions are executed by a single SPIT_Handler thread.
|
||||
* -> The event functions are called singlethreaded one after the other.
|
||||
* --------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "MyApp.h"
|
||||
|
||||
string MyApp::s_ClientName = "MySPITApp_Client"; //Name of this Client
|
||||
string MyApp::s_ClientProjectName = "MySPITAppProject"; //Name of the client'loaded project
|
||||
string MyApp::s_ClientProjectID = s_ClientProjectName; //ID of the client's project - maybe the same as the name or a specific id
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
//Win32 Main Function - application entry
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||
PSTR lpCmdLine, INT nCmdShow) {
|
||||
|
||||
return main();
|
||||
}
|
||||
#endif
|
||||
|
||||
//UNIX and Win64 Main function - application entry
|
||||
int main() {
|
||||
MyApp* ptrMyApp;
|
||||
//Create a MyApp instance
|
||||
ptrMyApp = new MyApp();
|
||||
|
||||
//load a client project
|
||||
//the client project may belong to a server's project or may be independend of server's projects
|
||||
//if the client project belongs to a specific server project
|
||||
// -> add some code in the function eventProjectReport(..) (for excample create special SPITTypes or Actions
|
||||
//if the client project is independend od server's project
|
||||
// -> use loadClientProject() to create all SPITypes and actions
|
||||
//An action is bound to a SPITType and called when the server plays a SPITObject that references the SPITType
|
||||
// see eventPlayObject
|
||||
ptrMyApp->loadClientProject();
|
||||
|
||||
//start autodetection of SPITServers
|
||||
//autodetection of SPITServers ends automaticallay when this SPITClient is connected to a SPITServer
|
||||
ptrMyApp->startServerAutoDetect();
|
||||
|
||||
//This application is multthreaded, in the background all is done by several threads
|
||||
//all events are delegated to SPIT_Handler
|
||||
//-> the eventxxx functions are called by the one and only SPIT_Handler's thread s_HandlerThread
|
||||
//-> the eventxxx functions are called singlethreaded
|
||||
|
||||
//Normally MyApp will have a user interface to decide when the app has to be closed.
|
||||
//Actual we have no user interface -> sleep a while
|
||||
//We can put the actual thread to sleep, because the events are executed by the SPIT_Handler-Thread s_HandlerThread.
|
||||
|
||||
printf("---THE APPLICATION RUNS FOR 60 SECONDS AND STOPS AUTOMATICALLY---\n\n");
|
||||
|
||||
this_thread::sleep_for(chrono::milliseconds(30000));
|
||||
ptrMyApp->testLiveShowRemote(); //This is an excample how to remote control the liveSHOWsoftware
|
||||
this_thread::sleep_for(chrono::milliseconds(30000));
|
||||
|
||||
//perhaps you should save the client project
|
||||
|
||||
//close MyApp instance
|
||||
delete ptrMyApp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
MyApp::MyApp() {
|
||||
//create a new SPIT_Client instance
|
||||
//the SPIT_Client will do the main work for you (receiving/sending SPIT_Messages ....)
|
||||
m_SPIT_Client = new SPIT_Client(this);
|
||||
|
||||
//You need to give your application a descriptive name
|
||||
m_SPIT_Client->setName(s_ClientName);
|
||||
|
||||
//The following members are set in loadClientProject function.
|
||||
m_ClientProjectName = "";
|
||||
m_ClientProjectID = ""; //id can be the same as the project name
|
||||
|
||||
//The following members are set in the eventConnectionStatus
|
||||
m_ServerID = "";
|
||||
m_ServerComputerName = "";
|
||||
m_ServerName = "";
|
||||
m_ServerStepTime = -1;
|
||||
|
||||
//The follwing members are set in eventProjectReport
|
||||
m_ServerProjectID = "";
|
||||
m_ServerProjectName = "";
|
||||
m_ServerFramesPerSecond = 44100; //is reset in eventProjectReport.
|
||||
//perhaps you may save the value from the last connection and set it here
|
||||
//liveSHOWsoftware will use 44100 frames per second as time resolution
|
||||
//All times are given in frames,
|
||||
//with this parameter you can convert the times into milliseconds/seconds ...
|
||||
|
||||
|
||||
//Used to decide if a reconnection is tried after the connection is lost
|
||||
//see eventServerDetected and eventConnectionStatus
|
||||
m_FlagReconnect = false;
|
||||
}
|
||||
|
||||
|
||||
MyApp::~MyApp() {
|
||||
//To close the connection and all other stuff delete the SPIT_Client instance
|
||||
if (m_SPIT_Client != NULL) {
|
||||
delete m_SPIT_Client;
|
||||
}
|
||||
}
|
||||
|
||||
//Following functions fullfill the SPIT_ClientInterface
|
||||
//They are needed when the server sends his project, see eventProjectReport
|
||||
//and they should be set in loadClientProject
|
||||
string MyApp::getClientProjectID() {
|
||||
return m_ClientProjectID;
|
||||
}
|
||||
string MyApp::getClientProjectName() {
|
||||
return m_ClientProjectName;
|
||||
}
|
||||
|
||||
void MyApp::loadClientProject() {
|
||||
//----- close the actual client project -----
|
||||
//inform the SPIT_Client that the actual project will close
|
||||
//If there is actual no connection to the server nothing happens
|
||||
if (m_SPIT_Client != NULL) {
|
||||
m_SPIT_Client->clientProjectClose();
|
||||
}
|
||||
//close the project
|
||||
|
||||
//----- load new client project -----
|
||||
// Add your loading code here
|
||||
//If your application is a small one using only a few fixed actions
|
||||
//you may keep the things simple and code all loading here
|
||||
|
||||
m_ClientProjectID = s_ClientProjectID; //maybe the same as s_ClientProjectName
|
||||
m_ClientProjectName = s_ClientProjectName;
|
||||
|
||||
|
||||
//Create SPITTypes for all functions of this client
|
||||
//--- Excample ---
|
||||
//the client owns two fixed functionality named "Action1" and "Action2"
|
||||
if (m_SPIT_Client != NULL) {
|
||||
|
||||
//FIXED SPITTYPES
|
||||
//Create SPITTypes for all discrete and unchangable functions of this client. Fixed means the server can't change or remove the SPITType.
|
||||
//-> Create a SPITTypes according to the following patterns
|
||||
//Excample "Action1"
|
||||
SPITType* ptrSPITType1Fix;
|
||||
ptrSPITType1Fix = m_SPIT_Client->createSPITTypeFixed("MySPITAPP_Action1ID", "MyActionGroupName", "FixedAction1", 0, 0);
|
||||
//When an action exist which shpuld be done whenever a SPITObject with this SPITType is played, <br>
|
||||
//then you should 'setAssignedActionType' to true
|
||||
m_SPIT_Client->setActionSPITType(ptrSPITType1Fix->getID(), true);
|
||||
//Excample "Action2"
|
||||
SPITType* ptrSPITType2Fix;
|
||||
ptrSPITType2Fix = m_SPIT_Client->createSPITTypeFixed("MySPITAPP_Action2ID", "MyActionGroupName", "FixedAction2", 0, 0);
|
||||
//When an action exist which shpuld be done whenever a SPITObject with this SPITType is played, <br>
|
||||
//then you should 'setAssignedActionType' to true
|
||||
m_SPIT_Client->setActionSPITType(ptrSPITType2Fix->getID(), true);
|
||||
|
||||
//later in the eventPlayObject you can react with your action code for "Action1" and "Action2"
|
||||
|
||||
//CHANGABLE SPITYPES
|
||||
//Create SPITTypes which are changable or temporarly, the server may change or delete them.
|
||||
ptrSPITType2Fix = m_SPIT_Client->createSPITType("MySPITAPP_ActionTemp1ID", "MyActionGroupName", "TempAction1", 0, 0, false, true);
|
||||
//When an action exist which shpuld be done whenever a SPITObject with this SPITType is played, <br>
|
||||
//then you should 'setAssignedActionType' to true
|
||||
m_SPIT_Client->setActionSPITType(ptrSPITType2Fix->getID(), true);
|
||||
|
||||
|
||||
}
|
||||
//--- End Excample ---
|
||||
|
||||
//----- inform the SPIT_Client that a new project is loaded -----
|
||||
if (m_SPIT_Client != NULL) {
|
||||
m_SPIT_Client->clientProjectLoaded();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
//---------- ServerAutoDetection ----------
|
||||
|
||||
void MyApp::startServerAutoDetect() {
|
||||
if (m_SPIT_Client != NULL) {
|
||||
m_SPIT_Client->startServerAutoDetect();
|
||||
}
|
||||
}
|
||||
void MyApp::stopServerAutoDetect() {
|
||||
if (m_SPIT_Client != NULL) {
|
||||
m_SPIT_Client->stopServerAutoDetect();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
//----- All events are delegated to the SPIT_Handler.
|
||||
//----- The follwoing event functions are called
|
||||
//----- by the one thread s_HandlerThread of the SPIT_Handler
|
||||
//------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Is always called when a new SPIT server is found.<br>
|
||||
* For this you have to call SPIT_Client::startServerAutoDetect.<br>
|
||||
* @param p_DetectedServer a reference to a copy of a SAD_DetectedServer instance.<br>
|
||||
* After this function call the copy of the SAD_DetectedServer will be deleted!!<br>
|
||||
*/
|
||||
void MyApp::eventServerDetected(const SAD_DetectedServer& p_DetectedServer) {
|
||||
//fetch the infoemations from the p_DetectedServer
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("mySPITApp\n");
|
||||
printf("-----> SERVER DETECTED\n");
|
||||
printf(" Name: %s\n", p_DetectedServer.getName().data());
|
||||
printf(" ID: %s\n", p_DetectedServer.getID().data());
|
||||
printf(" Computer: %s\n", p_DetectedServer.getComputerName().data());
|
||||
printf(" IP: %s\n", p_DetectedServer.getIP().data());
|
||||
printf(" Port: %s\n", p_DetectedServer.getPort().data());
|
||||
printf(" Addition: %s\n", p_DetectedServer.getAdditions().data());
|
||||
printf(" ClientIP: %s\n", p_DetectedServer.getClientIP().data());
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
bool boolSuccess;
|
||||
|
||||
//---------- RECONNECTION ----------
|
||||
//If a connection has been established and the connection is lost -> reconnect
|
||||
boolSuccess = false;
|
||||
if (m_FlagReconnect == true) {
|
||||
//check if the server is the same as prior connected
|
||||
if (m_ServerID == p_DetectedServer.getID()) {
|
||||
//reconnect
|
||||
if (m_SPIT_Client != NULL) {
|
||||
stopServerAutoDetect();
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: reconnect to %s ", p_DetectedServer.getIP().data());
|
||||
#endif
|
||||
boolSuccess = m_SPIT_Client->connect(p_DetectedServer.getIP(), p_DetectedServer.getPort(), p_DetectedServer.getClientIP(), "0"); //ClientPort = "0" meeans use any port
|
||||
if (boolSuccess == true) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------
|
||||
// You have three Options to use the detected server
|
||||
// OPTION 1 Use the first server found
|
||||
// OPTION 2 Use the first server found that fulfills specific conditions
|
||||
// OPTION 3 take a copy of the p_DetectedServer and do connection later
|
||||
// SAD_DetectedServer o_DetectedServer = p_DetectedServer; //this will call the copy constructor
|
||||
// ---------------------------------------
|
||||
|
||||
//Excample use the first detected LOOPBACK server, means the server runs on the same computer as this client
|
||||
//if (p_DetectedServer.getIpIsLoopback() == true) { //omit the if condition if you want to use the first server found
|
||||
|
||||
boolSuccess = false;
|
||||
//Stop auto detection because a suitable server was found
|
||||
stopServerAutoDetect();
|
||||
if (m_SPIT_Client != NULL) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: connect to %s ", p_DetectedServer.getIP().data());
|
||||
#endif
|
||||
boolSuccess = m_SPIT_Client->connect(p_DetectedServer.getIP(), p_DetectedServer.getPort(), p_DetectedServer.getClientIP(), "0"); //ClientPort = "0" meeans use any port
|
||||
}
|
||||
if (boolSuccess == false) {
|
||||
//connection message could not be sent
|
||||
//perhaps restart AutoDetection
|
||||
startServerAutoDetect();
|
||||
}
|
||||
|
||||
// } //Excample
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is always called when a SPIT server does not respond anymore.<br>
|
||||
* For this you have to call SPIT_Client::startServerAutoDetect.<br>
|
||||
* This is an information used by autodetection and not by an established connection.<br>
|
||||
* <br>
|
||||
* When a connection to a SPITServer is established, the autodetection should be stopped.<br>
|
||||
* The connection lost event is detected by eventConnectionStatus<br>
|
||||
* <br>
|
||||
* @param p_DetectedServer a reference to a copy of a SAD_DetectedServer instance.<br>
|
||||
* After this function call the copy of the SAD_DetectedServer will be deleted!!<br>
|
||||
*/
|
||||
void MyApp::eventServerLost(const SAD_DetectedServer& p_DetectedServer) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("\n");
|
||||
printf("-----> SERVER LOST\n");
|
||||
printf("Name: %s IP: %s\n", p_DetectedServer.getName().data(), p_DetectedServer.getIP().data());
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------
|
||||
//---------- Connecting event ----------
|
||||
|
||||
void MyApp::eventConnectionStatus(string p_ServerID, string p_ServerComputerName, string p_ServerName, int p_ServerStepTime, int p_ConnectionStatus, int p_OldConnectionStatus) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventConnectionStatus %d ", p_ConnectionStatus);
|
||||
#endif
|
||||
switch(p_ConnectionStatus) {
|
||||
case SPIT_Client::CONNECTION_NONE:
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf(" not connected\n");
|
||||
#endif
|
||||
break;
|
||||
case SPIT_Client::CONNECTION_NONESERVER:
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf(" connection terminated by server\n");
|
||||
#endif
|
||||
//call eventProjectClosed because this may not be sended by the server,
|
||||
//when the connstion is closed
|
||||
eventProjectClosed(m_ServerProjectID);
|
||||
|
||||
//Server has terminated the connection -> start a new game
|
||||
m_FlagReconnect = false;
|
||||
startServerAutoDetect();
|
||||
break;
|
||||
case SPIT_Client::CONNECTION_OK:
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf(" connection established\n");
|
||||
#endif
|
||||
stopServerAutoDetect(); //normally you should stop the autodetection before you try a connection
|
||||
//This is redundand
|
||||
m_ServerID = p_ServerID;
|
||||
m_ServerComputerName = p_ServerComputerName;
|
||||
m_ServerName = p_ServerName;
|
||||
m_ServerStepTime = p_ServerStepTime;
|
||||
|
||||
//Maybe you want to reconnect, see eventServerDetected(...)
|
||||
//Here the connection is established -> don't reconnect at eventServerDetected(...)
|
||||
m_FlagReconnect = false;
|
||||
break;
|
||||
case SPIT_Client::CONNECTION_LOST:
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf(" connection lost\n");
|
||||
#endif
|
||||
//Maybe you want to reconnect, see eventServerDetected(...)
|
||||
//We have lost the connection -> set the flag to true and start the autodetection to reconnect at eventServerDetected(...)
|
||||
m_FlagReconnect = true;
|
||||
startServerAutoDetect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//---------- Server's Project events ------------------------
|
||||
/**
|
||||
* The Server reports his loaded project
|
||||
* Called when<br>
|
||||
* a) the connection to the server is established.<br>
|
||||
* b) server load a new project<br>
|
||||
* c) server saves the project under a new name<br>
|
||||
* @param p_ProjectID the server project's id<br>
|
||||
* (maybe the filename of the project or a part o it or the same as p_ProjectName)
|
||||
* @param p_ProjectName the server project's name
|
||||
* @param p_FramesPerSeoond All times in SPIT are given in frames. FramesPerSecond can be used to convert frames to seconds....
|
||||
*/
|
||||
void MyApp::eventProjectReport(string p_ProjectID, string p_ProjectName, int p_FramesPerSeoond) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("\n");
|
||||
printf("MySPITApp: eventProjectReport ID: %s Name: %s FramesPerSecond: %d\n", p_ProjectID.data(), p_ProjectName.data(), p_FramesPerSeoond);
|
||||
#endif
|
||||
m_ServerProjectID = p_ProjectID;
|
||||
m_ServerProjectName = p_ProjectName;
|
||||
m_ServerFramesPerSecond = p_FramesPerSeoond;
|
||||
|
||||
//set the frames per second as the server - perhaps the client's time values have to be recalculated.
|
||||
m_ServerFramesPerSecond = p_FramesPerSeoond;
|
||||
|
||||
//When the this client's project depends on the server's project -> load some specific informations here
|
||||
|
||||
}
|
||||
/**
|
||||
* Called when the server closes his project.<br>
|
||||
* @param p_ProjectID the id of the project<br>
|
||||
* The server loads only one project at time-> the ID is not actually necessary
|
||||
*/
|
||||
void MyApp::eventProjectClosed(string p_ProjectID) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventProjectClosed ID: %s\n", p_ProjectID.data());
|
||||
printf("\n");
|
||||
#endif
|
||||
//If we don't save SPITServer's project specific information
|
||||
//perhaps close all SPITObjects and RemoteSPITObjects to avoid conflicts, when the SPITServer loads a new project
|
||||
//SPITObject::clearSPITObjects();
|
||||
//SPITObject::clearSPITObjectsRemote();
|
||||
}
|
||||
|
||||
/**
|
||||
* The server starts the transfer of its project, that means:.<br>
|
||||
* All SPITTypes and SPITObjects available on the server are transferred in the following.<br>
|
||||
* Several calls of eventSPITType and eventSPITObject will occur.<br>
|
||||
* At the end eventEndProjectTransfer is called.
|
||||
*/
|
||||
void MyApp::eventStartProjectTransfer() {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventStartProjectTransfer\n");
|
||||
#endif
|
||||
}
|
||||
/**
|
||||
* The transfer of the server's SPITTypes and SPITObjects is finished.<br>
|
||||
* AFter this all eventSPITType and eventSPITObject means that new types , objects are created or changed.
|
||||
*/
|
||||
void MyApp::eventEndProjectTransfer() {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventEndProjectTransfer\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------
|
||||
//--------- SPITType events ----------
|
||||
|
||||
// SPITTypes describing an action or a type of an action.
|
||||
// To trigger an action SPITObjects are used. Every SPITObject has one of the SPITTypes assigned.<br>
|
||||
// There are two ways action can be triggered, either the server triggers an action on the client,
|
||||
// or the client sends remote control commands to the server.
|
||||
// a) normal types that are comitted to the client and played per SPITObjects by server, so the client can react with actions.
|
||||
// b) Remote types are used for remote control of the server and are played by the client via SPIT objects.
|
||||
//All normal SPITTypes are listet in a static unordered_map in the SPITType class.
|
||||
//All remote SPITTypes are listet in a seperate static unordered_map in the SPITType class.
|
||||
//You can use the SPITType::get... functions to deal with them.
|
||||
//The SPITType class has a static recursive_mutex, you get a pointer of the mutex by: SPITType::getMutex();
|
||||
//To be thread save you should cover your code with a lock sequence:
|
||||
/*
|
||||
{ //start of the lock sequence
|
||||
unique_lock<recursive_mutex> o_LockType(*SPITType::getMutex());
|
||||
//got the lock
|
||||
|
||||
//fetch SPITType and deal with, but don't waste time while you holding the lock
|
||||
//Excample
|
||||
SPITType* ptrSPITType;
|
||||
for (int i = 0; i < SPITType::getSPITTypeCount(); i ++) {
|
||||
ptrSPITType = SPITType::getSPITType(i);
|
||||
if (ptrSPITType == NULL) break;
|
||||
//Do something with ptrSPITType
|
||||
//bew aware after you leave the lock sequence the ptrSPITType is no longer save!!
|
||||
}
|
||||
} //end of the lock sequence
|
||||
|
||||
//For Remote Types you can use the getSPITTypeRemote... functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Called when the server has created, loaded or changed a SPITType.<br>
|
||||
* May also occur when the server confirms a SPITType created or changed by the client.<br>
|
||||
* @param p_New true = server created a new SPITType<br>
|
||||
* false = server changed a existing SPITType<br>
|
||||
* @param p_SPITType a reference to a copy of the SPITType instance.<br>
|
||||
* The reference is deleted after this function call!!
|
||||
*/
|
||||
void MyApp::eventSPITType(bool p_New, const SPITType& p_SPITType) {
|
||||
//fetch information of the SPITType
|
||||
if (p_New) {
|
||||
//a new SPITType is created
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventSPITType NEW");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
//an existing SPITType is changed
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventSPITType CHANGED");
|
||||
#endif
|
||||
}
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf(" ID: %s GroupName: %s Name: %s confirmed: %d\n", p_SPITType.getID().data(), p_SPITType.getGroupName().data(), p_SPITType.getName().data(), p_SPITType.getConfirmed());
|
||||
#endif
|
||||
|
||||
//Check your actions
|
||||
//Whenever you provide an action for this SPITType take this over in your code.
|
||||
//call m_SPIT_Client->setActionSPITType(p_SPITType.getID(), true);
|
||||
|
||||
//for our little excample as described in loadClientProject we do following
|
||||
if (m_SPIT_Client != NULL) {
|
||||
//This may be redundand, because we defined the SPITTypes as fixed, so the server can't change them
|
||||
//But foe all SPITTypes which are not fixed we need to setActionSPITType
|
||||
if ("MySPITAPP_Action1ID" == p_SPITType.getID()) {
|
||||
m_SPIT_Client->setActionSPITType(p_SPITType.getID(), true);
|
||||
}
|
||||
if ("MySPITAPP_Action2ID" == p_SPITType.getID()) {
|
||||
m_SPIT_Client->setActionSPITType(p_SPITType.getID(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Called when the server has created or changed a Remote SPITType.<br>
|
||||
* Remote SPITType are used in Remote SPITObjects. A Remote SPITObject is used to remote control the SPITServer.
|
||||
* @param p_New true = server created a new SPITType<br>
|
||||
* false = server changed a existing SPITType<br>
|
||||
* @param p_SPITType a reference to a copy of the SPITType instance.<br>
|
||||
* The reference is deleted after this function call!!
|
||||
*/
|
||||
void MyApp::eventSPITTypeRemote(bool p_New, const SPITType& p_SPITType) {
|
||||
if (p_New) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventSPITTypeRemote NEW");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
//we had to inform all Remote SPITObjects using the p_SPITType
|
||||
//perhaps the SPITObject uses information from the SPITType
|
||||
SPITObject* ptrSPITObject;
|
||||
int intSPITObjectCount;
|
||||
intSPITObjectCount = SPITObject::getSPITObjectRemoteCount();
|
||||
for (int intObject = 0; intObject < intSPITObjectCount; intObject++) {
|
||||
ptrSPITObject = SPITObject::getSPITObjectRemote(intObject);
|
||||
if (ptrSPITObject == NULL) continue;
|
||||
if (ptrSPITObject->getSPITTypeID() == p_SPITType.getID()) {
|
||||
//call ecentSPITObjectRemote
|
||||
eventSPITObjectRemote(false, p_SPITType, *ptrSPITObject);
|
||||
}
|
||||
}
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventSPITTypeRemote CHANGED");
|
||||
#endif
|
||||
}
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf(" ID: %s GroupName: %s Name: %s confirmed: %d\n", p_SPITType.getID().data(), p_SPITType.getGroupName().data(), p_SPITType.getName().data(), p_SPITType.getConfirmed());
|
||||
#endif
|
||||
//this is a remote SPITType, if you want you can list this for later remote use.
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the server has removed a SPITType.<br>
|
||||
* After this function has been exited the SPITType is emeoved from the SPITType-List and the pointer is deleted.<br>
|
||||
* So use the pointer immediately or use the copyconstructor to make a copy for extended use.
|
||||
* You have to release the copy yourself later (delete ptr...)
|
||||
* @param p_SPITType a reference to a copy of the SPITType instance.<br>
|
||||
* The reference is deleted after this function call!!
|
||||
*/
|
||||
void MyApp::eventSPITTypeRemoved(const SPITType& p_SPITType) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventSPITType Removed");
|
||||
printf(" ID: %s GroupName: %s Name: %s\n", p_SPITType.getID().data(), p_SPITType.getGroupName().data(), p_SPITType.getName().data());
|
||||
#endif
|
||||
|
||||
//Check your actions
|
||||
//take the removal of the SPITType over in your code
|
||||
|
||||
//CAUTION: Deleted SPIT types can be added later again (perhaps per UNDO on the SPITServer)
|
||||
//-> don't remove your assigned action immediately - keep it to reassign it later
|
||||
}
|
||||
/**
|
||||
* Called when the server has removed a Remote SPITType.<br>
|
||||
* Remote SPITType are used in Remote SPITObjects. A Remote SPITObject is used to remote control the SPITServer.
|
||||
* After this function has been exited the SPITType is emeoved from the Remote SPITType-List and the pointer is deleted.<br>
|
||||
* So use the pointer immediately or use the copyconstructor to make a copy for extended use.
|
||||
* You have to release the copy yourself later (delete ptr...)
|
||||
* @param p_SPITType a reference to a copy of the SPITType instance.<br>
|
||||
* The reference is deleted after this function call!!
|
||||
*/
|
||||
void MyApp::eventSPITTypeRemoteRemoved(const SPITType& p_SPITType) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventSPITTypeRemote Removed");
|
||||
printf(" ID: %s GroupName: %s Name: %s\n", p_SPITType.getID().data(), p_SPITType.getGroupName().data(), p_SPITType.getName().data());
|
||||
#endif
|
||||
|
||||
//This is a remote SPITType
|
||||
//If you have listet this prior you should remove it from the list
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------
|
||||
//--------- SPITObject events ----------
|
||||
// Every SPITObjects has one one SPITType assigned.
|
||||
// Whenever an action is to be triggered, play events are sent with the corresponding SPITObject.
|
||||
// All SPITObjects are listet in a static unordered_map in the SPITObject class.
|
||||
// All Remote SPITObjects are listet in a seperate unordered_map in the SPITObject class;
|
||||
// You can use the SPITObject::get... functions to deal with them.
|
||||
// The SPITObject class has a static recursive_mutex, you get a pointer of the mutex by: SPITObject::getMutex();
|
||||
// To be thread save you should cover your code with a lock sequence:
|
||||
/*
|
||||
{ //start of the lock sequence
|
||||
unique_lock<recursive_mutex> o_LockObject(*SPITObject::getMutex());
|
||||
//got the lock
|
||||
|
||||
//fetch SPITObjects and deal with, but don't waste time while you holding the lock
|
||||
//Excample
|
||||
SPITObject* ptrSPITObject;
|
||||
for (int i = 0; i < SPITObject::getSPITObjectCount(); i++) {
|
||||
ptrSPITObject = SPITObject::getSPITObject(i);
|
||||
if (ptrSPITObject == NULL) break;
|
||||
//Do something with ptrSPITObject
|
||||
//bew aware after you leave the lock sequence the ptrSPITObject is no longer save!!
|
||||
}
|
||||
} //end of the lock sequence
|
||||
|
||||
//For Remote Objects you can use the getSPITObjectRemote... functions
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Called when the server has created, loaded or changed a SPITObject.<br>
|
||||
* May also occur when the server confirms a SPITObject created by the client, what the client should never do!!.<br>
|
||||
* @param p_New true = server created a new SPITObject<br>
|
||||
* false = server changed a existing SPITObject<br>
|
||||
* @param p_SPITType a reference to a copy of the associated SPITType instance.<br>
|
||||
* The reference is deleted after this function call!!
|
||||
* @param p_SPITObject a reference to a copy of the SPITObject instance.<br>
|
||||
* The reference is deleted after this function call!!
|
||||
*/
|
||||
void MyApp::eventSPITObject(bool p_New, const SPITType& p_SPITType, const SPITObject& p_SPITObject) {
|
||||
if (p_New) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventSPITObject NEW");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventSPITObject CHANGED");
|
||||
#endif
|
||||
}
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf(" ID: %s Name: %s -> SPITType: %s\n", p_SPITObject.getID().data(), p_SPITObject.getName().data(), p_SPITType.getName().data());
|
||||
#endif
|
||||
|
||||
//check your actions
|
||||
//Whenever you provide an action for this SPITObject take this over in your code.
|
||||
//call m_SPIT_Client->setActionSPITObject(p_SPITObject.getID(), true);
|
||||
|
||||
//for our little excample as described in loadClientProject:
|
||||
//We have only actions for SPITTypes - means every SPITObject with the associated "Actionx"-SPITTypes will trigger the action when it is played
|
||||
//-> no need to do something here, because setActionSPITType has been set prior and the SPITObject will automatically inherits this
|
||||
//SPITObjects with other SPITTypes asscciated will trigger no actions
|
||||
|
||||
}
|
||||
/**
|
||||
* Called when the server has created or changed a Remote SPITObject.<br>
|
||||
* A Remote SPITObject is used to remote control the SPITServer.
|
||||
* @param p_New true = server created a new remote SPITObject<br>
|
||||
* false = server changed a existing remote SPITObject<br>
|
||||
* @param p_SPITType a reference to a copy of the associated SPITType instance.<br>
|
||||
* The reference is deleted after this function call!!
|
||||
* @param p_SPITObject a reference to a copy of the SPITObject instance.<br>
|
||||
* The reference is deleted after this function call!!
|
||||
*/
|
||||
void MyApp::eventSPITObjectRemote(bool p_New, const SPITType& p_SPITType, const SPITObject& p_SPITObject) {
|
||||
if (p_New) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventSPITObjectRemote NEW");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventSPITObjectRemote CHANGED");
|
||||
#endif
|
||||
}
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf(" ID: %s Name: %s -> SPITType: %s\n", p_SPITObject.getID().data(), p_SPITObject.getName().data(), p_SPITType.getName().data());
|
||||
#endif
|
||||
|
||||
//This is a remote SPITObject which can be used to remote control the server.
|
||||
//If you want you can list this for later use
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the server has removed a SPITObject.<br>
|
||||
* After this function has been exited the SPITObject is emeoved from the SPITObject-List and the pointer is deleted.<br>
|
||||
* So use the pointer immediately or use the copyconstructor to make a copy for extended use.
|
||||
* You have to release the copy yourself later (delete ptr...)
|
||||
* @param p_SPITType a reference to a copy of the associated SPITType instance.<br>
|
||||
* The reference is deleted after this function call!!
|
||||
* @param p_SPITObject a reference to a copy of the SPITObject instance.<br>
|
||||
* The reference is deleted after this function call!!
|
||||
*/
|
||||
void MyApp::eventSPITObjectRemoved(const SPITType& p_SPITType, const SPITObject& p_SPITObject) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventSPITObject Removed");
|
||||
printf(" ID: %s Name: %s\n", p_SPITObject.getID().data(), p_SPITObject.getName().data());
|
||||
#endif
|
||||
|
||||
//Check your actions
|
||||
//take the removal of the SPITObject over in your code
|
||||
|
||||
//CAUTION: Deleted SPITObjects can be added later again (perhaps per UNDO on the SPITServer)
|
||||
//-> don't remove your assigned action immediately - keep it to reassign it later
|
||||
}
|
||||
/**
|
||||
* Called when the server has removed a Remote SPITObject.<br>
|
||||
* A Remote SPITObject is used to remote control the SPITServer.
|
||||
* After this function has been exited the SPITObject is emeoved from the SPITObject-List and the pointer is deleted.<br>
|
||||
* So use the pointer immediately or use the copyconstructor to make a copy for extended use.
|
||||
* You have to release the copy yourself later (delete ptr...)
|
||||
* @param p_SPITType a reference to a copy of the associated SPITType instance.<br>
|
||||
* The reference is deleted after this function call!!
|
||||
* @param p_SPITObject a reference to a copy of the SPITObject instance.<br>
|
||||
* The reference is deleted after this function call!!
|
||||
*/
|
||||
void MyApp::eventSPITObjectRemoteRemoved(const SPITType& p_SPITType, const SPITObject& p_SPITObject) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventSPITObjectRemote Removed");
|
||||
printf(" ID: %s Name: %s\n", p_SPITObject.getID().data(), p_SPITObject.getName().data());
|
||||
#endif
|
||||
|
||||
//This is a remote SPITObject
|
||||
//If you have listet this prior you should remove it from the list
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------
|
||||
//---------------- Playing SPITObjects ----------------
|
||||
// Following is called when the SPITServer play SPITObjects.
|
||||
// For every step the server does following sequence occurs:
|
||||
// a) eventPlay
|
||||
// b) several eventPlayObject for each actual played SPITObjectin this step
|
||||
// NEXT STAP of the server
|
||||
// a) eventPlay
|
||||
// b) several eventPlayObject for each actual played SPITObject in this step
|
||||
// ...
|
||||
|
||||
// SPITServer may use several methods for playing SPITObjects.
|
||||
// e.g. liveSHOWsoftware has the timeline and jingles which plays objects, where the timeline the main player is.
|
||||
// SPIT distinguishes between the different players. All eventPlay... functions contain the information which player plays the SPIT object.
|
||||
|
||||
void MyApp::eventPlay(string p_PlayerID, string p_PlayerName, char p_PlayerType, bool p_PlayerIsRunning, long long p_TimeFrames) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventPlay Player: %s Runs: %d Time: %lld\n", p_PlayerName.data(), p_PlayerIsRunning, p_TimeFrames);
|
||||
#endif
|
||||
|
||||
switch(p_PlayerType) {
|
||||
case SPIT_Client::PLAYERTYPE_MAIN:
|
||||
//p_FrameTimes contains the position inside the server's project, we can use it like a timecode
|
||||
int intMilliseconds;
|
||||
intMilliseconds= (int)(((double)p_TimeFrames / (double)m_ServerFramesPerSecond) * 1000);
|
||||
break;
|
||||
case SPIT_Client::PLAYERTYPE_CONTINOUS:
|
||||
//The olayer is playing only single Object sequences sometime during the project
|
||||
break;
|
||||
case SPIT_Client::PLAYERTYPE_DISCRETE:
|
||||
//Only discrete values where submitted, e.g the fader position of remote faders.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the SPITServer plays a SPITObject. For every played SPITObject one eventPlayObject is called.<br>
|
||||
* You can decide here which action should be done or not.<br>
|
||||
*
|
||||
* @param p_Started true = The SPITObject is newly played (e.g. in liveSHOWsoftware the cursor enters the SPITObject)
|
||||
* @param p_Ended Das true = Playback of SPITObject finished (e.g. in liveSHOWsoftware the cursor has exited the SPIT object)
|
||||
* @param p_SPITType the associated SPITType of p_SPITObject
|
||||
* @param p_SPITObject the actual played or stopped SPITObject
|
||||
* @param p_PlayObject contains information about the play status:<br>
|
||||
* frame where the cursor is inside the SPITObject<br>
|
||||
* whether the player is running or not<br>
|
||||
* the actual value of the SPITObject (in liveSHOWsoftware objects ma faded in or out or the main value is decreased, ..<br>
|
||||
*/
|
||||
void MyApp::eventPlayObject(string p_PlayerID, bool p_Started, bool p_Ended, const SPITType& p_SPITType, const SPITObject& p_SPITObject, const SPITPlayer::PlayObject& p_PlayObject) {
|
||||
// p_PlayObject.getValue() contain the value in ppm (we can calculate value between 0.0 and 1.0)
|
||||
// p_SPITObject.getValueFactor() or redundand p_PlayObject.getValueFactor()
|
||||
// contains the factor the above value should be multiplicated to get the end value.
|
||||
double doubleValue = ((double)p_PlayObject.getValue()/1000000)*((double)p_PlayObject.getValueFactor()/1000000);
|
||||
|
||||
//Other factors besides value may be of interest
|
||||
//p_PlayObject.getFrameInside() contains the play position inside the SPITObject
|
||||
//p_SPITObject.getFrameLength() contains the length of the SPITObject
|
||||
//-> we can calculate the position 0.0 to 1.0 where the Object is played
|
||||
|
||||
//in liveSHOWsoftware the player may play two different position in the SPITObject to mix them down, e.g. a SceneBridge is played
|
||||
//We can get the second (pre played) position: p_PlayObject.getFrameInsidePrePosition();
|
||||
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventPlayObject Player: %s is running: %d Object Started: %d Stopped: %d\n", p_PlayObject.getPlayerName().data(), p_PlayObject.getPlayerIsRunning(), p_Started, p_Ended);
|
||||
printf(" SPITType: %s SPITObject: %s Position: %lld Value: %f\n", p_SPITType.getName().data(), p_SPITObject.getName().data(), p_PlayObject.getFrameInside(), doubleValue);
|
||||
#endif
|
||||
|
||||
//check for your actions to do
|
||||
|
||||
//In our little excample decribed in loadClientProject:
|
||||
//We want to react to SPIT types, no matter which SPIT object is currently being played.
|
||||
//-> check not the SPITObject itself but the associated SPITType
|
||||
bool boolPLayerIsRunning = p_PlayObject.getPlayerIsRunning();
|
||||
if (p_SPITType.getID() == "MySPITAPP_Action1ID") { //do Action 1
|
||||
//we can get some information about the play status
|
||||
if (p_Started == true) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MyApp AKTION 1 started Value: %f and running: %d\n", doubleValue, boolPLayerIsRunning);
|
||||
#endif
|
||||
}
|
||||
else if (p_Ended == true) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MyApp AKTION 1 ended\n"); //p_PlayObject.getFrameInside() is -1
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MyApp AKTION 1 is played Value: %f and running: %d\n", doubleValue, boolPLayerIsRunning);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (p_SPITType.getID() == "MySPITAPP_Action2ID") { //do Action 2
|
||||
if (p_Started == true) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MyApp AKTION 2 started Value: %f and running: %d\n", doubleValue, boolPLayerIsRunning);
|
||||
#endif
|
||||
}
|
||||
else if (p_Ended == true) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MyApp AKTION 2 ended\n"); //p_PlayObject.getFrameInside() is -1
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MyApp AKTION 2 is played Value: %f and running: %d\n", doubleValue, boolPLayerIsRunning);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------
|
||||
//---------------- Remote Control SPITServer ----------------
|
||||
// The SPITServer has sent all possibilities to control it remotely - remote SPITObjects - see eventSPITObjectRemote
|
||||
// Some of them may control functionality with values (fader psotions for loudness of sound, ...).
|
||||
// When the server changes one of these value objects, it sends an eventPlayRemoteObjectStatus.
|
||||
|
||||
/**
|
||||
* Called when a remote SpitObject which value function is changed by the server.<br>
|
||||
* This allows the Client to adjust its display for the remote command.<br>
|
||||
* @param p_SPITType the assigned remote SPITType of p_SPITObject
|
||||
* @param p_SPITObject the remote SPITObject which is changed
|
||||
* @param p_FrameInsideObject can be discarded
|
||||
* @param p_Value the new value
|
||||
*/
|
||||
void MyApp::eventPlayRemoteObjectStatus(const SPITType& p_SPITType, const SPITObject& p_SPITObject, long long p_FrameInsideObject, int p_Value) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("MySPITApp: eventPlayRemoteObjectStatus RemoteSPITType: %s RemoteSPITObject: %s Position: %lld Value: %d\n", p_SPITType.getName().data(), p_SPITObject.getName().data(), p_FrameInsideObject, p_Value);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a remote control command to the SPITServer.<br>
|
||||
* There may be different command types:
|
||||
* a) Some don't use value e.g. go to next scene, olay a jingle, ..
|
||||
* b) Some use values e.g. the main sound fader
|
||||
* @param p_SPITObjectID the id of the remote SPITObject (this represents the remote control command)
|
||||
* @param p_Valueppm the value in ppm <br>
|
||||
* in case a) the value is ignored<br>
|
||||
* in case b) the value is used
|
||||
* @param p_ValueFlag indicates how the server should use p_Valueppm:<br>
|
||||
* VALUEFLAG_DIRECT (0x00) The server will overwrite his existing value with p_Value<br>
|
||||
* VALUEFLAG_INCREASE (0x01) The server increases his existing value by p_Valueppm
|
||||
* VALUEFLAG_DECREASE (0x01) The server decreases his existing value by p_Valueppm
|
||||
*/
|
||||
void MyApp::sendRemoteObject(string p_SPITObjectID, int p_Valueppm, char p_ValueFlag) {
|
||||
if (m_SPIT_Client != NULL) {
|
||||
m_SPIT_Client->sendRemoteObject(p_SPITObjectID, p_Valueppm, p_ValueFlag);
|
||||
}
|
||||
}
|
||||
|
||||
//liveSHOWsoftware excample for sending remote control
|
||||
//the liveSHOW software has the remote control commands (SPITObjects) among other things:
|
||||
// + next secenebridge with id "nextSceneBridge"
|
||||
// + main mixer sound width id = "mainmixerSound_Volume00"
|
||||
//You can detect this in eventSPITObjectRemote(...)
|
||||
void MyApp::testLiveShowRemote() {
|
||||
//We jump to the next Scenebridge - no Value is needed
|
||||
m_SPIT_Client->sendRemoteObject("nextSceneBridge");
|
||||
//we set the main sound volume to 0.1, SPIT uses ppm -> 0.1 = 100000
|
||||
m_SPIT_Client->sendRemoteObject("mainmixerSound_Volume00", 100000, SPIT_Client::VALUEFLAG_DIRECT);
|
||||
//we increase the main sound volume by 0.1, SPIT uses ppm -> 0.1 = 100000
|
||||
m_SPIT_Client->sendRemoteObject("mainmixerSound_Volume00", 100000, SPIT_Client::VALUEFLAG_INCREASE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
//---------- Options for the client user ----------
|
||||
//Normally this should not be used, because because the server is master of things
|
||||
//In some situations, however, it may be helpful
|
||||
|
||||
/**
|
||||
* Removes the SPITType with id == p_SPITTypeID
|
||||
* @param p_SPITTypeID the id of the SPITType
|
||||
* @return
|
||||
*/
|
||||
int MyApp::removeSPITType(string p_SPITTypeID) {
|
||||
if (m_SPIT_Client == NULL) return -1;
|
||||
return m_SPIT_Client->removeSPITType(p_SPITTypeID);
|
||||
}
|
||||
/**
|
||||
* Removes the SPITObject with id == p_SPITObjectID
|
||||
* @param p_SPITObjectID the id of the SPITObject
|
||||
* @return
|
||||
*/
|
||||
int MyApp::removeSPITObject(string p_SPITObjectID) {
|
||||
if (m_SPIT_Client == NULL) return -1;
|
||||
return m_SPIT_Client->removeSPITObject(p_SPITObjectID);
|
||||
}
|
||||
/**
|
||||
* Changes the SPITType
|
||||
* @param p_SPITType a pointer to a SPITType instance whith changed members
|
||||
* @return
|
||||
*/
|
||||
int MyApp::changeSPITType(SPITType* p_SPITType) {
|
||||
return m_SPIT_Client->changeSPITType(p_SPITType);
|
||||
}
|
||||
/**
|
||||
* Changes the SPITObject
|
||||
* @param p_SPITObject a pointer to a SPITObject with changed members
|
||||
* @return
|
||||
*/
|
||||
int MyApp::changeSPITObject(SPITObject* p_SPITObject) {
|
||||
return m_SPIT_Client->changeSPITObject(p_SPITObject);
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SAD_Client is used for ServerAutoDetection (SAD).
|
||||
*
|
||||
* File: ServerAutoDetetc_Client.cpp
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 16. April 2019, 08:57
|
||||
*/
|
||||
|
||||
#include "SAD_Client.h"
|
||||
|
||||
//----- initialze static members -----
|
||||
bool SAD_Client::s_StopSAD = true;
|
||||
mutex SAD_Client::s_MutexSAD;
|
||||
condition_variable SAD_Client::s_ConditionStopSAD;
|
||||
thread* SAD_Client::s_ThreadSend = NULL;
|
||||
thread* SAD_Client::s_ThreadReceiveIP4 = NULL;
|
||||
thread* SAD_Client::s_ThreadReceiveIP6 = NULL;
|
||||
|
||||
recursive_mutex SAD_Client::s_MutexClientInterface;
|
||||
SAD_ClientInterface* SAD_Client::s_SADClientInterface = NULL;
|
||||
|
||||
recursive_mutex SAD_Client::s_MutexSocket;
|
||||
SPITSocket* SAD_Client::s_SPITSocket = NULL;
|
||||
|
||||
|
||||
|
||||
void SAD_Client::startAutoDetectServer(SAD_ClientInterface* p_SADClientInterface, SPITSocket* p_SpitSocket) {
|
||||
if (p_SADClientInterface == NULL) return;
|
||||
if (p_SpitSocket == NULL) return;
|
||||
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockClient(s_MutexClientInterface);
|
||||
s_SADClientInterface = p_SADClientInterface;
|
||||
}
|
||||
{
|
||||
unique_lock<mutex> o_UniqueLock(s_MutexSAD);
|
||||
if (s_StopSAD == false) return;
|
||||
s_StopSAD = false;
|
||||
SAD_DetectedServer::clearDetectedServers();
|
||||
}
|
||||
|
||||
s_SPITSocket = p_SpitSocket;
|
||||
|
||||
s_ThreadSend = new thread(&SAD_Client::sendAutoDetectServer);
|
||||
s_ThreadReceiveIP4 = new thread(&SAD_Client::receiveAutoDetectServer_IP4);
|
||||
s_ThreadReceiveIP6 = new thread(&SAD_Client::receiveAutoDetectServer_IP6);
|
||||
}
|
||||
void SAD_Client::stopAutoDetectServer(SAD_ClientInterface* p_SADClientInterface) {
|
||||
bool boolStopDetection = false;
|
||||
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockClient(s_MutexClientInterface);
|
||||
if (s_SADClientInterface != p_SADClientInterface) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
unique_lock<mutex> o_UniqueLock(s_MutexSAD);
|
||||
if (s_StopSAD == true) return;
|
||||
s_StopSAD = true;
|
||||
}
|
||||
s_ConditionStopSAD.notify_one();
|
||||
if (s_ThreadSend != NULL) {
|
||||
if (this_thread::get_id() != s_ThreadSend->get_id()) {
|
||||
if (s_ThreadSend->joinable()) {
|
||||
s_ThreadSend->join();
|
||||
}
|
||||
}
|
||||
s_ThreadSend = NULL;
|
||||
}
|
||||
|
||||
//wait for receiving threads
|
||||
if (s_ThreadReceiveIP4 != NULL) {
|
||||
if (this_thread::get_id() != s_ThreadReceiveIP4->get_id()) {
|
||||
if (s_ThreadReceiveIP4->joinable()) {
|
||||
s_ThreadReceiveIP4->join();
|
||||
}
|
||||
}
|
||||
s_ThreadReceiveIP4 = NULL;
|
||||
}
|
||||
if (s_ThreadReceiveIP6 != NULL) {
|
||||
if (this_thread::get_id() != s_ThreadReceiveIP6->get_id()) {
|
||||
if (s_ThreadReceiveIP6->joinable()) {
|
||||
s_ThreadReceiveIP6->join();
|
||||
}
|
||||
}
|
||||
s_ThreadReceiveIP6 = NULL;
|
||||
}
|
||||
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockSocket(s_MutexSocket);
|
||||
if (s_SPITSocket != NULL) {
|
||||
delete s_SPITSocket;
|
||||
s_SPITSocket = NULL;
|
||||
}
|
||||
}
|
||||
{
|
||||
unique_lock<mutex> o_UniqueLock(s_MutexSAD);
|
||||
SAD_DetectedServer::clearDetectedServers();
|
||||
}
|
||||
}
|
||||
|
||||
void SAD_Client::sendAutoDetectServer() {
|
||||
SPITSocket::IPAddress* o_IPAddress;
|
||||
string stringBroadcastIP4;
|
||||
string stringBroadcastIP6;
|
||||
string stringBroadcastIP6_loopback;
|
||||
string stringDatagram;
|
||||
int intDatagramLength;
|
||||
bool boolDone;
|
||||
|
||||
stringDatagram = SERVERAUTODETECT_PRECODE;
|
||||
stringDatagram.append(SERVERAUTODETECT_SEPERATOR);
|
||||
stringDatagram.append(SERVERAUTODETECT_TASKID);
|
||||
intDatagramLength = stringDatagram.length();
|
||||
|
||||
stringBroadcastIP6 = "ff02::1";
|
||||
stringBroadcastIP6_loopback = "::1";
|
||||
|
||||
while(s_StopSAD == false) {
|
||||
|
||||
//---- IP4 ---
|
||||
cycleStart();
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockSocket(s_MutexSocket);
|
||||
|
||||
if (s_SPITSocket == NULL) {
|
||||
return;
|
||||
}
|
||||
s_SPITSocket->getAdaptersInfo();
|
||||
|
||||
for (int i = 0; i < SPITSocket::getIPAddressCount(); i++) {
|
||||
o_IPAddress = SPITSocket::getIPAddress(i);
|
||||
if (o_IPAddress == NULL) break;
|
||||
stringBroadcastIP4 = s_SPITSocket->getBroadcastIP4(o_IPAddress);
|
||||
if (s_SPITSocket->sendMessageTo(SPITSocket::FAMILY_IP4, stringBroadcastIP4, SERVERAUTODETECT_PORT, stringDatagram.data(), intDatagramLength) < 0) {
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
//---- IP6 --- send to "ff02::1" and to the loopback address "::1" because MAC OSX seems to to need the loopback over IP6
|
||||
//"ff02::1"
|
||||
if (s_SPITSocket->sendMessageTo(SPITSocket::FAMILY_IP6, stringBroadcastIP6, SERVERAUTODETECT_PORT, stringDatagram.data(), stringDatagram.length()) < 0) {
|
||||
}
|
||||
else {
|
||||
}
|
||||
//"::1" loopback
|
||||
if (s_SPITSocket->sendMessageTo(SPITSocket::FAMILY_IP6, stringBroadcastIP6_loopback, SERVERAUTODETECT_PORT, stringDatagram.data(), stringDatagram.length()) < 0) {
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (s_StopSAD == true) {
|
||||
return;
|
||||
}
|
||||
//wait for 3000 milliseconds or
|
||||
//s_StopAutoDetectServer == true see stopAutoDetectServer
|
||||
unique_lock<mutex> o_LockWait(s_MutexSAD);
|
||||
boolDone = s_ConditionStopSAD.wait_for(o_LockWait, chrono::milliseconds(3000),[]{return s_StopSAD;});
|
||||
if (s_StopSAD == true) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
cycleEnd();
|
||||
}
|
||||
int intTest = 0;
|
||||
}
|
||||
|
||||
void SAD_Client::receiveAutoDetectServer_IP4() {
|
||||
char buffer[512+1];
|
||||
int intReceivedByteCount;
|
||||
string stringMessage;
|
||||
string stringServerIP;
|
||||
|
||||
int intIndex = 0;
|
||||
int intPos = 0;
|
||||
int intOldPos = 0;
|
||||
string stringPart;
|
||||
string stringParts[9];
|
||||
|
||||
//sendAutoDetectServer will bind the socket to a port
|
||||
//wait a while to be sendAutoDetectServer first
|
||||
this_thread::sleep_for(chrono::milliseconds(500));
|
||||
|
||||
while (s_StopSAD == false) {
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockIP4(s_MutexSocket);
|
||||
if (s_SPITSocket == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
intReceivedByteCount = s_SPITSocket->receiveMessage(SPITSocket::FAMILY_IP4, buffer, 512, &stringServerIP);
|
||||
if (intReceivedByteCount <= 0) {
|
||||
if (s_StopSAD == false) {
|
||||
//To reduce the processor load if a socket error occurs, we let the thread sleep a bit.
|
||||
this_thread::sleep_for(chrono::milliseconds(100));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (s_StopSAD == true) {
|
||||
return;
|
||||
}
|
||||
//add null chararcter
|
||||
if (intReceivedByteCount < 512) {
|
||||
buffer[intReceivedByteCount] = '\0';
|
||||
}
|
||||
else {
|
||||
buffer[512] = '\0';
|
||||
}
|
||||
stringMessage = buffer;
|
||||
//Check if precode is ok
|
||||
if (stringMessage.find(SERVERAUTODETECT_PRECODE.data(),0) != 0) {
|
||||
return;
|
||||
}
|
||||
intIndex = 0;
|
||||
intPos = 0;
|
||||
intOldPos = 0;
|
||||
while(intIndex < 8) {
|
||||
intPos = stringMessage.find(SERVERAUTODETECT_SEPERATOR.data(),intOldPos);
|
||||
if (intPos == string::npos) {
|
||||
stringPart = "";
|
||||
}
|
||||
else {
|
||||
stringPart = stringMessage.substr(intOldPos, intPos-intOldPos);
|
||||
intOldPos = intPos + SERVERAUTODETECT_SEPERATOR.length();
|
||||
}
|
||||
stringParts[intIndex] = stringPart;
|
||||
intIndex++;
|
||||
}
|
||||
stringParts[8] = stringServerIP;
|
||||
SAD_DetectedServer::addDetectedServer(true, stringParts[SAD_DetectedServer::PARAMINDEX_ID], stringParts);
|
||||
}
|
||||
int inTest = 0;
|
||||
}
|
||||
void SAD_Client::receiveAutoDetectServer_IP6() {
|
||||
char buffer[512+1];
|
||||
int intReceivedByteCount;
|
||||
string stringMessage;
|
||||
string stringServerIP;
|
||||
|
||||
int intIndex = 0;
|
||||
int intPos = 0;
|
||||
int intOldPos = 0;
|
||||
string stringPart;
|
||||
string stringParts[9];
|
||||
|
||||
//sendto will bind the socket to a port
|
||||
//wait a while to be sendto first
|
||||
this_thread::sleep_for(chrono::milliseconds(500));
|
||||
|
||||
while (s_StopSAD == false) {
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockIP6(s_MutexSocket);
|
||||
if (s_SPITSocket == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
intReceivedByteCount = s_SPITSocket->receiveMessage(SPITSocket::FAMILY_IP6, buffer, 512, &stringServerIP);
|
||||
if (intReceivedByteCount <= 0) {
|
||||
if (s_StopSAD == false) {
|
||||
//To reduce the processor load if a socket error occurs, we let the thread sleep a bit.
|
||||
this_thread::sleep_for(chrono::milliseconds(100));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (s_StopSAD == true) {
|
||||
return;
|
||||
}
|
||||
//add null chararcter
|
||||
if (intReceivedByteCount < 512) {
|
||||
buffer[intReceivedByteCount] = '\0';
|
||||
}
|
||||
else {
|
||||
buffer[512] = '\0';
|
||||
}
|
||||
stringMessage = buffer;
|
||||
//Check if precode is ok
|
||||
if (stringMessage.find(SERVERAUTODETECT_PRECODE.data(),0) != 0) {
|
||||
return;
|
||||
}
|
||||
intIndex = 0;
|
||||
intPos = 0;
|
||||
intOldPos = 0;
|
||||
while(intIndex < 8) {
|
||||
intPos = stringMessage.find(SERVERAUTODETECT_SEPERATOR.data(),intOldPos);
|
||||
if (intPos == string::npos) {
|
||||
stringPart = "";
|
||||
}
|
||||
else {
|
||||
stringPart = stringMessage.substr(intOldPos, intPos-intOldPos);
|
||||
intOldPos = intPos + SERVERAUTODETECT_SEPERATOR.length();
|
||||
}
|
||||
stringParts[intIndex] = stringPart;
|
||||
intIndex++;
|
||||
}
|
||||
stringParts[8] = stringServerIP;
|
||||
SAD_DetectedServer::addDetectedServer(false, stringParts[SAD_DetectedServer::PARAMINDEX_ID], stringParts);
|
||||
}
|
||||
int inTest = 0;
|
||||
}
|
||||
|
||||
void SAD_Client::cycleStart() {
|
||||
{
|
||||
unique_lock<mutex> o_UniqueLock(s_MutexSAD);
|
||||
if (s_StopSAD == true) return;
|
||||
}
|
||||
// printf("SAD CYCLE START\n");
|
||||
SAD_DetectedServer::cycleStart();
|
||||
}
|
||||
void SAD_Client::cycleEnd() {
|
||||
{
|
||||
unique_lock<mutex> o_UniqueLock(s_MutexSAD);
|
||||
if (s_StopSAD == true) return;
|
||||
}
|
||||
SAD_DetectedServer::cycleEnd(s_SADClientInterface);
|
||||
// printf("SAD CYCLE END\n");
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SAD_DetectedServer holds information about SPIT Server detected by ServerAutoDetection (SAD).
|
||||
* File: SAD_DetectedServer.cpp
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 4. Mai 2019, 13:51
|
||||
*/
|
||||
|
||||
#include "SAD_DetectedServer.h"
|
||||
|
||||
recursive_mutex SAD_DetectedServer::s_MutexDetectedServer;
|
||||
unordered_map<string, SAD_DetectedServer*> SAD_DetectedServer::s_DetectedServers;
|
||||
|
||||
SAD_DetectedServer::~SAD_DetectedServer() {
|
||||
}
|
||||
//----- Detected Server -----
|
||||
SAD_DetectedServer::SAD_DetectedServer() {
|
||||
m_ID = "";
|
||||
m_Name = "";
|
||||
m_ComputerName = "";
|
||||
m_ClientIP = "";
|
||||
m_Port = "";
|
||||
m_Additions = "";
|
||||
m_IPIsLoopback = false;
|
||||
m_IPIsIP4 = false;
|
||||
m_IPIsIP6 = false;
|
||||
}
|
||||
|
||||
void SAD_DetectedServer::setID(string p_ID) {
|
||||
m_ID = p_ID;
|
||||
}
|
||||
void SAD_DetectedServer::setName(string p_Name) {
|
||||
m_Name = p_Name;
|
||||
}
|
||||
void SAD_DetectedServer::setComputerName(string p_ComputerName) {
|
||||
m_ComputerName = p_ComputerName;
|
||||
}
|
||||
void SAD_DetectedServer::setIP(string p_IP) {
|
||||
m_IP = p_IP;
|
||||
}
|
||||
void SAD_DetectedServer::setClientIP(string p_IP) {
|
||||
m_ClientIP = p_IP;
|
||||
}
|
||||
void SAD_DetectedServer::setPort(string p_Port) {
|
||||
m_Port = p_Port;
|
||||
}
|
||||
void SAD_DetectedServer::setAdditions(string p_Additions) {
|
||||
m_Additions = p_Additions;
|
||||
}
|
||||
|
||||
void SAD_DetectedServer::cycleStart() {
|
||||
{
|
||||
unique_lock<recursive_mutex>o_lock(s_MutexDetectedServer);
|
||||
for (auto i = s_DetectedServers.begin(); i != s_DetectedServers.end(); i++) {
|
||||
i->second->startCycleSAD();
|
||||
}
|
||||
}
|
||||
}
|
||||
void SAD_DetectedServer::cycleEnd(SAD_ClientInterface* p_SADClientInterface) {
|
||||
list<SAD_DetectedServer*> o_LostServers;
|
||||
list<SAD_DetectedServer*> o_NewServers;
|
||||
SAD_DetectedServer* ptrDetectedServer;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_lock(s_MutexDetectedServer);
|
||||
for (auto i = s_DetectedServers.begin(); i != s_DetectedServers.end(); i++) {
|
||||
ptrDetectedServer = i->second;
|
||||
if (ptrDetectedServer->getFoundAgain() == false) {
|
||||
o_LostServers.push_back(ptrDetectedServer);
|
||||
ptrDetectedServer->endCycleSAD();
|
||||
}
|
||||
else if (ptrDetectedServer->getNew()) {
|
||||
o_NewServers.push_back(ptrDetectedServer);
|
||||
ptrDetectedServer->setNew(false);
|
||||
ptrDetectedServer->endCycleSAD();
|
||||
}
|
||||
else if (ptrDetectedServer->getChanged()) {
|
||||
// p_SADClientInterface->
|
||||
ptrDetectedServer->endCycleSAD();
|
||||
}
|
||||
else {
|
||||
ptrDetectedServer->endCycleSAD();
|
||||
}
|
||||
}
|
||||
}
|
||||
//Notify client interface about lost servers
|
||||
for (auto i = o_LostServers.begin(); i != o_LostServers.end(); i++) {
|
||||
ptrDetectedServer = *i;
|
||||
if (p_SADClientInterface != NULL) {
|
||||
p_SADClientInterface->eventServerLost(ptrDetectedServer->getID(), ptrDetectedServer->getName(),
|
||||
ptrDetectedServer->getComputerName(), ptrDetectedServer->getIP(), ptrDetectedServer->getPort(), ptrDetectedServer->getAdditions(),
|
||||
ptrDetectedServer->getClientIP(),
|
||||
ptrDetectedServer->getIpIsLoopback(), ptrDetectedServer->getIpIsIP4(), ptrDetectedServer->getIpIsIP6());
|
||||
}
|
||||
}
|
||||
//Remove lost servers
|
||||
for (auto i = o_LostServers.begin(); i != o_LostServers.end(); i++) {
|
||||
ptrDetectedServer = *i;
|
||||
removeDetectedServer(ptrDetectedServer);
|
||||
}
|
||||
o_LostServers.clear();
|
||||
|
||||
for (auto i = o_NewServers.begin(); i != o_NewServers.end(); i++) {
|
||||
ptrDetectedServer = *i;
|
||||
if (p_SADClientInterface != NULL) {
|
||||
p_SADClientInterface->eventServerDetected(ptrDetectedServer->getID(), ptrDetectedServer->getName(),
|
||||
ptrDetectedServer->getComputerName(), ptrDetectedServer->getIP(), ptrDetectedServer->getPort(), ptrDetectedServer->getAdditions(),
|
||||
ptrDetectedServer->getClientIP(),
|
||||
ptrDetectedServer->getIpIsLoopback(), ptrDetectedServer->getIpIsIP4(), ptrDetectedServer->getIpIsIP6());
|
||||
}
|
||||
}
|
||||
o_NewServers.clear();
|
||||
|
||||
}
|
||||
/**
|
||||
* Used by SAD_Client to add a found SPITServer - don't use this manually
|
||||
* @param p_IsIP4 true = the server is reached via a IP4 address<br>false = the server is reahed via a IP6 address
|
||||
* @param p_ServerID the id of the server, every instance of a SPITServer has an own id
|
||||
* @param p_ServerParams the server's parameter
|
||||
*/
|
||||
void SAD_DetectedServer::addDetectedServer(bool p_IsIP4, string p_ServerID, string p_ServerParams[]) {
|
||||
SAD_DetectedServer* ptrDetectedServer;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_Lock(s_MutexDetectedServer);
|
||||
auto i = s_DetectedServers.find(p_ServerID);
|
||||
if (i != s_DetectedServers.end()) {
|
||||
ptrDetectedServer = i->second;
|
||||
}
|
||||
else {
|
||||
ptrDetectedServer = new SAD_DetectedServer();
|
||||
ptrDetectedServer->setID(p_ServerParams[PARAMINDEX_ID]);
|
||||
ptrDetectedServer->setNew(true);
|
||||
}
|
||||
ptrDetectedServer->setFoundAgain();
|
||||
|
||||
if (p_ServerParams[PARAMINDEX_IP].find("127.") == 0 ||
|
||||
p_ServerParams[PARAMINDEX_IP].find("0:") == 0 ||
|
||||
p_ServerParams[PARAMINDEX_IP].find("0000:") == 0||
|
||||
p_ServerParams[PARAMINDEX_IP].find(":") == 0) {
|
||||
//first prefer the loopback ip
|
||||
ptrDetectedServer->setIP(p_ServerParams[PARAMINDEX_IP]);
|
||||
ptrDetectedServer->setIPIsLoopback(true);
|
||||
ptrDetectedServer->setClientIP(p_ServerParams[PARAMINDEX_CLIENTIP]);
|
||||
}
|
||||
else if (ptrDetectedServer->getIpIsLoopback() == false) {
|
||||
//second prefer IP4
|
||||
if (p_IsIP4 == true) {
|
||||
ptrDetectedServer->setIP(p_ServerParams[PARAMINDEX_IP]);
|
||||
ptrDetectedServer->setIPIsIP4(true);
|
||||
ptrDetectedServer->setClientIP(p_ServerParams[PARAMINDEX_CLIENTIP]);
|
||||
}
|
||||
else if (ptrDetectedServer->getIpIsIP4() == false){
|
||||
ptrDetectedServer->setIP(p_ServerParams[PARAMINDEX_IP]);
|
||||
ptrDetectedServer->setIPIsIP6(true);
|
||||
ptrDetectedServer->setClientIP(p_ServerParams[PARAMINDEX_CLIENTIP]);
|
||||
}
|
||||
}
|
||||
ptrDetectedServer->setName(p_ServerParams[PARAMINDEX_NAME]);
|
||||
ptrDetectedServer->setComputerName(p_ServerParams[PARAMINDEX_COMPUTERNAME]);
|
||||
ptrDetectedServer->setPort(p_ServerParams[PARAMINDEX_PORT]);
|
||||
ptrDetectedServer->setAdditions(p_ServerParams[PARAMINDEX_ADDITIONS]);
|
||||
|
||||
s_DetectedServers[ptrDetectedServer->getID()] = ptrDetectedServer;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Used by SAD_Client to remove a SPITServer - don't use this manually
|
||||
* @param p_DetectedServer
|
||||
*/
|
||||
void SAD_DetectedServer::removeDetectedServer(SAD_DetectedServer* p_DetectedServer) {
|
||||
SAD_DetectedServer* o_DetectedServer;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_Lock(s_MutexDetectedServer);
|
||||
auto i = s_DetectedServers.find(p_DetectedServer->getID());
|
||||
if (i != s_DetectedServers.end()) {
|
||||
o_DetectedServer = i->second;
|
||||
i = s_DetectedServers.erase(i);
|
||||
delete o_DetectedServer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by SAD_Client to clear all found SPITServers - don't use this manually
|
||||
*/
|
||||
void SAD_DetectedServer::clearDetectedServers() {
|
||||
SAD_DetectedServer* ptrDetectedServer;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_Lock(s_MutexDetectedServer);
|
||||
for (auto i = s_DetectedServers.begin(); i != s_DetectedServers.end(); i++) {
|
||||
ptrDetectedServer = i->second;
|
||||
i = s_DetectedServers.erase(i);
|
||||
delete ptrDetectedServer;
|
||||
if (i == s_DetectedServers.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,463 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPITObject describes a SPIT Object
|
||||
* File: SPITObject.cpp
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 9. April 2019, 12:11
|
||||
*/
|
||||
|
||||
#include "SPITObject.h"
|
||||
#include "_SPITMACROS.h"
|
||||
|
||||
unordered_map<string, SPITObject*> SPITObject::s_SPITObjects;
|
||||
unordered_map<string, SPITObject*> SPITObject::s_SPITObjectsRemote;
|
||||
recursive_mutex SPITObject::s_MutexSPITObject;
|
||||
|
||||
SPITObject* SPITObject::getSPITObject(string p_ID) {
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
auto i = s_SPITObjects.find(p_ID);
|
||||
if (i == s_SPITObjects.end()) {
|
||||
return NULL;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the reference of the SPITObject with ID == p_ID.<br>
|
||||
* Throws an exception if no SPITObject is not found.<br>
|
||||
* @param p_ID the ID
|
||||
* @return reference of the SPITType with ID == p_ID
|
||||
*/
|
||||
const SPITObject& SPITObject::getSPITObjectRef(string p_ID) {
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
auto i = s_SPITObjects.find(p_ID);
|
||||
if (i == s_SPITObjects.end()) {
|
||||
throw "SPITObject no SPITObject with given id";
|
||||
}
|
||||
return *(i->second);
|
||||
}
|
||||
}
|
||||
|
||||
SPITObject* SPITObject::getSPITObjectRemote(string p_ID) {
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
auto i = s_SPITObjectsRemote.find(p_ID);
|
||||
if (i == s_SPITObjectsRemote.end()) {
|
||||
return NULL;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the reference of the remote SPITObject with ID == p_ID.<br>
|
||||
* Throws an exception if no SPITObject is not found.<br>
|
||||
* @param p_ID the ID
|
||||
* @return reference of the SPITType with ID == p_ID
|
||||
*/
|
||||
const SPITObject& SPITObject::getSPITObjectRemoteRef(string p_ID) {
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
auto i = s_SPITObjectsRemote.find(p_ID);
|
||||
if (i == s_SPITObjectsRemote.end()) {
|
||||
throw "Remote SPITObject no SPITObject with given id";
|
||||
}
|
||||
return *(i->second);
|
||||
}
|
||||
}
|
||||
|
||||
bool SPITObject::addSPITObject(SPITObject* p_ptrSPITObject) {
|
||||
if (p_ptrSPITObject == NULL) return false;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
s_SPITObjects[p_ptrSPITObject->getID()] = p_ptrSPITObject;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bool SPITObject::addSPITObjectRemote(SPITObject* p_ptrSPITObject) {
|
||||
if (p_ptrSPITObject == NULL) return false;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
s_SPITObjectsRemote[p_ptrSPITObject->getID()] = p_ptrSPITObject;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bool SPITObject::removeSPITObject(SPITObject* p_ptrSPITObject) {
|
||||
if (p_ptrSPITObject == NULL) return false;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
auto i = s_SPITObjects.find(p_ptrSPITObject->getID());
|
||||
if (i == s_SPITObjects.end()) {
|
||||
return false;
|
||||
}
|
||||
i = s_SPITObjects.erase(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bool SPITObject::removeSPITObjectRemote(SPITObject* p_ptrSPITObject) {
|
||||
if (p_ptrSPITObject == NULL) return false;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
auto i = s_SPITObjectsRemote.find(p_ptrSPITObject->getID());
|
||||
if (i == s_SPITObjectsRemote.end()) {
|
||||
return false;
|
||||
}
|
||||
i = s_SPITObjectsRemote.erase(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int SPITObject::getSPITObjectCount() {
|
||||
return s_SPITObjects.size();
|
||||
}
|
||||
int SPITObject::getSPITObjectRemoteCount() {
|
||||
return s_SPITObjectsRemote.size();
|
||||
}
|
||||
SPITObject* SPITObject::getSPITObject(int p_Index) {
|
||||
SPITObject* ptrSPITObject = NULL;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
if (p_Index >= 0 && p_Index < s_SPITObjects.size()) {
|
||||
unordered_map<string, SPITObject*>::iterator i = next(s_SPITObjects.begin(), p_Index);
|
||||
ptrSPITObject = i->second;
|
||||
return ptrSPITObject;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns a reference to the SPITObject at position p_Index.<br>
|
||||
* Throws an exception if p_Index is out of range.<br>
|
||||
* @param p_Index position
|
||||
* @return the reference of the SPITObject at position.
|
||||
*/
|
||||
const SPITObject& SPITObject::getSPITObjectRef(int p_Index) {
|
||||
SPITObject* ptrSPITObject = NULL;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
if (p_Index >= 0 && p_Index < s_SPITObjects.size()) {
|
||||
unordered_map<string, SPITObject*>::iterator i = next(s_SPITObjects.begin(), p_Index);
|
||||
ptrSPITObject = i->second;
|
||||
return *ptrSPITObject;
|
||||
}
|
||||
else {
|
||||
throw "SPITObject index out of range";
|
||||
}
|
||||
}
|
||||
}
|
||||
SPITObject* SPITObject::getSPITObjectRemote(int p_Index) {
|
||||
SPITObject* ptrSPITObject = NULL;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
if (p_Index >= 0 && p_Index < s_SPITObjectsRemote.size()) {
|
||||
unordered_map<string, SPITObject*>::iterator i = next(s_SPITObjectsRemote.begin(), p_Index);
|
||||
ptrSPITObject = i->second;
|
||||
return ptrSPITObject;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns a reference to the remote SPITObject at position p_Index.<br>
|
||||
* Throws an exception if p_Index is out of range.<br>
|
||||
* @param p_Index position
|
||||
* @return the reference of the SPITObject at position.
|
||||
*/
|
||||
const SPITObject& SPITObject::getSPITObjectRemoteRef(int p_Index) {
|
||||
SPITObject* ptrSPITObject = NULL;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
if (p_Index >= 0 && p_Index < s_SPITObjectsRemote.size()) {
|
||||
unordered_map<string, SPITObject*>::iterator i = next(s_SPITObjectsRemote.begin(), p_Index);
|
||||
ptrSPITObject = i->second;
|
||||
return *ptrSPITObject;
|
||||
}
|
||||
else {
|
||||
throw "Remote SPITObject index out of range";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SPITObject::clearSPITObjects() {
|
||||
SPITObject* ptrSPITObject;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
for (auto i = s_SPITObjects.begin(); i != s_SPITObjects.end(); i++) {
|
||||
ptrSPITObject = i->second;
|
||||
i = s_SPITObjects.erase(i);
|
||||
delete ptrSPITObject;
|
||||
if (i == s_SPITObjects.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void SPITObject::clearSPITObjectsRemote() {
|
||||
SPITObject* ptrSPITObject;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
for (auto i = s_SPITObjectsRemote.begin(); i != s_SPITObjectsRemote.end(); i++) {
|
||||
ptrSPITObject = i->second;
|
||||
i = s_SPITObjectsRemote.erase(i);
|
||||
delete ptrSPITObject;
|
||||
if (i == s_SPITObjectsRemote.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* sets confirmed = false for all SPITObjects.<br>
|
||||
* This should be called when the client has loaded a project.<br>
|
||||
*/
|
||||
void SPITObject::setConfirmedFalse() {
|
||||
SPITObject* ptrSPITObject;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockObject(s_MutexSPITObject);
|
||||
for (auto i = s_SPITObjects.begin(); i != s_SPITObjects.end(); i++) {
|
||||
ptrSPITObject = i->second;
|
||||
ptrSPITObject->setConfirmed(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
SPITObject::SPITObject() {
|
||||
initMembers();
|
||||
}
|
||||
void SPITObject::initMembers() {
|
||||
m_ActionAssigned = false;
|
||||
m_ActionAssignedType = false;
|
||||
m_Confirmed = false;
|
||||
m_Delay = 0;
|
||||
m_Duration = 0;
|
||||
m_Fixed = false;
|
||||
m_FrameFadeInLength = 0;
|
||||
m_FrameFadeOutLength = 0;
|
||||
m_FrameLength = 0;
|
||||
m_FrameStart = 0;
|
||||
m_Remark = "";
|
||||
m_ID = createGUID();
|
||||
m_Name = "";
|
||||
m_SPITTypeID = "";
|
||||
m_ServerParams = "";
|
||||
m_ServerRemote = false;
|
||||
m_Track = 0;
|
||||
m_ValueFactor = 1000000; //Values are given in ppm -> 1000000 = 1/1;
|
||||
m_ValueUse = 0x01;
|
||||
}
|
||||
/*
|
||||
SPITObject::SPITObject(const SPITObject& orig) {
|
||||
m_ActionAssigned = orig.getActionAssigned();
|
||||
m_Confirmed = orig.getConfirmed();
|
||||
m_Delay = orig.getDelay();
|
||||
m_Duration = orig.getDuration();
|
||||
m_Fixed = orig.getFixed();
|
||||
m_FrameFadeInLength = orig.getFrameFadeInLength();
|
||||
m_FrameFadeOutLength = orig.getFrameFadeOutLength();
|
||||
m_FrameLength = orig.getFrameLength();
|
||||
m_FrameStart = orig.getFrameStart();
|
||||
m_Remark = orig.getRemark();
|
||||
m_ID = orig.getID();
|
||||
m_Name = orig.getName();
|
||||
m_SPITTypeID = orig.getSPITTypeID();
|
||||
m_ServerParams = orig.getServerParams();
|
||||
m_ServerRemote = orig.getServerRemote();
|
||||
m_Track = orig.getTrack();
|
||||
m_ValueFactor = orig.getValueFactor();
|
||||
m_ValueUse = orig.getValueUse();
|
||||
}
|
||||
*/
|
||||
SPITObject::~SPITObject() {
|
||||
}
|
||||
|
||||
|
||||
void SPITObject::setMessageOP(SPIT_Message::ReportSPITObject* p_ReportSPITObject) {
|
||||
//m_ActionAssigned = p_ReportSPITObject->getActionAssigned(); //Should only be set by the client
|
||||
m_Confirmed = p_ReportSPITObject->getConfirmed();
|
||||
m_Delay = p_ReportSPITObject->getDelay();
|
||||
m_Duration = p_ReportSPITObject->getDuration();
|
||||
m_Fixed = p_ReportSPITObject->getFixed();
|
||||
m_FrameFadeInLength = p_ReportSPITObject->getFrameFadeInLength();
|
||||
m_FrameFadeOutLength = p_ReportSPITObject->getFrameFadeOutLength();
|
||||
m_FrameLength = p_ReportSPITObject->getFrameLength();
|
||||
m_FrameStart = p_ReportSPITObject->getFrameStart();
|
||||
m_Remark = p_ReportSPITObject->getRemark();
|
||||
m_ID = p_ReportSPITObject->getID();
|
||||
m_Name = p_ReportSPITObject->getName();
|
||||
m_SPITTypeID = p_ReportSPITObject->getSPITTypeID();
|
||||
m_ServerParams = p_ReportSPITObject->getServerParams();
|
||||
m_ServerRemote = p_ReportSPITObject->getServerRemote();
|
||||
m_Track = p_ReportSPITObject->getTrack();
|
||||
m_ValueFactor = p_ReportSPITObject->getValueFactor();
|
||||
m_ValueUse = p_ReportSPITObject->getValueUse();
|
||||
}
|
||||
|
||||
void SPITObject::fillMessageOP(SPIT_Message::ReportSPITObject* p_ReportSPITObject) {
|
||||
p_ReportSPITObject->setActionAssigned(getActionAssigned()); //Action can be assigned to type or to this object
|
||||
p_ReportSPITObject->setConfirmed(m_Confirmed);
|
||||
p_ReportSPITObject->setDelay(m_Delay);
|
||||
p_ReportSPITObject->setDuration(m_Duration);
|
||||
p_ReportSPITObject->setFixed(m_Fixed);
|
||||
p_ReportSPITObject->setFrameFadeInLength(m_FrameFadeInLength);
|
||||
p_ReportSPITObject->setFrameFadeOutLength(m_FrameFadeOutLength);
|
||||
p_ReportSPITObject->setFrameLength(m_FrameLength);
|
||||
p_ReportSPITObject->setFrameStart(m_FrameStart);
|
||||
p_ReportSPITObject->setID(m_ID);
|
||||
p_ReportSPITObject->setName(m_Name);
|
||||
p_ReportSPITObject->setRemark(m_Remark);
|
||||
p_ReportSPITObject->setSPITTypeID(m_SPITTypeID);
|
||||
p_ReportSPITObject->setServerParams(m_ServerParams);
|
||||
p_ReportSPITObject->setServerRemote(m_ServerRemote);
|
||||
p_ReportSPITObject->setTrack(m_Track);
|
||||
p_ReportSPITObject->setValueFactor(m_ValueFactor);
|
||||
p_ReportSPITObject->setValueUse(m_ValueUse);
|
||||
}
|
||||
void SPITObject::fillMessageOP(SPIT_Message::RemoveSPITObject* p_RemoveSPITObject) {
|
||||
p_RemoveSPITObject->setID(m_ID);
|
||||
}
|
||||
|
||||
void SPITObject::setID(string p_ID) {
|
||||
m_ID = p_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used by the server and client to tell if the other side has registered the changes.
|
||||
* @param p_Confirmed
|
||||
* @return if m_Confirmed has changed
|
||||
*/
|
||||
bool SPITObject::setConfirmed(bool p_Confirmed) {
|
||||
if (m_Confirmed == p_Confirmed) return false;
|
||||
m_Confirmed = p_Confirmed;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SPITObject::setName(string p_Name) {
|
||||
if (m_Name == p_Name) return false;
|
||||
m_Name = p_Name;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setRemark(string p_Remark) {
|
||||
if (m_Remark == p_Remark) return false;
|
||||
m_Remark = p_Remark;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setServerParams(string p_ServerParams) {
|
||||
if (m_ServerParams == p_ServerParams) return false;
|
||||
m_ServerParams = p_ServerParams;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setSPITTypeID(string p_SPITTypeID) {
|
||||
if (m_SPITTypeID == p_SPITTypeID) return false;
|
||||
m_SPITTypeID = p_SPITTypeID;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setServerRemote(bool p_BelongstoServer) {
|
||||
if (m_ServerRemote == p_BelongstoServer) return false;
|
||||
m_ServerRemote = p_BelongstoServer;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* This is a virtual construct - ActionAssignedType is not implemented in the SPITProtocol.<br>
|
||||
* This is used when an action is associated with a SPITType. <br>
|
||||
* Then this action is done for every SPITObject with the SPITType.
|
||||
* @return true = an action is assigned for the SPITType.
|
||||
*/
|
||||
bool SPITObject::setActionAssignedType(bool p_ActionAssigned) {
|
||||
if (m_ActionAssignedType == p_ActionAssigned) return false;
|
||||
bool boolOldActionAssigend;
|
||||
boolOldActionAssigend = getActionAssigned();
|
||||
m_ActionAssignedType = p_ActionAssigned;
|
||||
if (getActionAssigned() == boolOldActionAssigend) return false;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setActionAssigned(bool p_ActionAssigned) {
|
||||
if (m_ActionAssigned == p_ActionAssigned) return false;
|
||||
bool boolOldActionAssigend;
|
||||
boolOldActionAssigend = getActionAssigned();
|
||||
m_ActionAssigned = p_ActionAssigned;
|
||||
if (getActionAssigned() == boolOldActionAssigend) return false;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setFixed(bool p_Fixed) {
|
||||
if (m_Fixed == p_Fixed) return false;
|
||||
m_Fixed = p_Fixed;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setFrameStart(long long p_FrameStart) {
|
||||
if (m_FrameStart == p_FrameStart) return false;
|
||||
m_FrameStart = p_FrameStart;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setFrameLength(long long p_FrameLength) {
|
||||
if (m_FrameLength == p_FrameLength) return false;
|
||||
m_FrameLength = p_FrameLength;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setFrameFadeInLength(long long p_FrameFadeInLength) {
|
||||
if (m_FrameFadeInLength == p_FrameFadeInLength) return false;
|
||||
m_FrameFadeInLength = p_FrameFadeInLength;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setFrameFadeOutLength(long long p_FrameFadeOutLength) {
|
||||
if (m_FrameFadeOutLength == p_FrameFadeOutLength) return false;
|
||||
m_FrameFadeOutLength = p_FrameFadeOutLength;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setValueUse(char p_ValueUse) {
|
||||
if (m_ValueUse == p_ValueUse) return false;
|
||||
m_ValueUse = p_ValueUse;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setValueFactor(int p_ValueFactor) {
|
||||
if (m_ValueFactor == p_ValueFactor) return false;
|
||||
m_ValueFactor = p_ValueFactor;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setTrack(int p_Track) {
|
||||
if (m_Track == p_Track) return false;
|
||||
m_Track = p_Track;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setDelay(long long p_Delay) {
|
||||
if (m_Delay == p_Delay) return false;
|
||||
m_Delay = p_Delay;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITObject::setDuration(long long p_Duration) {
|
||||
if (m_Duration == p_Duration) return false;
|
||||
m_Duration = p_Duration;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPITPlayer describes a virtual SPIT Player.
|
||||
* File: SPITPLayer.cpp
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 30. April 2019, 11:44
|
||||
*/
|
||||
|
||||
#include "SPITPlayer.h"
|
||||
|
||||
recursive_mutex SPITPlayer::s_Mutex;
|
||||
unordered_map<string, SPITPlayer*> SPITPlayer::s_SPITPlayers;
|
||||
|
||||
SPITPlayer* SPITPlayer::getSPITPlayer(string p_PlayerID) {
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockSPITPlayer(*SPITPlayer::getMutex());
|
||||
auto i = s_SPITPlayers.find(p_PlayerID);
|
||||
if (i == s_SPITPlayers.end()) {
|
||||
s_SPITPlayers[p_PlayerID] = new SPITPlayer(p_PlayerID);
|
||||
}
|
||||
i = s_SPITPlayers.find(p_PlayerID);
|
||||
if (i == s_SPITPlayers.end()) return NULL;
|
||||
return i->second;
|
||||
}
|
||||
}
|
||||
|
||||
void SPITPlayer::clearPlayers() {
|
||||
SPITPlayer* ptrSPITPlayer;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockSPITPlayer(*SPITPlayer::getMutex());
|
||||
for (auto i = s_SPITPlayers.begin(); i != s_SPITPlayers.end(); i++) {
|
||||
ptrSPITPlayer = i->second;
|
||||
i = s_SPITPlayers.erase(i);
|
||||
delete ptrSPITPlayer;
|
||||
if (i == s_SPITPlayers.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
SPITPlayer::SPITPlayer(string p_PlayerID) {
|
||||
m_ID = p_PlayerID;
|
||||
s_SPITPlayers[p_PlayerID] = this;
|
||||
}
|
||||
|
||||
|
||||
SPITPlayer::~SPITPlayer() {
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockPlayer(s_Mutex);
|
||||
PlayObject* ptrPlayObject;
|
||||
for (auto i = m_PlayObjects.begin(); i != m_PlayObjects.end(); i++) {
|
||||
ptrPlayObject = i->second;
|
||||
i = m_PlayObjects.erase(i);
|
||||
delete ptrPlayObject;
|
||||
if (i == m_PlayObjects.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SPITPlayer::setIsRunning(bool p_IsRunning) {
|
||||
m_IsRunning = p_IsRunning;
|
||||
}
|
||||
void SPITPlayer::setName(string p_Name) {
|
||||
m_Name = p_Name;
|
||||
}
|
||||
void SPITPlayer::setType(char p_Type) {
|
||||
m_Type = p_Type;
|
||||
}
|
||||
void SPITPlayer::setTime(long long p_Frames) {
|
||||
m_TimeFrames = p_Frames;
|
||||
}
|
||||
|
||||
unordered_map<string, SPITPlayer::PlayObject*>* SPITPlayer::getPlayObjects() {
|
||||
return &m_PlayObjects;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param p_SPITObjectID
|
||||
* @return true = new PlayObject added<br>
|
||||
* false = PlayObject exists
|
||||
*/
|
||||
SPITPlayer::PlayObject* SPITPlayer::addSPITObject_Playing (string p_SPITObjectID) {
|
||||
PlayObject* ptrPlayObject;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockSPITPlayer(*SPITPlayer::getMutex());
|
||||
auto i = m_PlayObjects.find(p_SPITObjectID);
|
||||
if (i == m_PlayObjects.end()) {
|
||||
ptrPlayObject = new PlayObject(this, p_SPITObjectID);
|
||||
ptrPlayObject->setIsPlayed(true);
|
||||
ptrPlayObject->setIsNew(true);
|
||||
m_PlayObjects[p_SPITObjectID] = ptrPlayObject;
|
||||
}
|
||||
else {
|
||||
ptrPlayObject = i->second;
|
||||
ptrPlayObject->setIsPlayed(true);
|
||||
}
|
||||
return ptrPlayObject;
|
||||
}
|
||||
}
|
||||
|
||||
void SPITPlayer::startPlaySequence() {
|
||||
PlayObject* ptrPlayObject;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockSPITPlayer(*SPITPlayer::getMutex());
|
||||
for (auto i = m_PlayObjects.begin(); i != m_PlayObjects.end(); i++) {
|
||||
ptrPlayObject = i->second;
|
||||
ptrPlayObject->startPlaySequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
SPITPlayer::PlayObject* SPITPlayer::getPlayObject(string p_SPITObjectID) {
|
||||
auto i = m_SPITObjectsPlaying.find(p_SPITObjectID);
|
||||
if (i == m_SPITObjectsPlaying.end()) {
|
||||
return NULL;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
*/
|
||||
void SPITPlayer::endPlaySequence() {
|
||||
PlayObject* ptrPlayObject;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockSPITPlayer(*SPITPlayer::getMutex());
|
||||
for (auto i = m_PlayObjects.begin(); i != m_PlayObjects.end(); i++) {
|
||||
ptrPlayObject = i->second;
|
||||
if (ptrPlayObject->getIsPlayed() == false) {
|
||||
i = m_PlayObjects.erase(i);
|
||||
delete ptrPlayObject;
|
||||
if (i == m_PlayObjects.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
SPITPlayer::PlayObject::PlayObject() {
|
||||
}
|
||||
SPITPlayer::PlayObject::PlayObject(SPITPlayer* p_SPITPlayer, string p_SPITObjectID) {
|
||||
m_SPITObjectID = p_SPITObjectID;
|
||||
m_PlayerID = p_SPITPlayer->getID();
|
||||
m_PlayerName = p_SPITPlayer->getName();
|
||||
startPlaySequence();
|
||||
m_IsNew = true;
|
||||
}
|
||||
SPITPlayer::PlayObject::PlayObject(const PlayObject& orig) {
|
||||
m_SPITObjectID = orig.getSPITObjectID();
|
||||
m_IsPlayed = orig.getIsPlayed();
|
||||
m_IsNew = orig.getIsNew();
|
||||
|
||||
m_PlayerID = orig.getPlayerID();
|
||||
m_PlayerName = orig.getPlayerName();
|
||||
m_PlayerRuns = orig.getPlayerIsRunning();
|
||||
|
||||
m_Value = orig.getValueFade();
|
||||
m_ValuePrePosition = getValueFadePrePosition();
|
||||
m_ValueFactor = orig.getValueFactor();
|
||||
m_ValueFlag = orig.getValueFlag();
|
||||
m_FrameInsidePrePosition = orig.getFrameInsidePrePosition();
|
||||
m_FrameInside = orig.getFrameInside();
|
||||
}
|
||||
void SPITPlayer::PlayObject::startPlaySequence() {
|
||||
m_IsPlayed = false;
|
||||
m_IsNew = false;
|
||||
|
||||
m_FrameInside = -1;
|
||||
m_FrameInsidePrePosition = -1;
|
||||
m_Value = 0;
|
||||
m_ValuePrePosition = 0;
|
||||
m_ValueFlag = 0x00;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPITSOcket is the base class for WindowsSocket and UnixSocket.
|
||||
* File: SPITSocket.cpp
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 12. April 2019, 15:40
|
||||
*/
|
||||
|
||||
#include "SPITSocket.h"
|
||||
|
||||
//----- initialize static members -----
|
||||
recursive_mutex SPITSocket::s_MutexIPAddresses;
|
||||
unordered_map<string, SPITSocket::IPAddress*> SPITSocket::s_IPAddresses;
|
||||
int SPITSocket::FAMILY_IP4 = 2;
|
||||
int SPITSocket::FAMILY_IP6 = 23;
|
||||
|
||||
|
||||
SPITSocket::SPITSocket() {
|
||||
m_ServerIP = "";
|
||||
m_ServerPort = "";
|
||||
m_ClientIP = "";
|
||||
m_ClientPort = "";
|
||||
m_BoundClientPort = "";
|
||||
m_BoundClientFamily = 0;
|
||||
m_IsBound = false;
|
||||
}
|
||||
|
||||
|
||||
SPITSocket::~SPITSocket() {
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockSocket(m_MutexSocket);
|
||||
m_IsBound = false;
|
||||
}
|
||||
}
|
||||
void SPITSocket::setConnectionParams(string p_ServerIP, string p_ServerPort, string p_ClientIP, string p_ClientPort) {
|
||||
m_ServerIP = p_ServerIP;
|
||||
m_ServerPort = p_ServerPort;
|
||||
m_ClientIP = p_ClientIP;
|
||||
m_ClientPort = p_ClientPort;
|
||||
}
|
||||
string SPITSocket::getServerIP() {
|
||||
return m_ServerIP;
|
||||
}
|
||||
string SPITSocket::getServerPort(){
|
||||
return m_ServerPort;
|
||||
}
|
||||
string SPITSocket::getClientIP() {
|
||||
return m_ClientIP;
|
||||
}
|
||||
string SPITSocket::getClientPort() {
|
||||
return m_ClientPort;
|
||||
}
|
||||
string SPITSocket::getBoundClientPort() {
|
||||
return m_BoundClientPort;
|
||||
}
|
||||
void SPITSocket::setBoundClientPort(string p_Port) {
|
||||
m_BoundClientPort = p_Port;
|
||||
}
|
||||
int SPITSocket::getBoundClientFamily() {
|
||||
return m_BoundClientFamily;
|
||||
}
|
||||
void SPITSocket::setBoundClientFamily(int p_Family) {
|
||||
m_BoundClientFamily = p_Family;
|
||||
}
|
||||
|
||||
void SPITSocket::setIsBound(bool p_IsBound) {
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockSocket(m_MutexSocket);
|
||||
m_IsBound = p_IsBound;
|
||||
}
|
||||
}
|
||||
bool SPITSocket::getIsBound() {
|
||||
return m_IsBound;
|
||||
}
|
||||
|
||||
int SPITSocket::sendMessage(const char* p_MessageBytes, int p_MessageLength) {
|
||||
if (m_ServerPort.length() <= 0) return -1;
|
||||
int intResult;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockSocket(m_MutexSocket);
|
||||
if (m_IsBound == false) return -1;
|
||||
intResult = sendMessageTo(m_BoundClientFamily, m_ServerIP, m_ServerPort, p_MessageBytes, p_MessageLength);
|
||||
}
|
||||
return intResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---------- IP Adresses ---------
|
||||
void SPITSocket::addIPAddress(string p_IPAddress, string p_SubnetMask) {
|
||||
IPAddress* o_IPAddress;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockIP(s_MutexIPAddresses);
|
||||
auto i = s_IPAddresses.find(p_IPAddress);
|
||||
if (i != s_IPAddresses.end()) {
|
||||
o_IPAddress = i->second;
|
||||
}
|
||||
else {
|
||||
o_IPAddress = new IPAddress();
|
||||
}
|
||||
o_IPAddress->setIPAddress(p_IPAddress);
|
||||
o_IPAddress->setSubnetMask(p_SubnetMask);
|
||||
o_IPAddress->setFound(true);
|
||||
s_IPAddresses[o_IPAddress->getIPAddress()] = o_IPAddress;
|
||||
}
|
||||
}
|
||||
void SPITSocket::removeIPAddress(string p_IPAddress) {
|
||||
IPAddress* o_IPAddress;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockIP(s_MutexIPAddresses);
|
||||
auto i = s_IPAddresses.find(p_IPAddress);
|
||||
if (i != s_IPAddresses.end()) {
|
||||
o_IPAddress = i->second;
|
||||
i = s_IPAddresses.erase(i);
|
||||
delete o_IPAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
int SPITSocket::getIPAddressCount() {
|
||||
return s_IPAddresses.size();
|
||||
}
|
||||
SPITSocket::IPAddress* SPITSocket::getIPAddress(int p_Index) {
|
||||
IPAddress* ptr_IPAddress = NULL;
|
||||
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockIP(s_MutexIPAddresses);
|
||||
if (p_Index <= s_IPAddresses.size()) {
|
||||
unordered_map<string, IPAddress*>::iterator i = next(s_IPAddresses.begin(), p_Index);
|
||||
ptr_IPAddress = i->second;
|
||||
}
|
||||
return ptr_IPAddress;
|
||||
}
|
||||
}
|
||||
void SPITSocket::clearIPAddresses() {
|
||||
IPAddress* o_IPAddress;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockIP(s_MutexIPAddresses);
|
||||
for (auto i = s_IPAddresses.begin(); i != s_IPAddresses.end(); i++) {
|
||||
o_IPAddress = i->second;
|
||||
i = s_IPAddresses.erase(i);
|
||||
delete o_IPAddress;
|
||||
if (i == s_IPAddresses.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SPITSocket::resetFoundIPAddresses() {
|
||||
IPAddress* o_IPAddress;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockIP(s_MutexIPAddresses);
|
||||
for (auto i = s_IPAddresses.begin(); i != s_IPAddresses.end(); i++) {
|
||||
o_IPAddress = i->second;
|
||||
o_IPAddress->setFound(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
void SPITSocket::removeNotFoundIPAddresses() {
|
||||
IPAddress* o_IPAddress;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockIP(s_MutexIPAddresses);
|
||||
for (auto i = s_IPAddresses.begin(); i != s_IPAddresses.end(); i++) {
|
||||
o_IPAddress = i->second;
|
||||
if (o_IPAddress->getFound() == false) {
|
||||
i = s_IPAddresses.erase(i);
|
||||
delete o_IPAddress;
|
||||
if (i == s_IPAddresses.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------ IPAddress -------------------
|
||||
SPITSocket::IPAddress::IPAddress() {
|
||||
m_IPAddress = "";
|
||||
m_SubnetMask = "";
|
||||
m_Found = false;
|
||||
}
|
||||
SPITSocket::IPAddress::~IPAddress() {
|
||||
m_Found = false;
|
||||
}
|
||||
void SPITSocket::IPAddress::setIPAddress(const string& p_IPAddress) {
|
||||
m_IPAddress = p_IPAddress;
|
||||
}
|
||||
void SPITSocket::IPAddress::setSubnetMask(const string& p_SubnetMask) {
|
||||
m_SubnetMask = p_SubnetMask;
|
||||
}
|
||||
void SPITSocket::IPAddress::setFound(bool p_Found) {
|
||||
m_Found = p_Found;
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPITType describes a SPIT Type
|
||||
* File: SPITType.cpp
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 8. April 2019, 08:40
|
||||
*/
|
||||
|
||||
|
||||
#include "SPITType.h"
|
||||
#include "_SPITMACROS.h"
|
||||
|
||||
unordered_map<string, SPITType*> SPITType::s_SPITTypes;
|
||||
unordered_map<string, SPITType*> SPITType::s_SPITTypesRemote;
|
||||
recursive_mutex SPITType::s_MutexSPITType;
|
||||
|
||||
SPITType* SPITType::getSPITType(string p_ID) {
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
auto i = s_SPITTypes.find(p_ID);
|
||||
if (i == s_SPITTypes.end()) {
|
||||
return NULL;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the reference of the SPITType with ID == p_ID.<br>
|
||||
* Throws an exception if no SPITType is not found.<br>
|
||||
* @param p_ID the ID
|
||||
* @return reference of the SPITType with ID == p_ID
|
||||
*/
|
||||
const SPITType& SPITType::getSPITTypeRef(string p_ID) {
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
auto i = s_SPITTypes.find(p_ID);
|
||||
if (i == s_SPITTypes.end()) {
|
||||
throw "SPITType no SPITType with given ID";
|
||||
}
|
||||
return *(i->second);
|
||||
}
|
||||
}
|
||||
|
||||
SPITType* SPITType::getSPITTypeRemote(string p_ID) {
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
auto i = s_SPITTypesRemote.find(p_ID);
|
||||
if (i == s_SPITTypesRemote.end()) {
|
||||
return NULL;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the reference of the remote SPITType with ID == p_ID.<br>
|
||||
* Throws an exception if no SPITType is not found.<br>
|
||||
* @param p_ID the ID
|
||||
* @return reference of the SPITType with ID == p_ID
|
||||
*/
|
||||
const SPITType& SPITType::getSPITTypeRemoteRef(string p_ID) {
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
auto i = s_SPITTypesRemote.find(p_ID);
|
||||
if (i == s_SPITTypesRemote.end()) {
|
||||
throw "Remote SPITType no SPITType with given ID";
|
||||
}
|
||||
return *(i->second);
|
||||
}
|
||||
}
|
||||
|
||||
bool SPITType::addSPITType(SPITType* p_ptrSpitType) {
|
||||
if (p_ptrSpitType == NULL) return false;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
s_SPITTypes[p_ptrSpitType->getID()] = p_ptrSpitType;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bool SPITType::addSPITTypeRemote(SPITType* p_ptrSpitType) {
|
||||
if (p_ptrSpitType == NULL) return false;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
s_SPITTypesRemote[p_ptrSpitType->getID()] = p_ptrSpitType;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bool SPITType::removeSPITType(SPITType* p_ptrSpitType) {
|
||||
if (p_ptrSpitType == NULL) return false;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
auto i = s_SPITTypes.find(p_ptrSpitType->getID());
|
||||
if (i == s_SPITTypes.end()) {
|
||||
return false;
|
||||
}
|
||||
i = s_SPITTypes.erase(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bool SPITType::removeSPITTypeRemote(SPITType* p_ptrSpitType) {
|
||||
if (p_ptrSpitType == NULL) return false;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
auto i = s_SPITTypesRemote.find(p_ptrSpitType->getID());
|
||||
if (i == s_SPITTypesRemote.end()) {
|
||||
return false;
|
||||
}
|
||||
i = s_SPITTypesRemote.erase(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int SPITType::getSPITTypeCount() {
|
||||
return s_SPITTypes.size();
|
||||
}
|
||||
int SPITType::getSPITTypeRemoteCount() {
|
||||
return s_SPITTypesRemote.size();
|
||||
}
|
||||
SPITType* SPITType::getSPITType(int p_Index) {
|
||||
SPITType* ptrSPITType = NULL;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
if (p_Index < s_SPITTypes.size()) {
|
||||
unordered_map<string, SPITType*>::iterator i = next(s_SPITTypes.begin(), p_Index);
|
||||
ptrSPITType = i->second;
|
||||
}
|
||||
return ptrSPITType;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns a reference to the SPITType at position p_Index.<br>
|
||||
* Throws an exception if p_Index is out of range.<br>
|
||||
* @param p_Index position
|
||||
* @return the reference of the SPITType at position.
|
||||
*/
|
||||
const SPITType& SPITType::getSPITTypeRef(int p_Index) {
|
||||
SPITType* ptrSPITType = NULL;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
if (p_Index >= 0 && p_Index < s_SPITTypes.size()) {
|
||||
unordered_map<string, SPITType*>::iterator i = next(s_SPITTypes.begin(), p_Index);
|
||||
ptrSPITType = i->second;
|
||||
return *ptrSPITType;
|
||||
}
|
||||
else {
|
||||
throw "SPITType index out of range";
|
||||
}
|
||||
}
|
||||
}
|
||||
SPITType* SPITType::getSPITTypeRemote(int p_Index) {
|
||||
SPITType* ptrSPITType = NULL;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
if (p_Index < s_SPITTypesRemote.size()) {
|
||||
unordered_map<string, SPITType*>::iterator i = next(s_SPITTypesRemote.begin(), p_Index);
|
||||
ptrSPITType = i->second;
|
||||
}
|
||||
return ptrSPITType;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns a reference to the remote SPITType at position p_Index.<br>
|
||||
* Throws an exception if p_Index is out of range.<br>
|
||||
* @param p_Index position
|
||||
* @return the reference of the SPITType at position.
|
||||
*/
|
||||
const SPITType& SPITType::getSPITTypeRemoteRef(int p_Index) {
|
||||
SPITType* ptrSPITType = NULL;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
if (p_Index >= 0 && p_Index < s_SPITTypesRemote.size()) {
|
||||
unordered_map<string, SPITType*>::iterator i = next(s_SPITTypesRemote.begin(), p_Index);
|
||||
ptrSPITType = i->second;
|
||||
return *ptrSPITType;
|
||||
}
|
||||
else {
|
||||
throw "Remote SPITType index out of range";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SPITType::clearSPITTypes() {
|
||||
SPITType* ptrSPITType;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
for (auto i = s_SPITTypes.begin(); i != s_SPITTypes.end(); i++) {
|
||||
ptrSPITType = i->second;
|
||||
i = s_SPITTypes.erase(i);
|
||||
delete ptrSPITType;
|
||||
if (i == s_SPITTypes.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void SPITType::clearSPITTypesRemote() {
|
||||
SPITType* ptrSPITType;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
for (auto i = s_SPITTypesRemote.begin(); i != s_SPITTypesRemote.end(); i++) {
|
||||
ptrSPITType = i->second;
|
||||
i = s_SPITTypesRemote.erase(i);
|
||||
delete ptrSPITType;
|
||||
if (i == s_SPITTypesRemote.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets confirmed = false for all SPITTypes.<br>
|
||||
* This should be called when the client has loaded a project.<br>
|
||||
*/
|
||||
void SPITType::setConfirmedFalse() {
|
||||
SPITType* ptrSPITType;
|
||||
{
|
||||
unique_lock<recursive_mutex> o_LockType(s_MutexSPITType);
|
||||
for (auto i = s_SPITTypes.begin(); i != s_SPITTypes.end(); i++) {
|
||||
ptrSPITType = i->second;
|
||||
ptrSPITType->setConfirmed(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
SPITType::SPITType() {
|
||||
initMembers();
|
||||
}
|
||||
/*
|
||||
SPITType::SPITType(const SPITType& orig) {
|
||||
m_Confirmed = orig.getConfirmed();
|
||||
m_DefaultDelay = orig.getDefaultDelay();
|
||||
m_DefaultDuration = orig.getDefaultDuration();
|
||||
m_Fixed = orig.getFixed();
|
||||
m_GroupName = orig.getGroupName();
|
||||
m_ID = orig.getID();
|
||||
m_Name = orig.getName();
|
||||
m_ServerProjectIndepended = orig.getProjectIndepended();
|
||||
m_ServerRemote = orig.getServerRemote();
|
||||
}
|
||||
*/
|
||||
SPITType::SPITType(string p_ID, string p_GroupName, string p_Name, bool p_Fixed, bool p_ProjectIndepended,long long p_DefaultDelay, long long p_DefaultDuration) {
|
||||
initMembers();
|
||||
m_ActionAssigned = false;
|
||||
m_Confirmed = false;
|
||||
m_ID = p_ID;
|
||||
m_GroupName = p_GroupName;
|
||||
m_Name = p_Name;
|
||||
m_Fixed = p_Fixed;
|
||||
m_ServerProjectIndepended = p_ProjectIndepended;
|
||||
m_DefaultDelay = p_DefaultDelay;
|
||||
m_DefaultDuration = p_DefaultDuration;
|
||||
}
|
||||
|
||||
SPITType::~SPITType() {
|
||||
}
|
||||
|
||||
void SPITType::initMembers() {
|
||||
m_Confirmed = false;
|
||||
m_DefaultDelay = 0;
|
||||
m_DefaultDuration = 0;
|
||||
m_Fixed = false;
|
||||
m_GroupName = "";
|
||||
m_ID = createGUID();
|
||||
m_Name = "";
|
||||
m_ServerProjectIndepended = false;
|
||||
m_ServerRemote = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SPITType::setCreatedByClient(bool p_CreatedByClient) {
|
||||
m_CreatedByClient = p_CreatedByClient;
|
||||
}
|
||||
|
||||
|
||||
void SPITType::setID(string p_ID) {
|
||||
m_ID = p_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used by the server and client to tell if the other side has registered the changes.
|
||||
* @param p_Confirmed
|
||||
* @return if m_Confirmed has changed
|
||||
*/
|
||||
bool SPITType::setConfirmed(bool p_Confirmed) {
|
||||
if (m_Confirmed == p_Confirmed) return false;
|
||||
m_Confirmed = p_Confirmed;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SPITType::setGroupName(string p_GroupName) {
|
||||
if (m_GroupName == p_GroupName) return false;
|
||||
m_GroupName = p_GroupName;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITType::setName(string p_Name) {
|
||||
if (m_Name == p_Name) return false;
|
||||
m_Name = p_Name;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITType::setServerRemote(bool p_BelongstoServer) {
|
||||
if (m_ServerRemote == p_BelongstoServer) return false;
|
||||
m_ServerRemote = p_BelongstoServer;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITType::setProjectIndepended(bool p_ProjectIndepended) {
|
||||
if (m_ServerProjectIndepended == p_ProjectIndepended) return false;
|
||||
m_ServerProjectIndepended = p_ProjectIndepended;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITType::setFixed(bool p_Fixed) {
|
||||
if (m_Fixed == p_Fixed) return false;
|
||||
m_Fixed = p_Fixed;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITType::setDefaultDelay(long long p_Delay) {
|
||||
if (m_DefaultDelay == p_Delay) return false;
|
||||
m_DefaultDelay = p_Delay;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
bool SPITType::setDefaultDuration(long long p_Duration) {
|
||||
if (m_DefaultDuration == p_Duration) return false;
|
||||
m_DefaultDuration = p_Duration;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Virtual construct - means ActionAssigned for SPITTypes is is not implemented in SPITProtocol.<br>
|
||||
* This can used to setActionAssigned to all SPITObjects with this SPITType.<br>
|
||||
* This may be used in the case when the same action should be done for every SPITObject with this SPITType associated.<br>
|
||||
* @return true = the m_ActionAssigned has changed.
|
||||
*/
|
||||
bool SPITType::setActionAssigned(bool p_ActionAssigned) {
|
||||
if (m_ActionAssigned == p_ActionAssigned) return false;
|
||||
m_ActionAssigned = p_ActionAssigned;
|
||||
m_Confirmed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the content of the SPITType as received from the server
|
||||
* @param p_ReportSPITType
|
||||
* @return true = the SPITType is changed<br>
|
||||
* false = the SPITType is NOT changed, because it is not allowed to change.
|
||||
*/
|
||||
bool SPITType::setMessageOP(SPIT_Message::ReportSPITType* p_ReportSPITType) {
|
||||
bool boolChangeAllowed;
|
||||
|
||||
if (m_CreatedByClient == true && m_Fixed == true) {
|
||||
boolChangeAllowed = false;
|
||||
}
|
||||
else {
|
||||
boolChangeAllowed = true;
|
||||
}
|
||||
|
||||
//Confirmation should be changable
|
||||
if (m_CreatedByClient) {
|
||||
//Server reports a client created SPITType -> the type is confirmed
|
||||
m_Confirmed = true;
|
||||
}
|
||||
else {
|
||||
//type is NOT client created -> the client has to confirm the SPITtype
|
||||
m_Confirmed = p_ReportSPITType->getConfirmed();
|
||||
}
|
||||
if (m_DefaultDelay != p_ReportSPITType->getDelay()) {
|
||||
if (boolChangeAllowed == false) return false;
|
||||
m_DefaultDelay = p_ReportSPITType->getDelay();
|
||||
}
|
||||
if (m_DefaultDuration != p_ReportSPITType->getDuration()) {
|
||||
if (boolChangeAllowed == false) return false;
|
||||
m_DefaultDuration = p_ReportSPITType->getDuration();
|
||||
}
|
||||
if (m_Fixed != p_ReportSPITType->getFixed()) {
|
||||
if (boolChangeAllowed == false) return false;
|
||||
m_Fixed = p_ReportSPITType->getFixed();
|
||||
}
|
||||
if (m_GroupName != p_ReportSPITType->getGroupName()) {
|
||||
if (boolChangeAllowed == false) return false;
|
||||
m_GroupName = p_ReportSPITType->getGroupName();
|
||||
}
|
||||
if (m_ID != p_ReportSPITType->getID()) {
|
||||
if (boolChangeAllowed == false) return false;
|
||||
m_ID = p_ReportSPITType->getID();
|
||||
}
|
||||
if (m_Name != p_ReportSPITType->getName()) {
|
||||
if (boolChangeAllowed == false) return false;
|
||||
m_Name = p_ReportSPITType->getName();
|
||||
}
|
||||
if (m_ServerProjectIndepended != p_ReportSPITType->getServerProjectIndepended()) {
|
||||
if (boolChangeAllowed == false) return false;
|
||||
m_ServerProjectIndepended = p_ReportSPITType->getServerProjectIndepended();
|
||||
}
|
||||
if (m_ServerRemote != p_ReportSPITType->getServerRemote()) {
|
||||
if (boolChangeAllowed == false) return false;
|
||||
m_ServerRemote = p_ReportSPITType->getServerRemote();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SPITType::fillMessageOP(SPIT_Message::ReportSPITType* ptrSMReportSPITType) {
|
||||
ptrSMReportSPITType->setConfirmed(m_Confirmed);
|
||||
ptrSMReportSPITType->setDelay(m_DefaultDelay);
|
||||
ptrSMReportSPITType->setDuration(m_DefaultDuration);
|
||||
ptrSMReportSPITType->setFixed(m_Fixed);
|
||||
ptrSMReportSPITType->setGroupName(m_GroupName);
|
||||
ptrSMReportSPITType->setID(m_ID);
|
||||
ptrSMReportSPITType->setName(m_Name);
|
||||
ptrSMReportSPITType->setServerProjectIndepended(m_ServerProjectIndepended);
|
||||
ptrSMReportSPITType->setServerRemote(m_ServerRemote);
|
||||
}
|
||||
void SPITType::fillMessageOP(SPIT_Message::RemoveSPITType* ptrSMRemoveSPITType) {
|
||||
ptrSMRemoveSPITType->setID(m_ID);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPITHandler lists runnable instances and processes them in order.
|
||||
* File: SPIT_Handler.cpp
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 24. April 2019, 11:18
|
||||
*/
|
||||
|
||||
#include "SPIT_Handler.h"
|
||||
|
||||
|
||||
mutex SPIT_Handler::s_MutexLock;
|
||||
condition_variable SPIT_Handler::s_ConditionVariable;
|
||||
list<SPIT_Handler::Runnable*> SPIT_Handler::s_Runnables;
|
||||
bool SPIT_Handler::s_WakeUp = false;
|
||||
bool SPIT_Handler::s_Close = false;
|
||||
thread SPIT_Handler::s_HandlerThread(SPIT_Handler::run);
|
||||
SPIT_Handler::Runnable::~Runnable() {}
|
||||
|
||||
|
||||
void SPIT_Handler::addRunnable(Runnable* p_Runnable) {
|
||||
if (p_Runnable == NULL) return;
|
||||
{
|
||||
unique_lock<mutex> o_Unique_Lock(s_MutexLock);
|
||||
if (s_Close == true) return;
|
||||
s_Runnables.push_back(p_Runnable);
|
||||
s_WakeUp = true;
|
||||
}
|
||||
if (this_thread::get_id() != s_HandlerThread.get_id()) {
|
||||
s_ConditionVariable.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
void SPIT_Handler::closeHandler() {
|
||||
if (s_Close == true) return;
|
||||
{
|
||||
unique_lock<mutex> o_Unique_Lock(s_MutexLock);
|
||||
if (s_Close == true) return;
|
||||
|
||||
s_Close = true;
|
||||
s_WakeUp = true;
|
||||
}
|
||||
if (this_thread::get_id() != s_HandlerThread.get_id()) {
|
||||
s_ConditionVariable.notify_one();
|
||||
s_HandlerThread.join();
|
||||
}
|
||||
}
|
||||
void SPIT_Handler::run() {
|
||||
Runnable* o_Runnable;
|
||||
bool boolWait = false;
|
||||
while (s_Close == false) {
|
||||
boolWait = false;
|
||||
{
|
||||
unique_lock<mutex> o_Lock(s_MutexLock);
|
||||
|
||||
if (s_Runnables.empty()) {
|
||||
s_ConditionVariable.wait(o_Lock, []{return s_WakeUp;});
|
||||
}
|
||||
if (s_Close == true) {
|
||||
s_WakeUp = true;
|
||||
return;;
|
||||
}
|
||||
|
||||
s_WakeUp = false;
|
||||
|
||||
if (s_Runnables.empty()) {
|
||||
o_Lock.unlock();
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
o_Runnable = s_Runnables.front();
|
||||
s_Runnables.erase(s_Runnables.begin());
|
||||
}
|
||||
}
|
||||
|
||||
if (o_Runnable != NULL) {
|
||||
try {
|
||||
o_Runnable->run();
|
||||
delete o_Runnable;
|
||||
}
|
||||
catch(...) {
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("ERROR SPITHandler o_Runable->run()\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Unix implementation of a SPITSocket.
|
||||
*
|
||||
* File: UnixSocket.cpp
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 12. April 2019, 15:58
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "_SPITMACROS.h"
|
||||
#if defined(OS_MAC) || defined(OS_LINUX)
|
||||
|
||||
|
||||
#include "UnixSocket.h"
|
||||
|
||||
UnixSocket::UnixSocket() : SPITSocket(){
|
||||
SPITSocket::FAMILY_IP4 = AF_INET;
|
||||
SPITSocket::FAMILY_IP6 = AF_INET6;
|
||||
m_UDPSocketIP4 = INVALID_SOCKET;
|
||||
m_UDPSocketIP6 = INVALID_SOCKET;
|
||||
createSocket_UDP();
|
||||
}
|
||||
|
||||
|
||||
UnixSocket::~UnixSocket() {
|
||||
|
||||
int intResultIP4;
|
||||
int intResultIP6;
|
||||
if (m_UDPSocketIP4 != INVALID_SOCKET) {
|
||||
// intResultIP4 = shutdown(m_UDPSocketIP4, 2);
|
||||
intResultIP4 = close(m_UDPSocketIP4);
|
||||
m_UDPSocketIP4 = INVALID_SOCKET;
|
||||
}
|
||||
if (m_UDPSocketIP6 != INVALID_SOCKET) {
|
||||
// intResultIP6 = shutdown(m_UDPSocketIP6, 2);
|
||||
intResultIP6 = close(m_UDPSocketIP6);
|
||||
m_UDPSocketIP6 = INVALID_SOCKET;
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
int UnixSocket::init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int UnixSocket::cleanUp() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates two new sockets.<br>
|
||||
* One socket for IP4 and one for IP6.<br>
|
||||
* If there exist some, they will be closed.<br>
|
||||
* @return
|
||||
*/
|
||||
bool UnixSocket::createSocket_UDP() {
|
||||
bool boolSuccess = true;
|
||||
int intResult;
|
||||
int intOptionValue4 = 1;
|
||||
int intOptionValue6 = 1;
|
||||
u_char charOptionValue = 0x01;
|
||||
|
||||
//ip4
|
||||
if (m_UDPSocketIP4 != INVALID_SOCKET) {
|
||||
close(m_UDPSocketIP4);
|
||||
m_UDPSocketIP4 = INVALID_SOCKET;
|
||||
}
|
||||
if (m_UDPSocketIP6 != INVALID_SOCKET) {
|
||||
close(m_UDPSocketIP6);
|
||||
m_UDPSocketIP6 = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
|
||||
m_UDPSocketIP4 = socket(AF_INET,SOCK_DGRAM, 0);
|
||||
if (m_UDPSocketIP4 == INVALID_SOCKET) {
|
||||
boolSuccess = false;
|
||||
}
|
||||
else {
|
||||
intResult = setsockopt(m_UDPSocketIP4, SOL_SOCKET, SO_REUSEADDR, (void*)&intOptionValue4, sizeof(intOptionValue4));
|
||||
}
|
||||
|
||||
m_UDPSocketIP6 = socket(AF_INET6,SOCK_DGRAM, 0);
|
||||
if (m_UDPSocketIP6 == INVALID_SOCKET) {
|
||||
boolSuccess = false;
|
||||
close(m_UDPSocketIP4);
|
||||
m_UDPSocketIP4 = INVALID_SOCKET;
|
||||
}
|
||||
else {
|
||||
intResult = setsockopt(m_UDPSocketIP6, SOL_SOCKET, SO_REUSEADDR, (void*)&intOptionValue6, sizeof(intOptionValue6));
|
||||
}
|
||||
//set the m_UDPSocketIP4 and m_UDPSocketIP6 in NON BLOCKING mode because
|
||||
//if the UDPSockets are in blocking mode the receiveMessage does not return in every constellation
|
||||
int intFlags;
|
||||
intFlags = fcntl(m_UDPSocketIP4, F_GETFL);
|
||||
fcntl(m_UDPSocketIP4, F_SETFL, intFlags | O_NONBLOCK);
|
||||
intFlags = fcntl(m_UDPSocketIP6, F_GETFL);
|
||||
fcntl(m_UDPSocketIP6, F_SETFL, intFlags | O_NONBLOCK);
|
||||
|
||||
if (intResult < 0) {
|
||||
boolSuccess = false;
|
||||
}
|
||||
return boolSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the socket to the client's ip address and port.<br>
|
||||
* The socket option SO_REUSEADDR is set to true.<br>
|
||||
* @param p_ClientIP ip address of the client
|
||||
* @param p_ClientPort port of the client.<br>
|
||||
* if p_Port == "0" any free port will be used<br>
|
||||
* @return -1 id bind fails, o if bind is ok
|
||||
*
|
||||
*/
|
||||
int UnixSocket::bindSocket(string p_ClientIP, string p_ClientPort) {
|
||||
addrinfo *clientAI;
|
||||
struct sockaddr_in* ptrIP4SocketAddress;
|
||||
struct sockaddr_in o_IP4SocketAddress;
|
||||
struct sockaddr_in6* ptrIP6SocketAddress;
|
||||
struct sockaddr_in6 o_IP6SocketAddress;
|
||||
int intSocklen;
|
||||
string stringClientPort;
|
||||
if (p_ClientPort.length() <= 0) stringClientPort = "0";
|
||||
else stringClientPort = p_ClientPort;
|
||||
//int intResult = SOCKET_ERROR;
|
||||
int intResult = 0;
|
||||
if (getaddrinfo(p_ClientIP.data(), p_ClientPort.data(), NULL, &clientAI) != 0) {
|
||||
return -1;
|
||||
}
|
||||
switch(clientAI->ai_family) {
|
||||
case AF_INET:
|
||||
if (m_UDPSocketIP4 == INVALID_SOCKET) {
|
||||
break;
|
||||
}
|
||||
ptrIP4SocketAddress = reinterpret_cast<sockaddr_in*>(clientAI->ai_addr);
|
||||
intSocklen = sizeof (*ptrIP4SocketAddress);
|
||||
//copy the ptrIP4SocketAddress, may be not filled correct by getaddrinfo
|
||||
memset(&o_IP4SocketAddress, 0, intSocklen);
|
||||
o_IP4SocketAddress.sin_addr = ptrIP4SocketAddress->sin_addr;
|
||||
o_IP4SocketAddress.sin_family = ptrIP4SocketAddress->sin_family;
|
||||
#if defined(OS_MAC)
|
||||
o_IP4SocketAddress.sin_len = ptrIP4SocketAddress->sin_len;
|
||||
#endif
|
||||
#if defined(OS_LINUX)
|
||||
//o_IP4SocketAddress.sin_zero = ptrIP4SocketAddress->sin_zero;
|
||||
#endif
|
||||
o_IP4SocketAddress.sin_port = ptrIP4SocketAddress->sin_port;
|
||||
intResult = bind(m_UDPSocketIP4, (const sockaddr*)(ptrIP4SocketAddress),(socklen_t)intSocklen);
|
||||
if (intResult < 0) {
|
||||
break;
|
||||
}
|
||||
setBoundClientFamily(AF_INET);
|
||||
if (intResult == 0) {
|
||||
if (getsockname(m_UDPSocketIP4, (sockaddr*)ptrIP4SocketAddress, (socklen_t*)&intSocklen) != -1) {
|
||||
setBoundClientPort(to_string((int)ptrIP4SocketAddress->sin_port));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (m_UDPSocketIP6 == INVALID_SOCKET) {
|
||||
break;
|
||||
}
|
||||
ptrIP6SocketAddress = reinterpret_cast<sockaddr_in6*>(clientAI->ai_addr);
|
||||
intSocklen = sizeof (*ptrIP6SocketAddress);
|
||||
//copy the ptrIP6SocketAddress, may be not filled correct by getaddrinfo
|
||||
o_IP6SocketAddress.sin6_addr = ptrIP6SocketAddress->sin6_addr;
|
||||
o_IP6SocketAddress.sin6_family = ptrIP6SocketAddress->sin6_family;
|
||||
o_IP6SocketAddress.sin6_flowinfo = ptrIP6SocketAddress->sin6_flowinfo;
|
||||
o_IP6SocketAddress.sin6_port = ptrIP6SocketAddress->sin6_port;
|
||||
o_IP6SocketAddress.sin6_scope_id = ptrIP6SocketAddress->sin6_scope_id;
|
||||
intResult = bind(m_UDPSocketIP6, (const sockaddr*)(ptrIP6SocketAddress), (socklen_t)intSocklen);
|
||||
if (intResult < 0) {
|
||||
break;
|
||||
}
|
||||
setBoundClientFamily(AF_INET6);
|
||||
|
||||
if (intResult == 0) {
|
||||
if (getsockname(m_UDPSocketIP6, (sockaddr*)ptrIP6SocketAddress, (socklen_t*)&intSocklen) != -1) {
|
||||
setBoundClientPort(to_string((int)ptrIP6SocketAddress->sin6_port));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
setBoundClientFamily(0);
|
||||
intResult = -1;
|
||||
break;
|
||||
}
|
||||
freeaddrinfo(clientAI);
|
||||
|
||||
if (intResult == -1) {
|
||||
setIsBound(false);
|
||||
}
|
||||
else {
|
||||
setIsBound(true);
|
||||
}
|
||||
return intResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sockopt SO_BROADCAST to 0 or 1
|
||||
* @param p_Broadcast true SO_BROADCAST is set<br>
|
||||
* false = SO_BROADCAST is not set
|
||||
* @return 0 = ok, -1 = error
|
||||
*/
|
||||
int UnixSocket::setBroadcast(bool p_Broadcast) {
|
||||
int intResult;
|
||||
int intOptionValue = 1;
|
||||
u_char charOptionValue = 0x01;
|
||||
//IP4
|
||||
if (p_Broadcast) {
|
||||
intOptionValue = 1;
|
||||
}
|
||||
else {
|
||||
intOptionValue = 0;
|
||||
}
|
||||
intResult = setsockopt(m_UDPSocketIP4, SOL_SOCKET, SO_BROADCAST, &intOptionValue, sizeof(int));
|
||||
// intResult = setsockopt(m_UDPSocketIP4, IPPROTO_IP, IP_MULTICAST_LOOP, (void*)&charOptionValue, sizeof(charOptionValue));
|
||||
|
||||
//IP6
|
||||
// intResult = setsockopt(m_UDPSocketIP6, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (void*)&charOptionValue, sizeof(charOptionValue));
|
||||
|
||||
return intResult;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param p_InetFamily AF_INET or AF_INET6
|
||||
* @param p_ServerIP the ip address of the server
|
||||
* @param p_ServerPort the port of the server
|
||||
* @param p_MessageBytes buffer containing the message
|
||||
* @param p_MessageLength the length of the message
|
||||
* @return -1 send fails<br>
|
||||
* 0 send is done
|
||||
*/
|
||||
int UnixSocket::sendMessageTo(int p_InetFamily, string p_ServerIP, string p_ServerPort, const char* p_MessageBytes, int p_MessageLength) {
|
||||
if (m_UDPSocketIP4 == INVALID_SOCKET && m_UDPSocketIP6 == INVALID_SOCKET) return -1;
|
||||
struct addrinfo* ptrAddressInfo;
|
||||
struct sockaddr_in* ptrIP4SocketAddress;
|
||||
struct sockaddr_in o_IP4SocketAddress;
|
||||
struct sockaddr_in6* ptrIP6SocketAddress;
|
||||
struct sockaddr_in6 o_IP6SocketAddress;
|
||||
int intSocklen;
|
||||
int intResult = -1;
|
||||
|
||||
// prepare AddressInfo
|
||||
if (getaddrinfo(p_ServerIP.data(), p_ServerPort.data(), NULL, &ptrAddressInfo) != 0) {
|
||||
return -1;
|
||||
}
|
||||
switch(ptrAddressInfo->ai_family) {
|
||||
case AF_INET:
|
||||
ptrIP4SocketAddress = reinterpret_cast<sockaddr_in*>(ptrAddressInfo->ai_addr);
|
||||
intSocklen = sizeof(*ptrIP4SocketAddress);
|
||||
if (m_UDPSocketIP4 != INVALID_SOCKET) {
|
||||
//copy the ptrIP4SocketAddress, may be not filled correct by getaddrinfo
|
||||
memset(&o_IP4SocketAddress, 0, intSocklen);
|
||||
o_IP4SocketAddress.sin_addr = ptrIP4SocketAddress->sin_addr;
|
||||
o_IP4SocketAddress.sin_family = ptrIP4SocketAddress->sin_family;
|
||||
o_IP4SocketAddress.sin_port = ptrIP4SocketAddress->sin_port;
|
||||
intResult = sendto(m_UDPSocketIP4, p_MessageBytes, p_MessageLength, 0, (const sockaddr*)&o_IP4SocketAddress, (socklen_t)intSocklen);
|
||||
if (intResult < 0) printf("UnixSocket::sendMessageTo IP4 sendto %s FAILED %s\n", p_ServerIP.data(), strerror(errno));
|
||||
freeaddrinfo(ptrAddressInfo);
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
ptrIP6SocketAddress = reinterpret_cast<sockaddr_in6*>(ptrAddressInfo->ai_addr);
|
||||
intSocklen = sizeof(*ptrIP6SocketAddress);
|
||||
if (m_UDPSocketIP6 != INVALID_SOCKET) {
|
||||
//copy the ptrIP6SocketAddress, may be not filled correct by getaddrinfo
|
||||
o_IP6SocketAddress.sin6_addr = ptrIP6SocketAddress->sin6_addr;
|
||||
o_IP6SocketAddress.sin6_family = ptrIP6SocketAddress->sin6_family;
|
||||
o_IP6SocketAddress.sin6_flowinfo = ptrIP6SocketAddress->sin6_flowinfo;
|
||||
o_IP6SocketAddress.sin6_port = ptrIP6SocketAddress->sin6_port;
|
||||
o_IP6SocketAddress.sin6_scope_id = ptrIP6SocketAddress->sin6_scope_id;
|
||||
intResult = sendto(m_UDPSocketIP6, p_MessageBytes, p_MessageLength, 0, (const sockaddr*)&o_IP6SocketAddress, (socklen_t)intSocklen);
|
||||
if (intResult < 0) printf("UnixSocket::sendMessageTo IP6 sendto %s FAILED %s\n", p_ServerIP.data(), strerror(errno));
|
||||
freeaddrinfo(ptrAddressInfo);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
intResult = -1;
|
||||
}
|
||||
|
||||
if (intResult == -1) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Starts receiving a message
|
||||
* @param p_InetFamily AF_INET or AF_INET6
|
||||
* @param p_Buffer a char* buffer large enough to hold the expected data
|
||||
* @param p_BufferLength the length of the buffer
|
||||
* @param p_ServerIP = NULL, the ip address is not determined<br>
|
||||
* != NULL after receiving a message p_ServerID contains the ip address of the sender/server
|
||||
* @return
|
||||
*/
|
||||
int UnixSocket::receiveMessage(int p_InetFamily, char* p_Buffer, int p_BufferLength, string* p_ServerIP) {
|
||||
int intResult = -1;
|
||||
// ADDRINFO *AI;
|
||||
struct sockaddr_in o_IP4SocketAddress;
|
||||
struct sockaddr_in6 o_IP6SocketAddress;
|
||||
int intSocklen;
|
||||
|
||||
switch(p_InetFamily) {
|
||||
case AF_INET:
|
||||
if (m_UDPSocketIP4 == INVALID_SOCKET) {
|
||||
break;
|
||||
}
|
||||
intSocklen = sizeof(o_IP4SocketAddress);
|
||||
memset(&o_IP4SocketAddress, 0, intSocklen);
|
||||
intResult = recvfrom(m_UDPSocketIP4, (void*)p_Buffer, p_BufferLength, 0, (sockaddr*)&o_IP4SocketAddress, (socklen_t*)&intSocklen);
|
||||
if (intResult >= 0) {
|
||||
if (p_ServerIP != NULL) {
|
||||
char bufferIP4[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &(o_IP4SocketAddress.sin_addr), bufferIP4, intSocklen);
|
||||
*p_ServerIP = bufferIP4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (m_UDPSocketIP6 == INVALID_SOCKET) {
|
||||
break;
|
||||
}
|
||||
intSocklen = sizeof(o_IP6SocketAddress);
|
||||
memset(&o_IP6SocketAddress, 0, intSocklen);
|
||||
intResult = recvfrom(m_UDPSocketIP6, (void*)p_Buffer, p_BufferLength, 0, (sockaddr*)&o_IP6SocketAddress, (socklen_t*)&intSocklen);
|
||||
if (intResult >= 0) {
|
||||
if (p_ServerIP != NULL) {
|
||||
char bufferIP6[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &(o_IP6SocketAddress.sin6_addr), bufferIP6, intSocklen);
|
||||
*p_ServerIP = bufferIP6;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return intResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the broadcast address from a ip4 address.<br>
|
||||
* @param p_IPAddress the ip4 address
|
||||
* @return returns the broadcast address
|
||||
*/
|
||||
string UnixSocket::getBroadcastIP4(SPITSocket::IPAddress* p_IPAddress) {
|
||||
struct in_addr broadcast;
|
||||
unsigned long ulIPAddress;
|
||||
unsigned long ulSubnetMask;
|
||||
|
||||
ulIPAddress = inet_addr(p_IPAddress->getIPAddress().data());
|
||||
ulSubnetMask = inet_addr(p_IPAddress->getSubnetMask().data());
|
||||
broadcast.s_addr = ulIPAddress | ~ulSubnetMask;
|
||||
|
||||
return inet_ntoa(broadcast);
|
||||
}
|
||||
|
||||
void UnixSocket::getAdaptersInfo() {
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
struct sockaddr_in *o_sockaddr_in;
|
||||
// struct sockaddr_in6 *o_sockaddr_in6;
|
||||
char buffer[64];
|
||||
string stringIP4;
|
||||
string stringSubnet;
|
||||
void *in_addr;
|
||||
void *in_subnet;
|
||||
|
||||
resetFoundIPAddresses();
|
||||
|
||||
if (getifaddrs(&ifaddr) == -1) {
|
||||
printf("UnixSocket::getAdaptersInfo getifaddrs < 0\n");
|
||||
return;
|
||||
}
|
||||
|
||||
struct sockaddr* ptrSockAddr;
|
||||
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
|
||||
if (ifa->ifa_addr == NULL) break;
|
||||
|
||||
switch (ifa->ifa_addr->sa_family) {
|
||||
case AF_INET:
|
||||
o_sockaddr_in = (struct sockaddr_in *)ifa->ifa_addr;
|
||||
in_addr = &o_sockaddr_in->sin_addr;
|
||||
o_sockaddr_in = (struct sockaddr_in *)ifa->ifa_netmask;
|
||||
in_subnet = &o_sockaddr_in->sin_addr;
|
||||
break;
|
||||
case AF_INET6:
|
||||
continue;
|
||||
/*
|
||||
o_sockaddr_in6 = (struct sockaddr_in6 *)ifa->ifa_addr;
|
||||
in_addr = &o_sockaddr_in6->sin6_addr;
|
||||
o_sockaddr_in6 = (struct sockaddr_in6 *)ifa->ifa_netmask;
|
||||
in_subnet = &o_sockaddr_in6->sin6_addr;
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
if (inet_ntop(ifa->ifa_addr->sa_family, in_addr, buffer, sizeof(buffer))) {
|
||||
stringIP4 = buffer;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
if (inet_ntop(ifa->ifa_addr->sa_family, in_subnet, buffer, sizeof(buffer))) {
|
||||
stringSubnet = buffer;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("Networkadapter %s: %s Subnet %s\n", ifa->ifa_name, stringIP4.data(), stringSubnet.data());
|
||||
#endif
|
||||
addIPAddress(stringIP4, stringSubnet);
|
||||
}
|
||||
//IP4 loopback maybe not ok
|
||||
#if defined(DEBUGOUTPUT)
|
||||
printf("Networkinterfaces add/change loopback 127.0.0.1 subnet 255.255.255.0\n");
|
||||
#endif
|
||||
addIPAddress("127.0.0.1", "255.255.255.0");
|
||||
|
||||
freeifaddrs(ifaddr);
|
||||
|
||||
removeNotFoundIPAddresses();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPITWatchdog sends watchdog messages to the server from time to time.
|
||||
* If there is no response from the server an eventWatchdogLost is triggered.
|
||||
*
|
||||
* File: Watchdog.cpp
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 22. April 2019, 13:02
|
||||
*/
|
||||
|
||||
|
||||
#include "Watchdog.h"
|
||||
|
||||
int Watchdog::WATCHDOGTIME = 3000;
|
||||
bool Watchdog::s_StopWatchdog = true;
|
||||
|
||||
Watchdog::Watchdog(Listener* p_Listener) {
|
||||
s_StopWatchdog = true;
|
||||
m_Listener = p_Listener;
|
||||
m_WatchdogThread = NULL;
|
||||
}
|
||||
|
||||
|
||||
Watchdog::~Watchdog() {
|
||||
stopWatchdog();
|
||||
}
|
||||
|
||||
void Watchdog::startWatchdog() {
|
||||
if (s_StopWatchdog == false) return;
|
||||
{
|
||||
unique_lock<mutex> o_UniqueLock(m_MutexLock);
|
||||
s_StopWatchdog = false;
|
||||
}
|
||||
m_WatchdogThread = new thread(&Watchdog::runWatchdog, this);
|
||||
}
|
||||
void Watchdog::stopWatchdog() {
|
||||
if (m_WatchdogThread != NULL) {
|
||||
{
|
||||
unique_lock<mutex> o_UniqueLock(m_MutexLock);
|
||||
if (s_StopWatchdog == true) {
|
||||
return;
|
||||
}
|
||||
s_StopWatchdog = true;
|
||||
}
|
||||
if (this_thread::get_id() != m_WatchdogThread->get_id()) {
|
||||
m_ConditionVariable.notify_one();
|
||||
m_WatchdogThread->join();
|
||||
}
|
||||
m_WatchdogThread = NULL;
|
||||
}
|
||||
}
|
||||
void Watchdog::answerWatchdog() {
|
||||
m_Answered = true;
|
||||
}
|
||||
|
||||
void Watchdog::runWatchdog() {
|
||||
bool boolDone;
|
||||
auto waitTime = std::chrono::milliseconds(WATCHDOGTIME);
|
||||
while (s_StopWatchdog == false) {
|
||||
|
||||
m_Answered = false;
|
||||
m_Listener->sendWatchdog();
|
||||
{
|
||||
unique_lock<mutex> o_UniqueLock(m_MutexLock);
|
||||
boolDone = m_ConditionVariable.wait_for(o_UniqueLock, waitTime, []{return s_StopWatchdog;});
|
||||
if (s_StopWatchdog == true) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (boolDone) {
|
||||
return;
|
||||
}
|
||||
if (m_Answered == false) {
|
||||
stopWatchdog();
|
||||
m_Listener->eventWatchdogLost();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Windows implementation of a SPITSocket.
|
||||
*
|
||||
* File: WindowsSocket.cpp
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 11. April 2019, 08:36
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "_SPITMACROS.h"
|
||||
#if defined(OS_WINDOWS)
|
||||
#include "WindowsSocket.h"
|
||||
|
||||
|
||||
//----- -----
|
||||
WindowsSocket::WindowsSocket() : SPITSocket(){
|
||||
SPITSocket::FAMILY_IP4 = AF_INET;
|
||||
SPITSocket::FAMILY_IP6 = AF_INET6;
|
||||
m_UDPSocketIP4 = INVALID_SOCKET;
|
||||
m_UDPSocketIP6 = INVALID_SOCKET;
|
||||
createSocket_UDP();
|
||||
}
|
||||
|
||||
|
||||
WindowsSocket::~WindowsSocket() {
|
||||
|
||||
int intResultIP4;
|
||||
int intResultIP6;
|
||||
if (m_UDPSocketIP4 != INVALID_SOCKET) {
|
||||
// intResultIP4 = shutdown(m_UDPSocketIP4, 2);
|
||||
intResultIP4 = closesocket(m_UDPSocketIP4);
|
||||
m_UDPSocketIP4 = INVALID_SOCKET;
|
||||
}
|
||||
if (m_UDPSocketIP6 != INVALID_SOCKET) {
|
||||
// intResultIP6 = shutdown(m_UDPSocketIP6, 2);
|
||||
intResultIP6 = closesocket(m_UDPSocketIP6);
|
||||
m_UDPSocketIP6 = INVALID_SOCKET;
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(100));
|
||||
}
|
||||
/**
|
||||
* Initialize WSAStartup
|
||||
* @return
|
||||
*/
|
||||
int WindowsSocket::init() {
|
||||
WSADATA wsa;
|
||||
int intResult;
|
||||
intResult = WSAStartup(MAKEWORD(2,2),&wsa);
|
||||
return intResult;
|
||||
}
|
||||
/**
|
||||
* Clean WSACleanup
|
||||
* @return
|
||||
*/
|
||||
int WindowsSocket::cleanUp() {
|
||||
int intResult;
|
||||
intResult = WSACleanup();
|
||||
return intResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates two new sockets.<br>
|
||||
* One socket for IP4 and one for IP6.<br>
|
||||
* If there exist some, they will be closed.<br>
|
||||
* @return
|
||||
*/
|
||||
bool WindowsSocket::createSocket_UDP() {
|
||||
bool boolSuccess = true;
|
||||
int intResult = -1;
|
||||
int intResultNonBlocking = 0;
|
||||
BOOL o_OptionValue = TRUE;
|
||||
|
||||
//ip4
|
||||
if (m_UDPSocketIP4 != INVALID_SOCKET) {
|
||||
closesocket(m_UDPSocketIP4);
|
||||
m_UDPSocketIP4 = INVALID_SOCKET;
|
||||
}
|
||||
if (m_UDPSocketIP6 != INVALID_SOCKET) {
|
||||
closesocket(m_UDPSocketIP6);
|
||||
m_UDPSocketIP6 = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
|
||||
m_UDPSocketIP4 = socket(AF_INET,SOCK_DGRAM, 0);
|
||||
if (m_UDPSocketIP4 == INVALID_SOCKET) {
|
||||
boolSuccess = false;
|
||||
}
|
||||
else {
|
||||
intResult = setsockopt(m_UDPSocketIP4, SOL_SOCKET, SO_REUSEADDR, (char*)&o_OptionValue, sizeof(o_OptionValue));
|
||||
|
||||
}
|
||||
|
||||
m_UDPSocketIP6 = socket(AF_INET6,SOCK_DGRAM,0);
|
||||
if (m_UDPSocketIP6 == INVALID_SOCKET) {
|
||||
boolSuccess = false;
|
||||
closesocket(m_UDPSocketIP4);
|
||||
m_UDPSocketIP4 = INVALID_SOCKET;
|
||||
}
|
||||
else {
|
||||
intResult = setsockopt(m_UDPSocketIP6, SOL_SOCKET, SO_REUSEADDR, (char*)&o_OptionValue, sizeof(o_OptionValue));
|
||||
}
|
||||
if (intResult < 0) {
|
||||
boolSuccess = false;
|
||||
}
|
||||
else {
|
||||
//set the m_UDPSocketIP4 and m_UDPSocketIP6 in NON BLOCKING mode because
|
||||
//if the UDPSockets are in blocking mode the receiveMessage does not return in every constellation
|
||||
u_long blockingMode = 1; //1 = non blocking, 0 = blocking
|
||||
intResultNonBlocking = ioctlsocket(m_UDPSocketIP4, FIONBIO, &blockingMode);
|
||||
intResultNonBlocking = ioctlsocket(m_UDPSocketIP6, FIONBIO, &blockingMode);
|
||||
if (intResultNonBlocking != 0) {
|
||||
boolSuccess = false;
|
||||
}
|
||||
}
|
||||
return boolSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the socket to the client's ip address and port.<br>
|
||||
* The socket option SO_REUSEADDR is set to true.<br>
|
||||
* @param p_ClientIP ip address of the client
|
||||
* @param p_ClientPort port of the client.<br>
|
||||
* if p_Port == "0" any free port will be used<br>
|
||||
* @return -1 id bind fails, o if bind is ok
|
||||
*
|
||||
*/
|
||||
int WindowsSocket::bindSocket(string p_ClientIP, string p_ClientPort)
|
||||
{
|
||||
ADDRINFO *clientAI;
|
||||
SOCKADDR_IN o_IP4SocketAddress;
|
||||
SOCKADDR_IN6 o_IP6SocketAddress;
|
||||
int socklen;
|
||||
string stringClientPort;
|
||||
if (p_ClientPort.length() <= 0) stringClientPort = "0";
|
||||
else stringClientPort = p_ClientPort;
|
||||
//int intResult = SOCKET_ERROR;
|
||||
int intResult = 0;
|
||||
if (getaddrinfo(p_ClientIP.data(), stringClientPort.data(), NULL, &clientAI) != 0) {
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
BOOL o_OptionValue = TRUE;
|
||||
switch(clientAI->ai_family) {
|
||||
case AF_INET:
|
||||
if (m_UDPSocketIP4 == INVALID_SOCKET) {
|
||||
break;
|
||||
}
|
||||
intResult = bind(m_UDPSocketIP4, (const sockaddr*)clientAI->ai_addr, (int)clientAI->ai_addrlen);
|
||||
if (intResult < 0) {
|
||||
break;
|
||||
}
|
||||
setBoundClientFamily(AF_INET);
|
||||
if (intResult == 0) {
|
||||
socklen = sizeof (o_IP4SocketAddress);
|
||||
if (getsockname(m_UDPSocketIP4, (SOCKADDR*)&o_IP4SocketAddress, &socklen) != -1) {
|
||||
setBoundClientPort(to_string((int)o_IP4SocketAddress.sin_port));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (m_UDPSocketIP6 == INVALID_SOCKET) {
|
||||
break;
|
||||
}
|
||||
if (intResult < 0) {
|
||||
break;
|
||||
}
|
||||
intResult = bind(m_UDPSocketIP6, (const sockaddr*)clientAI->ai_addr, (int)clientAI->ai_addrlen);
|
||||
if (intResult < 0) {
|
||||
break;
|
||||
}
|
||||
setBoundClientFamily(AF_INET6);
|
||||
|
||||
if (intResult == 0) {
|
||||
socklen = sizeof (o_IP6SocketAddress);
|
||||
if (getsockname(m_UDPSocketIP6, (SOCKADDR*)&o_IP6SocketAddress, &socklen) != -1) {
|
||||
setBoundClientPort(to_string((int)o_IP6SocketAddress.sin6_port));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
setBoundClientFamily(0);
|
||||
intResult = SOCKET_ERROR;
|
||||
break;
|
||||
}
|
||||
freeaddrinfo(clientAI);
|
||||
|
||||
if (intResult == SOCKET_ERROR) {
|
||||
setIsBound(false);
|
||||
}
|
||||
else {
|
||||
setIsBound(true);
|
||||
}
|
||||
return intResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sockopt SO_BROADCAST to 0 or 1
|
||||
* @param p_Broadcast true SO_BROADCAST is set<br>
|
||||
* false = SO_BROADCAST is not set
|
||||
* @return 0 = ok, -1 = error
|
||||
*/
|
||||
int WindowsSocket::setBroadcast(bool p_Broadcast) {
|
||||
int intResult;
|
||||
//IP4
|
||||
BOOL o_BroadcastValue = FALSE;
|
||||
if (p_Broadcast) {
|
||||
o_BroadcastValue = TRUE;
|
||||
}
|
||||
else {
|
||||
o_BroadcastValue = FALSE;
|
||||
}
|
||||
intResult = setsockopt(m_UDPSocketIP4, SOL_SOCKET, SO_BROADCAST, (char*)&o_BroadcastValue, sizeof(BOOL));
|
||||
|
||||
//IP6
|
||||
DWORD loop = 1;
|
||||
if (p_Broadcast) {
|
||||
loop = 1;
|
||||
}
|
||||
else {
|
||||
loop = 0;
|
||||
}
|
||||
intResult = setsockopt(m_UDPSocketIP6, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char*)&loop, sizeof (loop));
|
||||
return intResult;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param p_InetFamily AF_INET or AF_INET6
|
||||
* @param p_ServerIP the ip address of the server
|
||||
* @param p_ServerPort the port of the server
|
||||
* @param p_MessageBytes buffer containing the message
|
||||
* @param p_MessageLength the length of the message
|
||||
* @return -1 send fails<br>
|
||||
* 0 send is done
|
||||
*/
|
||||
int WindowsSocket::sendMessageTo(int p_InetFamily, string p_ServerIP, string p_ServerPort, const char* p_MessageBytes, int p_MessageLength) {
|
||||
if (m_UDPSocketIP4 == INVALID_SOCKET && m_UDPSocketIP6 == INVALID_SOCKET) return -1;
|
||||
ADDRINFO *ptrAddressInfo;
|
||||
|
||||
int intResult = SOCKET_ERROR;
|
||||
// prepare AddressInfo
|
||||
if (getaddrinfo(p_ServerIP.data(), p_ServerPort.data(), NULL, &ptrAddressInfo) != 0) {
|
||||
return -1;
|
||||
}
|
||||
switch(ptrAddressInfo->ai_family) {
|
||||
case AF_INET:
|
||||
if (m_UDPSocketIP4 != INVALID_SOCKET) {
|
||||
intResult = sendto(m_UDPSocketIP4, p_MessageBytes, p_MessageLength, 0, ptrAddressInfo->ai_addr, ptrAddressInfo->ai_addrlen);
|
||||
freeaddrinfo(ptrAddressInfo);
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (m_UDPSocketIP6 != INVALID_SOCKET) {
|
||||
intResult = sendto(m_UDPSocketIP6, p_MessageBytes, p_MessageLength, 0, ptrAddressInfo->ai_addr, ptrAddressInfo->ai_addrlen);
|
||||
freeaddrinfo(ptrAddressInfo);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
intResult = -1;
|
||||
}
|
||||
if (intResult == SOCKET_ERROR) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Starts receiving a message
|
||||
* @param p_InetFamily AF_INET or AF_INET6
|
||||
* @param p_Buffer a char* buffer large enough to hold the expected data
|
||||
* @param p_BufferLength the length of the buffer
|
||||
* @param p_ServerIP = NULL, the ip address is not determined<br>
|
||||
* != NULL after receiving a message p_ServerID contains the ip address of the sender/server
|
||||
* @return
|
||||
*/
|
||||
int WindowsSocket::receiveMessage(int p_InetFamily, char* p_Buffer, int p_BufferLength, string* p_ServerIP) {
|
||||
int intResult = SOCKET_ERROR;
|
||||
// ADDRINFO *AI;
|
||||
SOCKADDR_IN o_IP4SocketAddress;
|
||||
SOCKADDR_IN6 o_IP6SocketAddress;
|
||||
int socklen;
|
||||
switch(p_InetFamily) {
|
||||
case AF_INET:
|
||||
if (m_UDPSocketIP4 == INVALID_SOCKET) {
|
||||
break;
|
||||
}
|
||||
socklen = sizeof (o_IP4SocketAddress);
|
||||
intResult = recvfrom(m_UDPSocketIP4, p_Buffer, p_BufferLength, 0, (SOCKADDR *)&o_IP4SocketAddress, &socklen);
|
||||
if (intResult >= 0) {
|
||||
if (p_ServerIP != NULL) {
|
||||
*p_ServerIP = inet_ntoa(o_IP4SocketAddress.sin_addr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (m_UDPSocketIP6 == INVALID_SOCKET) {
|
||||
break;
|
||||
}
|
||||
socklen = sizeof (o_IP6SocketAddress);
|
||||
intResult = recvfrom(m_UDPSocketIP6, p_Buffer, p_BufferLength, 0, (SOCKADDR *)&o_IP6SocketAddress, &socklen);
|
||||
if (intResult >= 0) {
|
||||
if (p_ServerIP != NULL) {
|
||||
char clienthost[NI_MAXHOST]; //The clienthost will hold the IP address.
|
||||
char clientservice[NI_MAXSERV];
|
||||
GetNameInfo((SOCKADDR *)&o_IP6SocketAddress, socklen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST|NI_NUMERICSERV);
|
||||
*p_ServerIP = clienthost;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return intResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the broadcast address from a ip4 address.<br>
|
||||
* @param p_IPAddress the ip4 address
|
||||
* @return returns the broadcast address
|
||||
*/
|
||||
string WindowsSocket::getBroadcastIP4(SPITSocket::IPAddress* p_IPAddress) {
|
||||
struct in_addr broadcast;
|
||||
unsigned long ulIPAddress;
|
||||
unsigned long ulSubnetMask;
|
||||
|
||||
ulIPAddress = inet_addr(p_IPAddress->getIPAddress().data());
|
||||
ulSubnetMask = inet_addr(p_IPAddress->getSubnetMask().data());
|
||||
broadcast.s_addr = ulIPAddress | ~ulSubnetMask;
|
||||
|
||||
return inet_ntoa(broadcast);
|
||||
}
|
||||
|
||||
|
||||
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
|
||||
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
|
||||
/// Note: could also use malloc() and free()
|
||||
|
||||
/**
|
||||
* Detect all ip-addresses
|
||||
*/
|
||||
void WindowsSocket::getAdaptersInfo() {
|
||||
|
||||
// It is possible for an adapter to have multiple
|
||||
// IPv4 addresses, gateways, and secondary WINS servers
|
||||
// assigned to the adapter.
|
||||
//
|
||||
|
||||
|
||||
PIP_ADAPTER_INFO pAdapterInfo;
|
||||
PIP_ADAPTER_INFO pAdapter = NULL;
|
||||
DWORD dwRetVal = 0;
|
||||
|
||||
resetFoundIPAddresses();
|
||||
|
||||
ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO);
|
||||
pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(sizeof (IP_ADAPTER_INFO));
|
||||
if (pAdapterInfo == NULL) {
|
||||
printf("WindowsSocket::getAdaptersInfo Error allocating memory needed to call GetAdaptersinfo\n");
|
||||
return ;
|
||||
}
|
||||
// Make an initial call to GetAdaptersInfo to get
|
||||
// the necessary size into the ulOutBufLen variable
|
||||
if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
|
||||
FREE(pAdapterInfo);
|
||||
pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(ulOutBufLen);
|
||||
if (pAdapterInfo == NULL) {
|
||||
printf("WindowsSocket::getAdaptersInfo Error allocating memory needed to call GetAdaptersinfo\n");
|
||||
return ;
|
||||
}
|
||||
}
|
||||
if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {
|
||||
pAdapter = pAdapterInfo;
|
||||
while (pAdapter) {
|
||||
if (strncmp(pAdapter->IpAddressList.IpAddress.String, "0.0.0.", 6) == 0) {
|
||||
pAdapter = pAdapter->Next;
|
||||
continue;
|
||||
}
|
||||
addIPAddress(pAdapter->IpAddressList.IpAddress.String, pAdapter->IpAddressList.IpMask.String);
|
||||
|
||||
pAdapter = pAdapter->Next;
|
||||
}
|
||||
} else {
|
||||
printf("WindowsSocket::getAdaptersInfo failed with error: %ud\n", dwRetVal);
|
||||
}
|
||||
if (pAdapterInfo)
|
||||
FREE(pAdapterInfo);
|
||||
|
||||
//loopback is not listet-> add manually
|
||||
addIPAddress("127.0.0.1", "255.0.0.0");
|
||||
|
||||
removeNotFoundIPAddresses();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
#include "_SPITMACROS.h"
|
||||
|
||||
string createGUID() {
|
||||
#if defined(OS_WINDOWS)
|
||||
GUID o_GUID;
|
||||
CoCreateGuid(&o_GUID);
|
||||
char guid_string[37]; // 32 hex chars + 4 hyphens + null terminator
|
||||
snprintf(
|
||||
guid_string, sizeof(guid_string) / sizeof(guid_string[0]),
|
||||
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
o_GUID.Data1, o_GUID.Data2, o_GUID.Data3,
|
||||
o_GUID.Data4[0], o_GUID.Data4[1], o_GUID.Data4[2],
|
||||
o_GUID.Data4[3], o_GUID.Data4[4], o_GUID.Data4[5],
|
||||
o_GUID.Data4[6], o_GUID.Data4[7]);
|
||||
string stringGUID = guid_string;
|
||||
return stringGUID;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(OS_MAC) || defined(OS_LINUX)
|
||||
uuid_t id;
|
||||
uuid_generate(id);
|
||||
char *guid_string = new char[100];
|
||||
uuid_unparse(id, guid_string);
|
||||
string stringGUID = guid_string;
|
||||
return stringGUID;
|
||||
#endif
|
||||
}
|
||||
/** The name of the client's host computer*/
|
||||
string getClientHostName() {
|
||||
string stringHostName;
|
||||
char hostname[255];
|
||||
if (gethostname(hostname, 255) != 0) {
|
||||
stringHostName = "";
|
||||
}
|
||||
else {
|
||||
stringHostName = hostname;
|
||||
}
|
||||
return stringHostName;;
|
||||
}
|
||||
Reference in New Issue
Block a user