This commit is contained in:
2025-11-15 00:48:13 +01:00
parent 0ecd846183
commit 331258692b
4 changed files with 1377 additions and 1452 deletions
+7 -38
View File
@@ -3,6 +3,7 @@
#include "sad_DetectedServer.hpp" #include "sad_DetectedServer.hpp"
#include "spit_object.hpp" #include "spit_object.hpp"
#include "spit_player.hpp" #include "spit_player.hpp"
#include "spit_processor.hpp"
#include "spit_socket.hpp" #include "spit_socket.hpp"
#include "spit_type.hpp" #include "spit_type.hpp"
#include "spit_message.hpp" #include "spit_message.hpp"
@@ -21,42 +22,11 @@ class SClient : ISadClient {
/** Maximal length of a SPITMessage*/ /** Maximal length of a SPITMessage*/
static const int MAXSPITMESSAGEBYTECOUNT = 512; static const int MAXSPITMESSAGEBYTECOUNT = 512;
enum class ProjUpdate { using Callbacks = SProcessor::Callbacks;
ServerLoaded, using ProjUpdate = SProcessor::ProjUpdate;
StartTransfer, using ServerEvent = SProcessor::ServerEvent;
EndTransfer, using ObjectEvent = SProcessor::ObjectEvent;
ServerClosed, using Connection = SProcessor::Connection;
};
enum class ServerEvent {
Detect,
Lost,
Changed,
};
enum class ObjectEvent {
Created,
Changed,
Deleted
};
enum class Connection {
None = 0, // No Connection established.<br>Either no connect tried or disconnected
NoneServer = 1, // Server has disconnected
Lost = 2, // The connection is lost<br>Either because of a network crash or because the server no longer responds.
Ok = 3, // Connection to the serv er is established.
TryConnection = 4, // A connection to the server is tried.
};
struct Callbacks {
function<void(ServerEvent event, const SadDetectedServer &detectedServer)> onServerEvent;
function<void(string serverID, string serverComputerName, string serverName, int serverStepTime, Connection connectionStatus, Connection oldConnectionStatus)> onConnectionStatus;
function<void(ProjUpdate state, string projectId)> onProjectUpdate;
function<void(ObjectEvent event, bool isRemote, const SType &spitType)> onSpitType;
function<void(ObjectEvent event, bool isRemote, const SType &spitType, const SObject &spitObject)> onSpitObject;
function<void(string playerID, string playerName, char playerType, bool playerIsRunning, uint64_t timeFrames)> onPlay;
function<void(string playerID, string spitTypeID, bool playerIsRunning, bool started, bool ended, double value)> onPlaySpitType;
function<void(const SType &spitType, const SObject &spitObject, uint64_t p_FrameInsideObject, int value)> onPlayRemoteObjectStatus;
function<bool(bool knownType, bool createdByClient)> onCheckSpitTypeVeto;
function<bool(bool knownType)> onCheckSpitObjectVeto;
};
//------ PlayerType ------ //------ PlayerType ------
public: public:
@@ -96,6 +66,7 @@ class SClient : ISadClient {
string mName; string mName;
string mProjName; string mProjName;
string mComputerName; string mComputerName;
SProcessor mProcessor;
string mClientProjectName; string mClientProjectName;
@@ -327,8 +298,6 @@ class SClient : ISadClient {
SpitRepo<SObject> mSpitObjects; SpitRepo<SObject> mSpitObjects;
SpitRepo<SObject> mRemoteSpitObjects; SpitRepo<SObject> mRemoteSpitObjects;
SpitRepo<SType> mSpitTypes;
SpitRepo<SType> mRemoteSpitTypes;
}; };
} }
+237 -232
View File
@@ -1,14 +1,14 @@
#pragma once #pragma once
#include "sad_DetectedServer.hpp" #include "sad_DetectedServer.hpp"
#include "spit_message.hpp"
#include "spit_object.hpp" #include "spit_object.hpp"
#include "spit_player.hpp" #include "spit_player.hpp"
#include "spit_type.hpp"
#include "spit_message.hpp"
#include "spit_repo.hpp" #include "spit_repo.hpp"
#include "spit_type.hpp"
#include <functional>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <functional>
using namespace std; using namespace std;
@@ -16,8 +16,8 @@ namespace spit {
class SProcessor { class SProcessor {
public: public:
/** Maximal length of a SPITMessage*/ // /** Maximal length of a SPITMessage*/
static const int MAXSPITMESSAGEBYTECOUNT = 512; // static const int MAXSPITMESSAGEBYTECOUNT = 512;
enum class ProjUpdate { enum class ProjUpdate {
ServerLoaded, ServerLoaded,
@@ -56,266 +56,271 @@ class SProcessor {
function<bool(bool knownType)> onCheckSpitObjectVeto; function<bool(bool knownType)> onCheckSpitObjectVeto;
}; };
//------ PlayerType ------ struct InternalCallbacks {
public: function<int(SType &sType)> sendSpitTypeInternal;
/** 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 constexpr char PLAYERTYPE_MAIN = 0x02;
/** continous player. This player plays SPIT objects sometime during the project.*/
static constexpr char PLAYERTYPE_CONTINOUS = 0x01;
/** diescrete player. This player is used to transmit single discrete values.*/
static constexpr char PLAYERTYPE_DISCRETE = 0x00;
//------ Value Flag ------ // //------ PlayerType ------
//------ used by sendRemoteObject // public:
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.*/
/**Set the given value directly*/ // static constexpr char PLAYERTYPE_MAIN = 0x02;
static constexpr char VALUEFLAG_DIRECT = 0x00; // /** continous player. This player plays SPIT objects sometime during the project.*/
/**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 constexpr char PLAYERTYPE_CONTINOUS = 0x01;
static constexpr char VALUEFLAG_INCREASE = 0x01; // /** diescrete player. This player is used to transmit single discrete values.*/
/**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 constexpr char PLAYERTYPE_DISCRETE = 0x00;
static constexpr char VALUEFLAG_DECREASE = 0x02;
static constexpr int MAX_OVERTAKING_SPIT_MESSAGES = 10; // //------ Value Flag ------
// //------ used by sendRemoteObject
// public:
// /**Set the given value directly*/
// static constexpr 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 constexpr 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 constexpr char VALUEFLAG_DECREASE = 0x02;
// static constexpr int MAX_OVERTAKING_SPIT_MESSAGES = 10;
//----- SProcessor ----- //----- SProcessor -----
public: public:
SProcessor(string name, string projName, string hostName, string guid, Callbacks calls); SProcessor(string name, string projName, string hostName, string guid,
Callbacks calls, InternalCallbacks intern);
virtual ~SProcessor(); virtual ~SProcessor();
private: private:
Callbacks mCallbacks; Callbacks mCallbacks;
InternalCallbacks mInternCallbacks;
Connection mConnectionStatus{Connection::None}; // Connection mConnectionStatus{Connection::None};
bool mDisconnectedByServer{}; // flag true = when server disconnects // bool mDisconnectedByServer{}; // flag true = when server disconnects
string mGuid; string mGuid;
string mName; string mName;
string mProjName; string mProjName;
string mComputerName; string mComputerName;
string mClientProjectName; // string mClientProjectName;
uint8_t mMessageNumberSend{1}; // uint8_t mMessageNumberSend{1};
int mMessageNumberReceived{-1}; // set to -1 because the first received message will set the number (1..255) // int mMessageNumberReceived{-1}; // set to -1 because the first received message will set the number (1..255)
vector<unique_ptr<Message>> mOvertakingMessages; // vector<unique_ptr<Message>> mOvertakingMessages;
// Server's info filled by parseConnectAnswer // // Server's info filled by parseConnectAnswer
string mServerID{}; // string mServerID{};
string mServerName{}; // string mServerName{};
string mServerComputerName{}; // string mServerComputerName{};
int mServerStepTime{-1}; // int mServerStepTime{-1};
//--- Server Project --- // //--- Server Project ---
string mServerProjectID; // string mServerProjectID;
string mServerProjectName; // string mServerProjectName;
int mServerFramesPerSecond; // int mServerFramesPerSecond;
public: // public:
/** The ID of the client.<br>Every client instance should set an unique id*/ // /** The ID of the client.<br>Every client instance should set an unique id*/
string getID() { return mGuid; } // string getID() { return mGuid; }
/** The name of the client, should be set by the user app*/ // /** The name of the client, should be set by the user app*/
string getName() { return mName; } // string getName() { return mName; }
//----- Computer Params ----- // //----- Computer Params -----
/** The name of the client's host computer*/ // /** The name of the client's host computer*/
string getComputerName() { return mComputerName; } // string getComputerName() { return mComputerName; }
void setClientProjectName(string clientProjectName) { mClientProjectName = clientProjectName; } // void setClientProjectName(string clientProjectName) { mClientProjectName = clientProjectName; }
string getClientProjectName() { return mClientProjectName; } // string getClientProjectName() { return mClientProjectName; }
// connected Server Infos // // connected Server Infos
/** The ID of the connected SPITServer*/ // /** The ID of the connected SPITServer*/
string getServerID() { return mServerID; } // string getServerID() { return mServerID; }
/** The host computername of the connected SPITServer*/ // /** The host computername of the connected SPITServer*/
string getServerComputerName() { return mServerComputerName; } // string getServerComputerName() { return mServerComputerName; }
/** The name of the connected SPITServer*/ // /** The name of the connected SPITServer*/
string getServerName() { return mServerName; } // string getServerName() { return mServerName; }
/** Expected Refreah Rate of the connectd SPITServer.<br> // /** Expected Refreah Rate of the connectd SPITServer.<br>
* When the server plays objects, it will do so at discrete time steps.<br> // * When the server plays objects, it will do so at discrete time steps.<br>
* Play events will take place in these time steps.. // * Play events will take place in these time steps..
*/ // */
int getServerStepTime() { return mServerStepTime; } // int getServerStepTime() { return mServerStepTime; }
/** Should be called when the client wants to close his project*/ // /** Should be called when the client wants to close his project*/
void clientProjectClose(); // void clientProjectClose();
/** // /**
* Should be called whenever the client has a project loaded // * Should be called whenever the client has a project loaded
*/ // */
void clientProjectLoaded(); // void clientProjectLoaded();
void setActionSPITType(string spitypeID, bool actionAssigned); // void setActionSPITType(string spitypeID, bool actionAssigned);
void setActionSPITObject(string objectID, bool actionAssigned); // void setActionSPITObject(string objectID, bool actionAssigned);
//--------------- SPITMessage --------------- // //--------------- SPITMessage ---------------
// private:
// // Reconnect to the server when connection is lost see eventConnectionStatus and eventServerDetected
// bool _doReconnect{}; // true = on eventServerDetected connect to the server identified by mServerID
// public:
// std::vector<char> createMessage(Message::OPPart & spitMessageOPPart);
// void checkParseMessageData(vector<char> data);
// //--------------- 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(SadDetectedServer &server);
// /** Called every time a prior detected SPITServer is is no longer found.*/
// void eventServerLost(SadDetectedServer &server);
// void eventServerChanged(SadDetectedServer &server);
// //--------------- 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 serverIP, string serverPort, string clientIP, string clientPort, string loginName = "", string loginPassword = "");
// /**
// * Terminates the connection to the SPITServer.
// */
// void disconnect();
// private:
// void disconnectInternal(Connection cause);
// void resetMessageNumberReceived();
// void parseMessage(Message& message);
// void addOvertakingMessage(unique_ptr<Message> message);
// void parseConnectAnswer(Message::ConnectAnswer &message);
// void parseDisconnect(Message::Disconnect &message);
// void parseWatchdog(Message::Watchdog &message);
// void parseWatchdogAnswer(Message::WatchdogAnswer &message);
// public:
// /** Used internally*/
// void sendWatchdog();
// /** Used internally. When the connection to the SPITServer is lost an eventConnectionStatus will occur*/
// void eventWatchdogLost();
// //--------------- SPIT Project ---------------
// private:
// void parseReportProject(Message::ReportProject &message);
// void parseCloseProject(Message::CloseProject &message);
// 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();
// private:
// void parseRequestProjectTransfer(Message::RequestProjectTransfer &message);
// void parseStartProjectTransfer(Message::StartProjectTransfer &message);
// void parseEndProjectTransfer(Message::EndProjectTransfer &message);
// public:
// // static void sendProject(SClient *p_PtrSProcessor);
// // --------------- 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.
// */
// SType *createTypeFixed(string iD, string groupName, string name, uint64_t defaultDelay, uint64_t 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.
// */
// SType *createType(string iD, string groupName, string name, uint64_t defaultDelay, uint64_t defaultDuration, bool fixed, bool projectIndepended);
private: private:
// Reconnect to the server when connection is lost see eventConnectionStatus and eventServerDetected public: // @todo delete
bool _doReconnect{}; // true = on eventServerDetected connect to the server identified by mServerID
public:
std::vector<char> createMessage(Message::OPPart & spitMessageOPPart);
void checkParseMessageData(vector<char> data);
//--------------- 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(SadDetectedServer &server);
/** Called every time a prior detected SPITServer is is no longer found.*/
void eventServerLost(SadDetectedServer &server);
void eventServerChanged(SadDetectedServer &server);
//--------------- 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 serverIP, string serverPort, string clientIP, string clientPort, string loginName = "", string loginPassword = "");
/**
* Terminates the connection to the SPITServer.
*/
void disconnect();
private:
void disconnectInternal(Connection cause);
void resetMessageNumberReceived();
void parseMessage(Message& message);
void addOvertakingMessage(unique_ptr<Message> message);
void parseConnectAnswer(Message::ConnectAnswer &message);
void parseDisconnect(Message::Disconnect &message);
void parseWatchdog(Message::Watchdog &message);
void parseWatchdogAnswer(Message::WatchdogAnswer &message);
public:
/** Used internally*/
void sendWatchdog();
/** Used internally. When the connection to the SPITServer is lost an eventConnectionStatus will occur*/
void eventWatchdogLost();
//--------------- SPIT Project ---------------
private:
void parseReportProject(Message::ReportProject &message);
void parseCloseProject(Message::CloseProject &message);
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();
private:
void parseRequestProjectTransfer(Message::RequestProjectTransfer &message);
void parseStartProjectTransfer(Message::StartProjectTransfer &message);
void parseEndProjectTransfer(Message::EndProjectTransfer &message);
public:
// static void sendProject(SClient *p_PtrSProcessor);
// --------------- 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.
*/
SType *createTypeFixed(string iD, string groupName, string name, uint64_t defaultDelay, uint64_t 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.
*/
SType *createType(string iD, string groupName, string name, uint64_t defaultDelay, uint64_t defaultDuration, bool fixed, bool projectIndepended);
private:
// receive SPIT-Types
void parseReportType(Message::ReportType &message); void parseReportType(Message::ReportType &message);
void parseRemoveSPITType(Message::RemoveType &message); // void parseRemoveSPITType(Message::RemoveType &message);
int sendSPITTypeInternal(SType &sType); // int sendSPITTypeInternal(SType &sType);
public: // public:
/** // /**
* If a client wants to change a SPITType, he should send it to the server.<br> // * 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> // * 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 spitypeID the id of the SPITType to remove. // * @param spitypeID the id of the SPITType to remove.
* @return 0 = is sended, -1 = is not sended // * @return 0 = is sended, -1 = is not sended
*/ // */
bool changeSPITType(SType *spitType); // bool changeSPITType(SType *spitType);
/** // /**
* If a client wants to remove a SPITType, he should send it to the server.<br> // * 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> // * 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 spitypeID the id of the SPITType to remove. // * @param spitypeID the id of the SPITType to remove.
* @return 0 = is sended, -1 = is not sended // * @return 0 = is sended, -1 = is not sended
*/ // */
int removeSPITType(string spitypeID); // int removeSPITType(string spitypeID);
public: // public:
//--------------- SPIT Objects --------------- // //--------------- SPIT Objects ---------------
private: // private:
void parseReportSPITObject(Message::ReportObject &message); // void parseReportSPITObject(Message::ReportObject &message);
void parseRemoveSPITObject(Message::RemoveObject &message); // void parseRemoveSPITObject(Message::RemoveObject &message);
int sendSPITObjectInternal(SObject *ptrObject); // int sendSPITObjectInternal(SObject *ptrObject);
public: // public:
/** // /**
* When the client changes a SPITObject (normally the client should not do this), then it should send the changes to the SPITServer.<br> // * 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> // * The SPITServer may discard the changes and an eventSPITObject occurs.<br>
* @param spitObject the pointer to the changed SPITObject. // * @param spitObject the pointer to the changed SPITObject.
* @return 0 = sended, -1 = not sended // * @return 0 = sended, -1 = not sended
*/ // */
bool changeSPITObject(SObject *spitObject); // bool changeSPITObject(SObject *spitObject);
/** // /**
* When the client removes a SPITObject (normally the client should not do this), then he should send it to the SPITServer.<br> // * 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> // * The SPITServer may discard the deletion and an eventSPITObject occurs.<br>
* @param objectID the id of the SPITObject to remove. // * @param objectID the id of the SPITObject to remove.
* @return 0 = sended, -1 = not sended // * @return 0 = sended, -1 = not sended
*/ // */
int removeSPITObject(string objectID); // int removeSPITObject(string objectID);
public: // public:
//--------------- Play SPIT Objects --------------- // //--------------- Play SPIT Objects ---------------
private: // private:
void parsePlaySPITStart(Message::PlayStart &message); // void parsePlaySPITStart(Message::PlayStart &message);
void parsePlaySPITObject(Message::PlayObject &message); // void parsePlaySPITObject(Message::PlayObject &message);
void parsePlaySPITEnd(Message::PlayEnd &message); // void parsePlaySPITEnd(Message::PlayEnd &message);
void parseReportPlayStatus(Message::ReportPlayStatus &message); // void parseReportPlayStatus(Message::ReportPlayStatus &message);
public: // public:
//--------- Remote ---------- // //--------- Remote ----------
void sendRemoteObject(string objectID, int valuePpm = 0, char valueFlag = 0x00); // void sendRemoteObject(string objectID, int valuePpm = 0, char valueFlag = 0x00);
private: // private:
bool mAbortSearch{}; // bool mAbortSearch{};
bool sAnswered{}; // bool sAnswered{};
void answerWatchdog() { // void answerWatchdog() {
sAnswered = true; // sAnswered = true;
} // }
SpitRepo<SObject> mSpitObjects; // SpitRepo<SObject> mSpitObjects;
SpitRepo<SObject> mRemoteSpitObjects; // SpitRepo<SObject> mRemoteSpitObjects;
public: // @todo remove
SpitRepo<SType> mSpitTypes; SpitRepo<SType> mSpitTypes;
SpitRepo<SType> mRemoteSpitTypes; SpitRepo<SType> mRemoteSpitTypes;
}; };
} } // namespace spit
+27 -73
View File
@@ -18,6 +18,11 @@ SClient::SClient(string name, string projName, ISocket &socket, Callbacks calls)
mCallbacks(calls), mCallbacks(calls),
mName(name), mName(name),
mProjName(projName), mProjName(projName),
mProcessor(name, projName, getClientHostName(), createGUID(), calls,
{
.sendSpitTypeInternal = [&](SType &sType) { return sendSPITTypeInternal(sType);}
}
),
mSocket(socket) { mSocket(socket) {
mID = createGUID(); mID = createGUID();
mComputerName = getClientHostName(); mComputerName = getClientHostName();
@@ -40,7 +45,7 @@ void SClient::clientProjectClose() {
void SClient::clientProjectLoaded() { void SClient::clientProjectLoaded() {
// set confirmed = false for all SPITTypes and SPITObjects // set confirmed = false for all SPITTypes and SPITObjects
SType::setConfirmedFalse(mSpitTypes); SType::setConfirmedFalse(mProcessor.mSpitTypes);
SObject::setConfirmedFalse(mSpitObjects); SObject::setConfirmedFalse(mSpitObjects);
if (mConnectionStatus == Connection::Ok) { if (mConnectionStatus == Connection::Ok) {
@@ -68,7 +73,7 @@ void SClient::clientProjectLoaded() {
* @param actionAssigned * @param actionAssigned
*/ */
void SClient::setActionSPITType(string typeId, bool actionAssigned) { void SClient::setActionSPITType(string typeId, bool actionAssigned) {
SType *spitType = mSpitTypes.getEntry(typeId); SType *spitType = mProcessor.mSpitTypes.getEntry(typeId);
if (spitType == nullptr) if (spitType == nullptr)
return; return;
if (spitType->ActionAssigned.set(actionAssigned)) { if (spitType->ActionAssigned.set(actionAssigned)) {
@@ -383,7 +388,7 @@ void SClient::parseMessage(unique_ptr<Message> message) {
break; break;
//----- SPIT Types ------ //----- SPIT Types ------
case Message::ReportType::OPFLAG: case Message::ReportType::OPFLAG:
parseReportType(message->getAs<Message::ReportType>()); mProcessor.parseReportType(message->getAs<Message::ReportType>());
break; break;
case Message::RemoveType::OPFLAG: case Message::RemoveType::OPFLAG:
parseRemoveSPITType(message->getAs<Message::RemoveType>()); parseRemoveSPITType(message->getAs<Message::RemoveType>());
@@ -605,7 +610,7 @@ void SClient::parseReportProject(Message::ReportProject &message) {
mCallbacks.onProjectUpdate(ProjUpdate::ServerLoaded, mServerProjectID); mCallbacks.onProjectUpdate(ProjUpdate::ServerLoaded, mServerProjectID);
// Set all SPITTypes and SPITObjects confirmed = false // Set all SPITTypes and SPITObjects confirmed = false
SType::setConfirmedFalse(mSpitTypes); SType::setConfirmedFalse(mProcessor.mSpitTypes);
SObject::setConfirmedFalse(mSpitObjects); SObject::setConfirmedFalse(mSpitObjects);
// Send RequestProjectTransfer // Send RequestProjectTransfer
@@ -642,7 +647,7 @@ void SClient::parseRequestProjectTransfer(Message::RequestProjectTransfer &messa
} }
// send all listes SPITTypes // send all listes SPITTypes
for (const auto& [key, value] : mSpitTypes.getRepo()) { for (const auto& [key, value] : mProcessor.mSpitTypes.getRepo()) {
sendSPITTypeInternal(*value); sendSPITTypeInternal(*value);
fos::Task::delayMs(10); fos::Task::delayMs(10);
} }
@@ -797,67 +802,16 @@ void SClient::parseEndProjectTransfer(Message::EndProjectTransfer &message) {
} }
} }
//----- SPIT Types ------
void SClient::parseReportType(Message::ReportType &message) {
ESP_LOGD(TAG, "parse ReportType ID %s Name %s",message.getID().c_str(), message.getName().c_str());
SType *ptrSPITType;
bool boolNew = false;
bool boolChanged = false;
{
if (message.getServerRemote() == false) {
ptrSPITType = mSpitTypes.getEntry(message.getID());
if (ptrSPITType == nullptr) {
// The user's app my veto the SPITType
bool createdByClient = false;
if (ptrSPITType) {
createdByClient = ptrSPITType->getCreatedByClient();
}
if (mCallbacks.onCheckSpitTypeVeto(false, createdByClient) == false) {
ESP_LOGW(TAG, "TypeVeto %s / %s", message.getID().c_str(), message.getName().c_str());
return;
}
auto spitType = make_unique<SType>(message.getID());
ptrSPITType = spitType.get();
mSpitTypes.addEntry(move(spitType));
boolNew = true;
}
} else {
ptrSPITType = mRemoteSpitTypes.getEntry(message.getID());
if (ptrSPITType == nullptr) {
auto spitType = make_unique<SType>(message.getID());
ptrSPITType = spitType.get();
mRemoteSpitTypes.addEntry(move(spitType));
boolNew = true;
}
}
if (!ptrSPITType->setMessageOP(message)) {
// SPITType is not changable -> send back to the server
sendSPITTypeInternal(*ptrSPITType);
return;
}
auto eventType = boolNew ? ObjectEvent::Created : ObjectEvent::Changed;
// add or change SPITType
mCallbacks.onSpitType(eventType, ptrSPITType->ServerRemote.get(), *ptrSPITType);
if (ptrSPITType != nullptr) {
if (ptrSPITType->setConfirmed(true) == true || boolChanged == true) {
sendSPITTypeInternal(*ptrSPITType);
}
}
}
}
void SClient::parseRemoveSPITType(Message::RemoveType &message) { void SClient::parseRemoveSPITType(Message::RemoveType &message) {
ESP_LOGD(TAG, "parse RemoveType %s", message.getID().c_str()); ESP_LOGD(TAG, "parse RemoveType %s", message.getID().c_str());
bool boolRemote = false; bool boolRemote = false;
string stringSPITTypeID = message.getID(); string stringSPITTypeID = message.getID();
SType *ptrSPITType = mRemoteSpitTypes.getEntry(stringSPITTypeID); SType *ptrSPITType = mProcessor.mRemoteSpitTypes.getEntry(stringSPITTypeID);
if (!ptrSPITType) { if (!ptrSPITType) {
boolRemote = true; boolRemote = true;
} else { } else {
ptrSPITType = mSpitTypes.getEntry(stringSPITTypeID); ptrSPITType = mProcessor.mSpitTypes.getEntry(stringSPITTypeID);
if (!ptrSPITType) { if (!ptrSPITType) {
boolRemote = false; boolRemote = false;
} else { } else {
@@ -875,9 +829,9 @@ void SClient::parseRemoveSPITType(Message::RemoveType &message) {
mCallbacks.onSpitType(ObjectEvent::Deleted, boolRemote, *ptrSPITType); mCallbacks.onSpitType(ObjectEvent::Deleted, boolRemote, *ptrSPITType);
if (boolRemote == false) { if (boolRemote == false) {
mSpitTypes.removeEntry(*ptrSPITType); mProcessor.mSpitTypes.removeEntry(*ptrSPITType);
} else { } else {
mRemoteSpitTypes.removeEntry(*ptrSPITType); mProcessor.mRemoteSpitTypes.removeEntry(*ptrSPITType);
} }
} }
@@ -901,7 +855,7 @@ int SClient::sendSPITTypeInternal(SType &p_SPITType) {
bool SClient::changeSPITType(SType *p_SPITType) { bool SClient::changeSPITType(SType *p_SPITType) {
if (p_SPITType == nullptr) if (p_SPITType == nullptr)
return false; return false;
SType *ptrSPITType = mSpitTypes.getEntry(p_SPITType->getID()); SType *ptrSPITType = mProcessor.mSpitTypes.getEntry(p_SPITType->getID());
if (ptrSPITType == nullptr) if (ptrSPITType == nullptr)
return false; return false;
@@ -932,13 +886,13 @@ int SClient::removeSPITType(string p_SPITTypeID) {
return -1; return -1;
SType *ptrSPITType; SType *ptrSPITType;
{ {
ptrSPITType = mSpitTypes.getEntry(p_SPITTypeID); ptrSPITType = mProcessor.mSpitTypes.getEntry(p_SPITTypeID);
if (ptrSPITType == nullptr) if (ptrSPITType == nullptr)
return -1; return -1;
Message::RemoveType sMRemoveSPITType; Message::RemoveType sMRemoveSPITType;
ptrSPITType->fillMessageOP(sMRemoveSPITType); ptrSPITType->fillMessageOP(sMRemoveSPITType);
mCallbacks.onSpitType(ObjectEvent::Deleted, false, *ptrSPITType); mCallbacks.onSpitType(ObjectEvent::Deleted, false, *ptrSPITType);
mSpitTypes.removeEntry(*ptrSPITType); mProcessor.mSpitTypes.removeEntry(*ptrSPITType);
return sendSPITMessage(sMRemoveSPITType); return sendSPITMessage(sMRemoveSPITType);
} }
return -1; return -1;
@@ -950,11 +904,11 @@ SType *SClient::createTypeFixed(string iD, string p_GroupName, string p_Name, ui
SType *SClient::createType(string p_ID, string p_GroupName, string p_Name, uint64_t p_DefaultDelay, uint64_t p_DefaultDuration, bool p_FIxed, bool p_ProjectIndepended) { SType *SClient::createType(string p_ID, string p_GroupName, string p_Name, uint64_t p_DefaultDelay, uint64_t p_DefaultDuration, bool p_FIxed, bool p_ProjectIndepended) {
bool boolNew; bool boolNew;
SType *ptrSPITType = mSpitTypes.getEntry(p_ID); SType *ptrSPITType = mProcessor.mSpitTypes.getEntry(p_ID);
if (ptrSPITType == nullptr) { if (ptrSPITType == nullptr) {
auto spitType = make_unique<SType>(p_ID, p_GroupName, p_Name, p_FIxed, p_ProjectIndepended, p_DefaultDelay, p_DefaultDuration); auto spitType = make_unique<SType>(p_ID, p_GroupName, p_Name, p_FIxed, p_ProjectIndepended, p_DefaultDelay, p_DefaultDuration);
ptrSPITType = spitType.get(); ptrSPITType = spitType.get();
mSpitTypes.addEntry(move(spitType)); mProcessor.mSpitTypes.addEntry(move(spitType));
ptrSPITType->setCreatedByClient(true); ptrSPITType->setCreatedByClient(true);
boolNew = true; boolNew = true;
} else { } else {
@@ -986,7 +940,7 @@ void SClient::parseReportSPITObject(Message::ReportObject &message) {
if (message.getServerRemote() == false) { if (message.getServerRemote() == false) {
boolRemote = false; boolRemote = false;
ptrSPITObject = mSpitObjects.getEntry(message.getID()); ptrSPITObject = mSpitObjects.getEntry(message.getID());
ptrSPITType = mSpitTypes.getEntry(message.getSPITTypeID()); ptrSPITType = mProcessor.mSpitTypes.getEntry(message.getSPITTypeID());
if (ptrSPITType == nullptr) { if (ptrSPITType == nullptr) {
// No associated SPITType found // No associated SPITType found
@@ -1020,7 +974,7 @@ void SClient::parseReportSPITObject(Message::ReportObject &message) {
} else { } else {
boolRemote = true; boolRemote = true;
ptrSPITObject = mRemoteSpitObjects.getEntry(message.getID()); ptrSPITObject = mRemoteSpitObjects.getEntry(message.getID());
ptrSPITType = mRemoteSpitTypes.getEntry(message.getSPITTypeID()); ptrSPITType = mProcessor.mRemoteSpitTypes.getEntry(message.getSPITTypeID());
if (ptrSPITType == nullptr) { if (ptrSPITType == nullptr) {
// No associated SPITType found // No associated SPITType found
return; return;
@@ -1058,7 +1012,7 @@ void SClient::parseRemoveSPITObject(Message::RemoveObject &message) {
ESP_LOGD(TAG, "parse RemoveObject %s", message.getID().c_str()); ESP_LOGD(TAG, "parse RemoveObject %s", message.getID().c_str());
SObject *ptrSPITObject = mRemoteSpitObjects.getEntry(message.getID()); SObject *ptrSPITObject = mRemoteSpitObjects.getEntry(message.getID());
if (ptrSPITObject != nullptr) { if (ptrSPITObject != nullptr) {
SType *ptrSPITType = mRemoteSpitTypes.getEntry(ptrSPITObject->SPITTypeID.get()); SType *ptrSPITType = mProcessor.mRemoteSpitTypes.getEntry(ptrSPITObject->SPITTypeID.get());
if (ptrSPITType != nullptr) { if (ptrSPITType != nullptr) {
mCallbacks.onSpitObject(ObjectEvent::Deleted, true, *ptrSPITType, *ptrSPITObject); mCallbacks.onSpitObject(ObjectEvent::Deleted, true, *ptrSPITType, *ptrSPITObject);
} }
@@ -1094,7 +1048,7 @@ bool SClient::changeSPITObject(SObject *obj) {
ptrSPITObject = mSpitObjects.getEntry(obj->getID()); ptrSPITObject = mSpitObjects.getEntry(obj->getID());
if (ptrSPITObject == nullptr) if (ptrSPITObject == nullptr)
return false; return false;
ptrSPITType = mSpitTypes.getEntry(obj->getID()); ptrSPITType = mProcessor.mSpitTypes.getEntry(obj->getID());
if (ptrSPITObject == nullptr) if (ptrSPITObject == nullptr)
return false; return false;
@@ -1141,7 +1095,7 @@ int SClient::removeSPITObject(string objId) {
ptrSPITObject = mSpitObjects.getEntry(objId); ptrSPITObject = mSpitObjects.getEntry(objId);
if (ptrSPITObject == nullptr) if (ptrSPITObject == nullptr)
return -1; return -1;
ptrSPITType = mSpitTypes.getEntry(ptrSPITObject->SPITTypeID.get()); ptrSPITType = mProcessor.mSpitTypes.getEntry(ptrSPITObject->SPITTypeID.get());
if (ptrSPITType == nullptr) if (ptrSPITType == nullptr)
return -1; return -1;
ptrSPITObject->fillMessageOP(sMRemoveSPITObject); ptrSPITObject->fillMessageOP(sMRemoveSPITObject);
@@ -1189,7 +1143,7 @@ void SClient::parsePlaySPITEnd(Message::PlayEnd &message) {
SPlayer::PlayType *ptrPlaySPITType = i->second.get(); SPlayer::PlayType *ptrPlaySPITType = i->second.get();
bool boolStarted = ptrPlaySPITType->getIsNew(); bool boolStarted = ptrPlaySPITType->getIsNew();
bool boolStopped = (ptrPlaySPITType->getIsPlayed() == false); bool boolStopped = (ptrPlaySPITType->getIsPlayed() == false);
SType *ptrSPITType = mSpitTypes.getEntry(ptrPlaySPITType->getSPITTypeID()); SType *ptrSPITType = mProcessor.mSpitTypes.getEntry(ptrPlaySPITType->getSPITTypeID());
if (ptrSPITType == nullptr) { if (ptrSPITType == nullptr) {
// set isplayed to false, the ptrPlayObject will be removed by ptrSPITPlayer.endPlaySequence() // set isplayed to false, the ptrPlayObject will be removed by ptrSPITPlayer.endPlaySequence()
ptrPlaySPITType->setIsPlayed(false); ptrPlaySPITType->setIsPlayed(false);
@@ -1211,9 +1165,9 @@ void SClient::parseReportPlayStatus(Message::ReportPlayStatus &message) {
} }
} }
if (ptrSPITObject->ServerRemote.get() == false) { if (ptrSPITObject->ServerRemote.get() == false) {
ptrSPITType = mSpitTypes.getEntry(ptrSPITObject->SPITTypeID.get()); ptrSPITType = mProcessor.mSpitTypes.getEntry(ptrSPITObject->SPITTypeID.get());
} else { } else {
ptrSPITType = mRemoteSpitTypes.getEntry(ptrSPITObject->SPITTypeID.get()); ptrSPITType = mProcessor.mRemoteSpitTypes.getEntry(ptrSPITObject->SPITTypeID.get());
} }
if (ptrSPITType == nullptr) { if (ptrSPITType == nullptr) {
File diff suppressed because it is too large Load Diff