Files
1NiM-WatingRoom-WatchContro…/components/spit/src/spit_processor.cpp
T
2026-10-18 16:22:11 +02:00

745 lines
28 KiB
C++

#include "spit_processor.hpp"
#include "esp_log.h"
namespace spit {
static const char *TAG = "SPIT";
/**
* Create a new SPIT_client instance, should be done once by the user app.
* @param p_SPITClientInterface the user app should implement the SPIT_ClientInterface.
*/
SProcessor::SProcessor(string name, string projName, string hostName, string guid, Callbacks calls, InternalCallbacks intern)
: mCallbacks(calls),
mInternCallbacks(intern),
mName(name),
mGuid(guid),
mProjName(projName),
mComputerName(hostName) {
}
SProcessor::~SProcessor() {
}
unique_ptr<Message::Connect> SProcessor::createConnectMessage(string serverIP, string serverPort, string loginName, string loginPassword) {
auto msg = make_unique<Message::Connect>(getComputerName(), mName);
msg->setLoginName(loginName);
msg->setLoginPassword(loginPassword);
msg->setServerIP(serverIP);
if (serverPort.length() <= 0) {
serverPort = "0";
}
int intServerPort = stoi(serverPort);
msg->setServerPort(intServerPort);
return msg;
}
/**
* Virtual construct - means actionAssigned for SPITTypes is is not implemented in SPITProtocol.
* This can used to setActionAssigned to all SPITObjects with this SPITType.
* This may be used in the case when the same action should be done for every SPITObject with this SPITType associated.
* This tells the server not what action is done, but it tells the server that there is an action.
* @param typeId the id of the SPITType
* @param actionAssigned
*/
void SProcessor::setActionType(string typeId, bool actionAssigned) {
SType *spitType = mSpitTypes.getEntry(typeId);
if (spitType == nullptr)
return;
if (spitType->ActionAssigned.set(actionAssigned)) {
sendTypeInternal(*spitType);
for (auto &[key, value] : mSpitObjects.getRepo()) {
if (value->SPITTypeID.get() == spitType->getID()) {
if (value->setActionAssignedType(actionAssigned) == true) {
sendObjectInternal(value.get());
}
}
}
}
}
/** This should be called if the user wants to associate/remove an action with a SPITObject. */
void SProcessor::setActionObject(string spitObjId, bool actionAssigned) {
SObject *spitObject = mSpitObjects.getEntry(spitObjId);
if (spitObject == nullptr)
return;
if (spitObject->setActionAssigned(actionAssigned) == true) {
sendObjectInternal(spitObject);
}
}
std::vector<char> SProcessor::createMessage(Message::OPPart &opPart) {
if (mMessageNumberSend == 255)
mMessageNumberSend = 1;
else
mMessageNumberSend++;
opPart.setMessageNumber(mMessageNumberSend);
opPart.setServerInfoInHeader(mGuid, mServerID);
int opFlag = opPart.getHeader()->getType();
try {
return Message::createMessage(opPart);
} catch (...) {
ESP_LOGD(TAG, "Exception client OPFlag: %d", opFlag);
}
return {};
}
void SProcessor::resetMessageNumberReceived() {
mMessageNumberReceived = -1;
mOvertakingMessages.clear();
}
void SProcessor::checkParseMessageData(vector<char> data) {
auto message = make_unique<Message>(data);
// answerWatchdog();
if (!message->getHeader() || !message->getOPPart()) {
ESP_LOGD(TAG, "Client::parseMessage incomplete message");
return;
}
int msgNum = (int)(message->getHeader()->getMessageNumber() & 0xFF);
if (msgNum == 0) {
parseMessage(*message);
return;
}
if (mMessageNumberReceived < 0) {
mMessageNumberReceived = msgNum;
parseMessage(*message);
return;
}
int msgNumNext = mMessageNumberReceived + 1;
if (msgNumNext > 255 || msgNumNext < 1)
msgNumNext = 1;
if (msgNum == msgNumNext) {
mMessageNumberReceived = msgNum;
parseMessage(*message);
mMessageNumberReceived = sendOvertakingMessage(mMessageNumberReceived);
} else {
// message has overtaken another message
addOvertakingMessage(move(message));
}
}
void SProcessor::addOvertakingMessage(unique_ptr<Message> message) {
if (!message) {
return;
}
if (mOvertakingMessages.size() > MAX_OVERTAKING_SPIT_MESSAGES) {
ESP_LOGD(TAG, "Client receiveing: perhaps message lost !!!!!");
}
int intMessageNumber = (int)(message->getHeader()->getMessageNumber() & 0xFF);
for (auto it = mOvertakingMessages.begin(); it != mOvertakingMessages.end(); ++it) {
const auto &overtaking = *it;
int intOvertakingMessageNumber = (int)(overtaking->getHeader()->getMessageNumber() & 0xFF);
if (intMessageNumber < intOvertakingMessageNumber) {
mOvertakingMessages.insert(it, move(message));
return;
}
}
mOvertakingMessages.push_back(move(message));
}
int SProcessor::sendOvertakingMessage(int msgNumRec) {
// check overtaking messages
auto it = mOvertakingMessages.begin();
while (mOvertakingMessages.size() > 0) {
int msgNumNext = msgNumRec + 1;
if (msgNumNext > 255 || msgNumNext < 1)
msgNumNext = 1;
auto &overtakingMessage = *it;
int msgNum = (int)(overtakingMessage->getHeader()->getMessageNumber() & 0xFF);
if (msgNum == msgNumNext) {
msgNumRec = msgNum;
parseMessage(*overtakingMessage);
mOvertakingMessages.erase(it);
it = mOvertakingMessages.begin();
} else {
break;
}
}
return msgNumRec;
}
void SProcessor::parseMessage(Message &message) {
// answerWatchdog();
if (!message.getHeader() || !message.getOPPart()) {
ESP_LOGD(TAG, "Client::parseMessage incomplete message");
return;
}
switch (message.getType()) {
//----- Connection -----
case Message::ReportProject::OPFLAG:
parseReportProject(message.getAs<Message::ReportProject>());
break;
//----- SPIT Project -----
case Message::StartProjectTransfer::OPFLAG:
parseStartProjectTransfer(message.getAs<Message::StartProjectTransfer>());
break;
case Message::CloseProject::OPFLAG:
parseCloseProject(message.getAs<Message::CloseProject>());
break;
case Message::RequestProjectTransfer::OPFLAG:
parseRequestProjectTransfer(message.getAs<Message::RequestProjectTransfer>());
break;
case Message::EndProjectTransfer::OPFLAG:
parseEndProjectTransfer(message.getAs<Message::EndProjectTransfer>());
break;
//----- SPIT Types ------
case Message::ReportType::OPFLAG:
parseReportType(message.getAs<Message::ReportType>());
break;
case Message::RemoveType::OPFLAG:
parseRemoveType(message.getAs<Message::RemoveType>());
//----- SPIT Objects ------
break;
case Message::ReportObject::OPFLAG:
parseReportObject(message.getAs<Message::ReportObject>());
break;
case Message::RemoveObject::OPFLAG:
parseRemoveObject(message.getAs<Message::RemoveObject>());
break;
//----- Play SPIT Objects ------
case Message::PlayStart::OPFLAG:
parsePlayStart(message.getAs<Message::PlayStart>());
break;
case Message::PlayObject::OPFLAG:
parsePlayObject(message.getAs<Message::PlayObject>());
break;
case Message::PlayEnd::OPFLAG:
parsePlayEnd(message.getAs<Message::PlayEnd>());
break;
case Message::ReportPlayStatus::OPFLAG:
parseReportPlayStatus(message.getAs<Message::ReportPlayStatus>());
break;
default:
ESP_LOGD(TAG, "Client::parseMessage: Unknown Message");
}
}
//----- SPIT Project ------
void SProcessor::parseReportProject(Message::ReportProject &message) {
ESP_LOGD(TAG, "parse ReportProject");
mServerProjectID = message.getProjectID();
mServerProjectName = message.getProjectName();
mServerFramesPerSecond = message.getFramesPerSecond();
mCallbacks.onProjectUpdate(ProjUpdate::ServerLoaded, mServerProjectID);
// Set all SPITTypes and SPITObjects confirmed = false
SType::setConfirmedFalse(mSpitTypes);
SObject::setConfirmedFalse(mSpitObjects);
// Send RequestProjectTransfer
Message::RequestProjectTransfer sMRequestProjectTransfer;
if (mInternCallbacks.sendMessage(sMRequestProjectTransfer) < 0) {
ESP_LOGD(TAG, "Client::parseReportProject could not send RequestProjectTransfer");
}
// todo Don't send the ReportProject here it should be sended after parseEndProjectTransfer
// Send client's ReportProject
Message::ReportProject reportProject(mProjName, mProjName);
reportProject.setFramesPerSecond(0);
if (mInternCallbacks.sendMessage(reportProject) < 0) {
ESP_LOGD(TAG, "Client::parseReportProject could not send Client's ReportProject");
}
}
void SProcessor::parseCloseProject(Message::CloseProject &p_CloseSPITProject) {
ESP_LOGD(TAG, "parse CloseProject");
string stringProjectID;
mCallbacks.onProjectUpdate(ProjUpdate::ServerClosed, p_CloseSPITProject.getProjectID());
SPlayer::clearPlayers();
}
void SProcessor::parseRequestProjectTransfer(Message::RequestProjectTransfer &message) {
ESP_LOGD(TAG, "parse RequestProjectTransfer");
// StartProjectTransfer
Message::StartProjectTransfer sMStartProjectTransfer;
if (mInternCallbacks.sendMessage(sMStartProjectTransfer) < 0) {
return;
}
// send all listes SPITTypes
for (const auto &[key, value] : mSpitTypes.getRepo()) {
sendTypeInternal(*value);
mInternCallbacks.delay(10);
}
for (auto &[key, value] : mSpitObjects.getRepo()) {
sendObjectInternal(value.get());
mInternCallbacks.delay(10);
}
// EndProjectTransfer
Message::EndProjectTransfer sMEndProjectTransfer;
mInternCallbacks.sendMessage(sMEndProjectTransfer);
}
void SProcessor::parseStartProjectTransfer(Message::StartProjectTransfer &message) {
mCallbacks.onProjectUpdate(ProjUpdate::StartTransfer, mServerProjectID);
}
void SProcessor::parseEndProjectTransfer(Message::EndProjectTransfer &message) {
SObject::clearUnconfirmedObjects(mSpitObjects);
mCallbacks.onProjectUpdate(ProjUpdate::EndTransfer, mServerProjectID);
// Send Message::ReportProject after the mSPITClientInterface is notfied of EndProjectTransfer
Message::ReportProject reportSPITProject(mProjName, mProjName);
reportSPITProject.setFramesPerSecond(0);
if (mInternCallbacks.sendMessage(reportSPITProject) < 0) {
ESP_LOGD(TAG, "Client::parseReportProject could not send Client's ReportProject");
}
}
void SProcessor::parseReportType(Message::ReportType &message) {
ESP_LOGD(TAG, "parse ReportType ID %s Name %s", message.getID().c_str(), message.getName().c_str());
SType *sType;
bool isNew = false;
bool isChanged = false;
if (message.getServerRemote() == false) {
sType = mSpitTypes.getEntry(message.getID());
if (sType == nullptr) {
// The user's app may veto the SPITType
bool createdByClient = false;
if (sType) {
createdByClient = sType->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());
sType = spitType.get();
mSpitTypes.addEntry(move(spitType));
isNew = true;
}
} else {
sType = mRemoteSpitTypes.getEntry(message.getID());
if (sType == nullptr) {
auto spitType = make_unique<SType>(message.getID());
sType = spitType.get();
mRemoteSpitTypes.addEntry(move(spitType));
isNew = true;
}
}
if (!sType->setMessageOP(message)) {
// SPITType is not changable -> send back to the server
sendTypeInternal(*sType);
return;
}
auto eventType = isNew ? ObjectEvent::Created : ObjectEvent::Changed;
// add or change SPITType
mCallbacks.onSpitType(eventType, sType->ServerRemote.get(), *sType);
if (sType != nullptr) {
if (sType->setConfirmed(true) == true || isChanged == true) {
sendTypeInternal(*sType);
}
}
}
void SProcessor::parseRemoveType(Message::RemoveType &message) {
ESP_LOGD(TAG, "parse RemoveType %s", message.getID().c_str());
bool isRemote = false;
string sTypeID = message.getID();
SType *sType = mRemoteSpitTypes.getEntry(sTypeID);
if (!sType) {
isRemote = true;
} else {
sType = mSpitTypes.getEntry(sTypeID);
if (!sType) {
isRemote = false;
} else {
// No SType with sTypeID is listet
return;
}
}
if (sType->getCreatedByClient() && sType->Fixed.get()) {
// the SPITyte is created by client himself and it is fixed -> don't remove the SType!!
// Send the SPITTyp back to the server
sendTypeInternal(*sType);
return;
}
mCallbacks.onSpitType(ObjectEvent::Deleted, isRemote, *sType);
if (isRemote == false) {
mSpitTypes.removeEntry(*sType);
} else {
mRemoteSpitTypes.removeEntry(*sType);
}
}
/**
* Change an existing SPIT_Type.
* @param p_SPITType the SPITType vont
* @return true = changed, false = not changed maybe p_SPITType is NULL or the SPITType doesn't exists
*/
bool SProcessor::changeType(SType *sType) {
if (sType == nullptr)
return false;
SType *mod = mSpitTypes.getEntry(sType->getID());
if (mod == nullptr)
return false;
mod->DefaultDelay.set(sType->DefaultDelay.get());
mod->DefaultDuration.set(sType->DefaultDuration.get());
mod->Fixed.set(sType->Fixed.get());
mod->GroupName.set(sType->GroupName.get());
mod->Name.set(sType->Name.get());
mod->ProjectIndepended.set(sType->ProjectIndepended.get());
mCallbacks.onSpitType(ObjectEvent::Changed, false, *mod);
sendTypeInternal(*mod);
return true;
}
/**
* If a client has removed a SPITType where id == p_SPITTypeID, it should send it to the server.
* The corresponding SPITType if listet in SPITType will be deleted.
* An eventRemoveSPITType will occur.
* If a connection to a SPITServer is established, the SPITServer may dicard the deletion an an eventSPITType will occur
* -> the SPITType will be listet again.
* @param p_SPITType the id of the SPITType ro remove
* @return 0 = is sended, -1 = is not sended
*/
int SProcessor::removeType(string sType) {
if (sType.length() <= 0)
return -1;
SType *mod = mSpitTypes.getEntry(sType);
if (mod == nullptr)
return -1;
Message::RemoveType sMRemoveSPITType;
mod->fillMessageOP(sMRemoveSPITType);
mCallbacks.onSpitType(ObjectEvent::Deleted, false, *mod);
mSpitTypes.removeEntry(*mod);
return mInternCallbacks.sendMessage(sMRemoveSPITType);
}
SType *SProcessor::createType(string id, string groupName, string name, uint64_t delay, uint64_t duration, bool fixed, bool projIndipendent) {
bool boolNew;
SType *sType = mSpitTypes.getEntry(id);
if (sType == nullptr) {
auto spitType = make_unique<SType>(id, groupName, name, fixed, projIndipendent, delay, duration);
sType = spitType.get();
mSpitTypes.addEntry(move(spitType));
sType->setCreatedByClient(true);
boolNew = true;
} else {
sType->GroupName.set(groupName);
sType->Name.set(name);
sType->Fixed.set(fixed);
sType->ProjectIndepended.set(projIndipendent);
sType->DefaultDelay.set(delay);
sType->DefaultDuration.set(duration);
boolNew = false;
}
auto eventType = boolNew ? ObjectEvent::Created : ObjectEvent::Changed;
mCallbacks.onSpitType(eventType, false, *sType);
sendTypeInternal(*sType);
return sType;
}
/**
* If a client has changed a SPITType, it should send it to the server to transmit the changes.
* If the SPITType is a fixed one and not created by the client himself, then an eventSPITType can be sent from the server, which cancels the changes.
* @param sType the pointer to the changed SPITType
* @return 0 = is sended, -1 = is not sended
*/
int SProcessor::sendTypeInternal(SType &sType) {
Message::ReportType reportType;
sType.fillMessageOP(reportType);
return mInternCallbacks.sendMessage(reportType);
}
//----- SPIT Objects ------
void SProcessor::parseReportObject(Message::ReportObject &message) {
ESP_LOGD(TAG, "parse ReportObject %s", message.getID().c_str());
SObject *sObject;
SType *sType;
bool isNew = false;
bool isRemote = false;
bool isChanged = false;
{
ESP_LOGD(TAG, "parse ReportObject %s / %s", message.getID().c_str(), message.getName().c_str());
if (message.getServerRemote() == false) {
isRemote = false;
sObject = mSpitObjects.getEntry(message.getID());
sType = mSpitTypes.getEntry(message.getSPITTypeID());
if (sType == nullptr) {
// No associated SPITType found
if (sObject != nullptr) {
// SpitObject exists but has no corresponding SPITType -> remove the SPITObject without sending a message
// Maybe the SPITObject has changed the SPITTypeID to a SPITTypeID of another board
mSpitObjects.removeEntry(*sObject);
}
return;
}
bool isKnownType = sType != nullptr;
if (sObject == nullptr) {
// The user's app my veto the SPITType
if (mCallbacks.onCheckSpitObjectVeto(isKnownType) == false) {
ESP_LOGW(TAG, "ObjectVeto %s / %s", message.getID().c_str(), message.getName().c_str());
return;
}
auto spitObj = make_unique<SObject>(message.getID());
sObject = spitObj.get();
mSpitObjects.addEntry(move(spitObj));
isNew = true;
} else {
// The user's app my veto the SPITType
if (mCallbacks.onCheckSpitObjectVeto(isKnownType) == false) {
// SpitObject exists and User APp denied the SPITObject -> remove the SPITObject without sending a message
mSpitObjects.removeEntry(*sObject);
ESP_LOGW(TAG, "TypeVeto %s / %s", message.getID().c_str(), message.getName().c_str());
return;
}
}
} else {
isRemote = true;
sObject = mRemoteSpitObjects.getEntry(message.getID());
sType = mRemoteSpitTypes.getEntry(message.getSPITTypeID());
if (sType == nullptr) {
// No associated SPITType found
return;
}
if (sObject == nullptr) {
auto spitObj = make_unique<SObject>(message.getID());
sObject = spitObj.get();
mRemoteSpitObjects.addEntry(move(spitObj));
isNew = true;
}
}
if (!sObject->setMessageOP(&message)) {
ESP_LOGE(TAG, "Change not allowed %s", sObject->getID().c_str());
// setMessageOP error - the SPITObject can't be changed, it may be fixed and crated by this client
sendObjectInternal(sObject);
return;
}
if (isRemote == false) {
// set the virtual action assignment
sObject->setActionAssignedType(sType->ActionAssigned.get());
}
auto eventType = isNew ? ObjectEvent::Created : ObjectEvent::Changed;
mCallbacks.onSpitObject(eventType, isRemote, *sType, *sObject);
if (sObject->setConfirmed(true) == true || isChanged == true) {
// Confirmation has changed
sendObjectInternal(sObject);
}
}
}
void SProcessor::parseRemoveObject(Message::RemoveObject &message) {
ESP_LOGD(TAG, "parse RemoveObject %s", message.getID().c_str());
SObject *sObject = mRemoteSpitObjects.getEntry(message.getID());
if (sObject != nullptr) {
SType *sType = mRemoteSpitTypes.getEntry(sObject->SPITTypeID.get());
if (sType != nullptr) {
mCallbacks.onSpitObject(ObjectEvent::Deleted, true, *sType, *sObject);
}
mRemoteSpitObjects.removeEntry(*sObject);
} else {
// call removeObject, this will notify the server that the object is removed
removeObject(message.getID());
}
}
int SProcessor::sendObjectInternal(SObject *sObject) {
if (sObject == nullptr)
return -1;
Message::ReportObject reportObject;
sObject->fillMessageOP(reportObject);
return mInternCallbacks.sendMessage(reportObject);
}
/**
* When the client changes an existing SPITObject (normally the client should not do this), then he should send the changes to the SPITServer.
* An eventSPITObject occurs.
* The SPITServer may discard the changes and a second eventSPITObject occurs to correct the changes.
* @param obj the pointer to the changed SPITObject.
* @return 0 = sended, -1 = not sended
*/
bool SProcessor::changeObject(SObject *sObject) {
if (sObject == nullptr)
return false;
SObject *mod = mSpitObjects.getEntry(sObject->getID());
if (mod == nullptr)
return false;
SType *sType = mSpitTypes.getEntry(sObject->getID());
if (mod == nullptr)
return false;
mod->setActionAssigned(sObject->getActionAssigned());
mod->Delay.set(sObject->Delay.get());
mod->Duration.set(sObject->Delay.get());
mod->Fixed.set(sObject->Fixed.get());
mod->FrameFadeInLength.set(sObject->FrameFadeInLength.get());
mod->FrameFadeOutLength.set(sObject->FrameFadeOutLength.get());
mod->FrameLength.set(sObject->FrameLength.get());
mod->FrameStart.set(sObject->FrameStart.get());
mod->Name.set(sObject->Name.get());
mod->Remark.set(sObject->Remark.get());
mod->SPITTypeID.set(sObject->SPITTypeID.get());
mod->ServerParams.set(sObject->ServerParams.get());
mod->Track.set(sObject->Track.get());
mod->ValueFactor.set(sObject->ValueFactor.get());
mod->ValueUse.set(sObject->ValueUse.get());
mCallbacks.onSpitObject(ObjectEvent::Changed, false, *sType, *mod);
sendObjectInternal(mod);
return true;
}
/**
* When the client wants to remove a SPITObject with id == p_SPITObjectID (normally the client should not do this), then he should send it to the SPITServer.
* The corresponding SPITObject if listet in SPITObject will be deleted.
* An eventRemoveSPITType will occur.
* If an connection to a SPITServer is established, the SPITServer may discard the deletion and an eventSPITObject occurs
* -> the SPITObject is listet again.
* @param objId the id of the SPITObject to remove.
* @return 0 = sended to the SPITServer, -1 = not sended to the SPITServer or nos SPITObject with id == objId exists.
*/
int SProcessor::removeObject(string objId) {
if (objId.length() <= 0)
return -1;
Message::RemoveObject remObj;
SObject *sObject = mSpitObjects.getEntry(objId);
if (sObject == nullptr)
return -1;
SType *sType = mSpitTypes.getEntry(sObject->SPITTypeID.get());
if (sType == nullptr)
return -1;
sObject->fillMessageOP(remObj);
mCallbacks.onSpitObject(ObjectEvent::Deleted, false, *sType, *sObject);
mSpitObjects.removeEntry(*sObject);
return mInternCallbacks.sendMessage(remObj);
}
// //----- Play SPIT Objects ------
void SProcessor::parsePlayStart(Message::PlayStart &message) {
ESP_LOGD(TAG, "parse PlayStart ID: %s Name: %s Running: %d", message.getPlayerID().c_str(), message.getPlayerName().c_str(), (int)message.getPlayerIsRunning());
SPlayer &player = SPlayer::getSPITPlayer(message.getPlayerID());
player.setIsRunning(message.getPlayerIsRunning());
player.setName(message.getPlayerName());
player.setType(message.getPlayerType());
player.setTime(message.getTime());
player.startPlaySequence();
mCallbacks.onPlay(player.getID(), player.getName(), player.getType(), player.getIsRunning(), player.getTime());
}
void SProcessor::parsePlayObject(Message::PlayObject &message) {
SPlayer &player = SPlayer::getSPITPlayer(message.getPlayerID());
SObject *sObject = mSpitObjects.getEntry(message.getSPITObjectID());
if (sObject == nullptr) {
return;
}
SPlayer::PlayType *playType = player.addTypePlaying(sObject->SPITTypeID.get());
if (playType == nullptr) {
return;
}
playType->setPlayerIsRunning(player.getIsRunning());
playType->addValue(((double)message.getValue() / 1000000), ((double)sObject->ValueFactor.get() / 1000000));
}
void SProcessor::parsePlayEnd(Message::PlayEnd &message) {
SPlayer &sPlayer = SPlayer::getSPITPlayer(message.getPlayerID());
auto &playTypes = sPlayer.getPlaySPITTypes();
for (auto i = playTypes.begin(); i != playTypes.end(); i++) {
SPlayer::PlayType *playType = i->second.get();
bool isStarted = playType->getIsNew();
bool iStopped = (playType->getIsPlayed() == false);
SType *ptrSPITType = mSpitTypes.getEntry(playType->getSPITTypeID());
if (ptrSPITType == nullptr) {
// set isplayed to false, the ptrPlayObject will be removed by sPlayer.endPlaySequence()
playType->setIsPlayed(false);
continue;
}
mCallbacks.onPlaySpitType(playType->getPlayerID(), playType->getSPITTypeID(), playType->getPlayerIsRunning(), isStarted, iStopped, playType->getValue());
}
sPlayer.endPlaySequence();
}
void SProcessor::parseReportPlayStatus(Message::ReportPlayStatus &message) {
SType *sType = NULL;
SObject *sObject = mRemoteSpitObjects.getEntry(message.getID());
if (sObject == nullptr) {
sObject = mSpitObjects.getEntry(message.getID());
if (sObject == nullptr) {
return;
}
}
if (sObject->ServerRemote.get() == false) {
sType = mSpitTypes.getEntry(sObject->SPITTypeID.get());
} else {
sType = mRemoteSpitTypes.getEntry(sObject->SPITTypeID.get());
}
if (sType == nullptr) {
return;
}
mCallbacks.onPlayRemoteObjectStatus(*sType, *sObject, message.getFrameInsideObject(), message.getValue());
}
// //--------- Remote ----------
/**
* Send a remote control command to the SPITServer.
* 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 sObjectId the id of the remote SPITObject (this represents the remote control command)
* @param valuePpm the value in ppm
* in case a) the value is ignored
* in case b) the value is used
* @param valueFlag indicates how the server should use valuePpm:
* VALUEFLAG_DIRECT (0x00) The server overwrites its existing value with p_Value
* VALUEFLAG_INCREASE (0x01) The server increases his existing value by valuePpm
* VALUEFLAG_DECREASE (0x01) The server decreases his existing value by valuePpm
*/
void SProcessor::sendRemoteObject(string sObjectId, int valuePpm, char valueFlag) {
SObject *remoteObject = mRemoteSpitObjects.getEntry(sObjectId);
if (remoteObject == nullptr)
return;
Message::PlayStart playSPITStart(mGuid, mProjName, SPlayer::PTYPE_DISCRETE);
playSPITStart.setPlayerIsRunning(false);
playSPITStart.setTime(0);
mInternCallbacks.sendMessage(playSPITStart);
Message::PlayObject playSPITObject;
playSPITObject.setID(remoteObject->getID());
playSPITObject.setPlayPrePosition(false);
playSPITObject.setPlayerID(mGuid);
playSPITObject.setValue(valuePpm);
playSPITObject.setValueFlag(valueFlag);
mInternCallbacks.sendMessage(playSPITObject);
Message::PlayEnd playSPITEnd(mGuid);
mInternCallbacks.sendMessage(playSPITEnd);
}
} // namespace spit