/** * @RDE_HEADER@ * AvaTestServer * $Id$ * $HeadURL$ * $Author$ * Created by Christian Fröbel, SLSE, 2017-06-19 */ #include #include #include #include #include "ava_test_server.h" namespace AudioVideoManagement { int ScrEdAVStream::getCategory() const { return m_Category; } double ScrEdAVStream::getDuration() const { return m_Duration; } QDateTime ScrEdAVStream::getEndTime() const { return m_EndTime; } QString ScrEdAVStream::getName() const { return m_Name; } QDateTime ScrEdAVStream::getPlayTime() const { return m_PlayTime; } int ScrEdAVStream::getSignalPauseHandling() const { return m_SignalPauseHandling; } int ScrEdAVStream::getSpeed() const { return m_Speed; } QDateTime ScrEdAVStream::getStartTime() const { return m_StartTime; } int ScrEdAVStream::getState() const { return m_State; } int ScrEdAVStream::getStreamPlayMode() const { return m_StreamPlayMode; } int ScrEdAVStream::getType() const { return m_Type; } bool ScrEdAVStream::isMute() const { return m_Mute; } void ScrEdAVStream::setCategory(int newVal) { m_Category = newVal; } void ScrEdAVStream::setDuration(double newVal) { m_Duration = newVal; } void ScrEdAVStream::setEndTime(const QDateTime &newVal) { if(m_StartTime.isValid() && newVal < m_StartTime) { m_EndTime = m_StartTime; m_StartTime = newVal; } else { m_EndTime = newVal; } } void ScrEdAVStream::setMute(bool newVal) { m_Mute = newVal; } void ScrEdAVStream::setName(const QString &newVal) { m_Name = newVal.trimmed(); } void ScrEdAVStream::setPlayTime(const QDateTime &newVal) { if(newVal >= m_StartTime && newVal <= m_EndTime) { m_PlayTime = newVal; } else { m_PlayTime = QDateTime(); } } void ScrEdAVStream::setSignalPauseHandling(int newVal) { m_SignalPauseHandling = newVal; } double ScrEdAVStream::getVolume() const { return m_VolumeFactor; } void ScrEdAVStream::setVolume(double volume) { m_VolumeFactor = volume; } void ScrEdAVStream::setSpeed(int newVal) { m_Speed = newVal; } void ScrEdAVStream::setStartTime(const QDateTime &newVal) { m_StartTime = newVal; } void ScrEdAVStream::setState(int newVal) { m_State = newVal; } void ScrEdAVStream::setStreamPlayMode(int newVal) { m_StreamPlayMode = newVal; } void ScrEdAVStream::setType(int newVal) { m_Type = newVal; } //====================================================================================================================== int ScrEdAVScript::getCategory() const { return m_Category; } int ScrEdAVScript::getFileSplitting() const { return m_FileSplitting; } QString ScrEdAVScript::getExportScriptName() const { return m_ExportScriptName; } QString ScrEdAVScript::getExportDirectory() const { return m_ExportDirectory; } QString ScrEdAVScript::getCurrentPlayedStream() const { return m_CurrentPlayedStream; } double ScrEdAVScript::getDuration() const { return m_Duration; } double ScrEdAVScript::getElapsedTime() const { return m_ElapsedTime; } QDateTime ScrEdAVScript::getEndTime() const { return m_EndTime; } QString ScrEdAVScript::getName() const { return m_Name; } QDateTime ScrEdAVScript::getStartTime() const { return m_StartTime; } int ScrEdAVScript::getState() const { return m_State; } QVector ScrEdAVScript::getStreamSequences() const { return m_StreamSequences; } bool ScrEdAVScript::isMute() const { return m_Mute; } void ScrEdAVScript::setCategory(int newVal) { m_Category = newVal; } void ScrEdAVScript::setCurrentPlayedStream(const QString &newVal) { m_CurrentPlayedStream = newVal.trimmed(); } void ScrEdAVScript::setDuration(double newVal) { m_Duration = newVal; } void ScrEdAVScript::setElapsedTime(double newVal) { m_ElapsedTime = newVal; } void ScrEdAVScript::setEndTime(const QDateTime &newVal) { m_EndTime = newVal; } void ScrEdAVScript::setMute(bool newVal) { m_Mute = newVal; } void ScrEdAVScript::setName(const QString &newVal) { m_Name = newVal.trimmed(); } void ScrEdAVScript::setStartTime(const QDateTime &newVal) { m_StartTime = newVal; } void ScrEdAVScript::setState(int newVal) { m_State = newVal; } void ScrEdAVScript::setFileSplitting(int newVal) { m_FileSplitting = newVal; } void ScrEdAVScript::setStreamSequences(const QVector &newVal) { m_StreamSequences = newVal; } void ScrEdAVScript::setExportScriptName(const QString &newVal) { m_ExportScriptName = newVal; } void ScrEdAVScript::setExportDirectory(const QString &newVal) { m_ExportDirectory = newVal; } //====================================================================================================================== AvaTestServer::AvaTestServer() : m_AbsScriptPos() , m_RelScriptPos() , m_PosUpdateTime() , m_StreamState() , m_ScriptState() , m_StreamSpeed() , m_PendingListReading() , m_ReversPlay() , m_Audiomute() , m_PlayMode() , m_StreamNbr() { m_Server = new QTcpServer(); bool couldListen = m_Server->listen(QHostAddress::Any, 6370); Q_ASSERT(couldListen); connect(m_Server, &QTcpServer::newConnection, this, &AvaTestServer::connectionIncoming); m_PosUpdate = new QTimer(); m_ScriptPosUpdate = new QTimer(); connect(m_PosUpdate, &QTimer::timeout, this, &AvaTestServer::sendPosUpdate); connect(m_ScriptPosUpdate, &QTimer::timeout, this, &AvaTestServer::sendScriptPosUpdate); } AvaTestServer::~AvaTestServer() { for (QTcpSocket *conn : qAsConst(m_Conns)) { // disconnect before we delete as otherwise closedConnection() would be called wich would // also delete the socket. conn->disconnect(this); delete conn; } m_Conns.clear(); delete m_ScriptPosUpdate; delete m_PosUpdate; delete m_Server; } void AvaTestServer::connectionIncoming() { qDebug() << "Incoming connection"; QTcpSocket *l_Conn = m_Server->nextPendingConnection(); Q_ASSERT(l_Conn); connect(l_Conn, &QTcpSocket::disconnected, this, &AvaTestServer::closedConnection); connect(l_Conn, &QTcpSocket::readyRead, this, &AvaTestServer::readAndAnswer); m_SignalPause = QStringLiteral("0"); m_PosUpdateTime = 0; m_ReversPlay = false; m_StreamSpeed = 100; m_StreamState = 0; m_Audiomute = false; m_Outputdevice.clear(); m_Conns.push_back(l_Conn); sendData(QStringLiteral("RCP_AVA/1.0")); } void AvaTestServer::closedConnection() { qDebug() << "connection closed"; m_PosUpdate->stop(); QMutableVectorIterator l_It(m_Conns); while (l_It.hasNext()) { QTcpSocket *l_Conn = l_It.next(); if (l_Conn->state() == QAbstractSocket::UnconnectedState) { l_Conn->disconnect(this); l_It.remove(); l_Conn->deleteLater(); // use deleteLater() as we want to delete the object which was emitting the signal return; } } Q_ASSERT_X(false, "AvaTestServer", "There must be a socket that was closed"); } void AvaTestServer::sendPosUpdate() { if (m_ReversPlay) m_Position = m_Position.addSecs(-1); else m_Position = m_Position.addSecs(1); if (m_PosUpdateTime != 0) { quint64 t = m_Position.toMSecsSinceEpoch() / 1000; QString l_Send = QString::fromUtf8(u8"221 \"%1\" \"%2\"").arg(m_SelectedStream, m_Outputdevice).append(QString::fromUtf8(u8" %1.%2 STREAMPOS").arg(t).arg(m_Position.toString(QStringLiteral("z")))); sendData(l_Send); } } void AvaTestServer::sendScriptPosUpdate() { m_AbsScriptPos += 1; m_RelScriptPos += 1; if (m_RelScriptPos >= m_SelStreamFromScript.getDuration()) { QVectorIterator l_Iterator(m_Script.getStreamSequences()); float l_Duration = 0; while (l_Iterator.hasNext()) { ScrEdAVStream l_Stream = l_Iterator.next(); l_Duration += l_Stream.getDuration(); qDebug() << "l_Duration " << l_Duration << " abs_scriptpos " << m_AbsScriptPos << " stream " << l_Stream.getName(); if (l_Duration > m_AbsScriptPos) { qDebug() << "set stream " << l_Stream.getName(); m_SelStreamFromScript = l_Stream; l_Iterator.toBack(); m_RelScriptPos = 0; } } } if (m_AbsScriptPos > m_Script.getDuration()) m_ScriptPosUpdate->stop(); QDateTime l_SendAbsPos = m_SelStreamFromScript.getStartTime().addSecs(m_RelScriptPos); QString l_Send = QString::fromUtf8(u8"233 \"%1\" \"%2\"").arg(m_Script.getName(), m_Outputdevice).append(QString::fromUtf8(u8" \"%1\" %2 %3 SCRIPTPOS")).arg(m_SelStreamFromScript.getName(), qDateTimeToAVTime(l_SendAbsPos), floatToAVTime(m_AbsScriptPos)); sendData(l_Send); } void AvaTestServer::readAndAnswer() { QVectorIterator l_It(m_Conns); while (l_It.hasNext()) { QTcpSocket *l_Conn = l_It.next(); if (l_Conn->state() != QAbstractSocket::ConnectedState) continue; //QString l_Data = QString::fromUtf8(m_Conn->readAll().data()); while (l_Conn->canReadLine()) { qDebug() << "read line from conn: " << l_Conn; processLine(l_Conn->readLine().trimmed()); } if (m_PendingListReading) { m_PendingListReading = false; //send script info.... QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); l_Send = QString::fromUtf8(u8"230 \"%1\" \"%2\" %3 %4 %5 SCRIPTINFO").arg(m_Script.getName(), m_Outputdevice, qDateTimeToAVTime(m_Script.getStartTime()), qDateTimeToAVTime(m_Script.getEndTime()), floatToAVTime(m_Script.getDuration())); sendData(l_Send); l_Send = QString::fromUtf8(u8"231 \"%1\" \"%2\" %3 SCRIPTSTATE").arg(m_Script.getName(), m_Outputdevice).arg(m_ScriptState); sendData(l_Send); m_StreamNbr = 0; if (m_Script.getStreamSequences().size() > m_StreamNbr) m_SelStreamFromScript = m_Script.getStreamSequences().at(m_StreamNbr); QDateTime l_SendAbsPos = m_SelStreamFromScript.getStartTime().addSecs(m_RelScriptPos); l_Send = QString::fromUtf8(u8"233 \"%1\" \"%2\" \"%3\" %4 %5 SCRIPTPOS").arg(m_Script.getName(), m_Outputdevice, m_SelStreamFromScript.getName(), qDateTimeToAVTime(l_SendAbsPos), floatToAVTime(m_AbsScriptPos)); sendData(l_Send); } } } void AvaTestServer::processLine(const QByteArray &line) { if (line.isEmpty()) { replyCommandNotAllowed(); return; } QList l_Parts = parse(line, 0); QString l_StringCode; //Q_FOREACH(QString str, l_Parts) qDebug() << "l_Parts parts: " << str; Q_ASSERT(!l_Parts.isEmpty()); l_StringCode = QString::fromUtf8(l_Parts[0].toUpper().trimmed()); qDebug() << "INCOMIMG: " << QString::fromUtf8(line) << " code is: " << l_StringCode; if (l_StringCode == QStringLiteral("KEEPALIVE")) { QString l_Send = QString::fromUtf8(u8"298 KEEPALIVE"); sendData(l_Send); return; } else if (l_StringCode == QStringLiteral("HELP")) { QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); l_Send = QString::fromUtf8(u8"290 COMMANDLIST"); sendData(l_Send); l_Send = QString::fromUtf8(u8"299 ENDOFPARAMETERLIST"); sendData(l_Send); } else if (l_StringCode == QStringLiteral("GETSTREAMLIST")) { if (l_Parts.size() >= 3) { int streamType = l_Parts[1].toInt(); int streamSource = l_Parts[2].toInt(); QString postfix; switch (streamSource) { case 2: postfix = QStringLiteral("(S)"); break; case 4: postfix = QStringLiteral("(L)"); break; default: break; } QString l_Send = QString::fromUtf8(u8"293 STREAMLIST"); sendData(l_Send); switch (streamType) { case 1 : //Audiolist l_Send = QString::fromUtf8(u8"1 2 \"Audiostream 1%1\"").arg(postfix); sendData(l_Send); l_Send = QString::fromUtf8(u8"1 2 \"Video 52-2%1\"").arg(postfix); sendData(l_Send); l_Send = QString::fromUtf8(u8"1 2 \"Audiostream 2%1\"").arg(postfix); sendData(l_Send); l_Send = QString::fromUtf8(u8"1 2 \"TrSpFuKr12%1\"").arg(postfix); sendData(l_Send); break; case 2 : //Videolist l_Send = QString::fromUtf8(u8"2 2 \"Video 52-1%1\"").arg(postfix); sendData(l_Send); l_Send = QString::fromUtf8(u8"2 2 \"Videöäü 50-5%1\"").arg(postfix); sendData(l_Send); l_Send = QString::fromUtf8(u8"2 2 \"Video 52-2%1\"").arg(postfix); sendData(l_Send); l_Send = QString::fromUtf8(u8"2 2 \"Video 3%1\"").arg(postfix); sendData(l_Send); l_Send = QString::fromUtf8(u8"2 2 \"Video 4%1\"").arg(postfix); sendData(l_Send); break; default : break; } l_Send = QString::fromUtf8(u8"299 ENDOFPARAMETERLIST"); sendData(l_Send); } } else if (l_StringCode == QStringLiteral("GETELOKALIST")) { QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); l_Send = QString::fromUtf8(u8"291 ELOKALIST"); sendData(l_Send); l_Send = QString::fromUtf8(u8"\"ELOKA 1\""); sendData(l_Send); l_Send = QString::fromUtf8(u8"\"Eloka 2\""); sendData(l_Send); l_Send = QString::fromUtf8(u8"299 ENDOFPARAMETERLIST"); sendData(l_Send); } else if (l_StringCode == QStringLiteral("SETVOLUME")) { if (l_Parts.size() >= 3) { m_Outputdevice = QString::fromUtf8(l_Parts[1].trimmed()); QString l_Value = QString::fromUtf8(l_Parts[2].trimmed()); QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); l_Send = QString::fromUtf8(u8"215 \"%1\" %2 VOLUME").arg(m_Outputdevice, l_Value); sendData(l_Send); } } else if (l_StringCode == QStringLiteral("SETBALANCE")) { if (l_Parts.size() >= 3) { m_Outputdevice = QString::fromUtf8(l_Parts[1].trimmed()); QString l_Value = QString::fromUtf8(l_Parts[2].trimmed()); QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); l_Send = QString::fromUtf8(u8"216 \"%1\" %2 BALANCE").arg(m_Outputdevice, l_Value); sendData(l_Send); } } else if (l_StringCode == QStringLiteral("SETVIDEODIALOGPROFILE")) { QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); } else if (l_StringCode == QStringLiteral("DELETEVIDEODIALOGPROFILE")) { QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); //TODO send actual states of the channels } else if (l_StringCode == QStringLiteral("SETNOTCHFILTERFREQ")) { if (l_Parts.size() >= 3) { m_Outputdevice = QString::fromUtf8(l_Parts[1].trimmed()); QString l_Value = QString::fromUtf8(l_Parts[2].trimmed()); QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); l_Send = QString::fromUtf8(u8"219 \"%1\" %2 NOTCHFILTERFREQ").arg(m_Outputdevice, l_Value); } } else if (l_StringCode == QStringLiteral("SWITCHCONTEXT")) { QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); return; } // cfroebel 2017-06-21 else if (l_StringCode == QStringLiteral("SETUSERPROFILE")) { if (l_Parts.size() != 8) { replyBadArguments(); return; } replyOk(); sendData(QStringLiteral("212 8 \"\" 1 RTCHOICEUNITSTATE")); sendData(QStringLiteral("212 6 \"\" 1 RTCHOICEUNITSTATE")); sendData(QStringLiteral("212 7 \"\" 1 RTCHOICEUNITSTATE")); sendData(QStringLiteral("212 4 \"\" 1 RTCHOICEUNITSTATE")); sendData(QStringLiteral("212 5 \"\" 1 RTCHOICEUNITSTATE")); sendData(QStringLiteral("212 2 \"\" 1 RTCHOICEUNITSTATE")); sendData(QStringLiteral("212 3 \"\" 1 RTCHOICEUNITSTATE")); sendData(QStringLiteral("212 1 \"\" 1 RTCHOICEUNITSTATE")); } else if (l_StringCode == QStringLiteral("SETTIMEZONE")) { QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); } else if (l_StringCode == QStringLiteral("SETFILTERSTATE")) { if (l_Parts.size() >= 4) { m_Outputdevice = QString::fromUtf8(l_Parts[1].trimmed()); QString l_Type = QString::fromUtf8(l_Parts[2].trimmed()); QString l_State = QString::fromUtf8(l_Parts[3].trimmed()); QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); l_Send = QStringLiteral("217 \"%1\" %2 %3 FILTERSTATE").arg(m_Outputdevice, l_Type, l_State); sendData(l_Send); } } else if (l_StringCode == QStringLiteral("DELETELOCALSTREAM")) { QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); } else if (l_StringCode == QStringLiteral("CHOOSESTREAMOVERVIEW")) { QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); //TODO send stream info for all chosen streams. } else if (l_StringCode == QStringLiteral("CHOOSEIMPORT")) { QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); //TODO send import state } else if (l_StringCode == QStringLiteral("RELEASEIMPORT")) { QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); } else if (l_StringCode == QStringLiteral("GETELOKALIST")) { QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); l_Send = QString::fromUtf8(u8"291 ELOKALIST"); sendData(l_Send); //TODO send eloka list l_Send = QString::fromUtf8(u8"295 ENDOFPARAMETERLIST"); sendData(l_Send); } else if (l_StringCode == QStringLiteral("RELEASEELOKA")) { QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); } else if (l_StringCode == QStringLiteral("QUERYELOKA")) { if (l_Parts.size() != 2) { replyBadArguments(); return; } int mode = l_Parts[1].toInt(); QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); // queryEloka 0 (Stop) will only be confirmed with OK, the server does not response with a list then. if (mode != 0) { l_Send = QString::fromUtf8(u8"294 QUERYELOKALIST"); sendData(l_Send); l_Send = QString::fromUtf8(u8"\"Eloka1\" \"Funk1\" 1 1255515414"); sendData(l_Send); l_Send = QString::fromUtf8(u8"299 ENDOFPARAMETERLIST"); sendData(l_Send); } } else if (l_StringCode == QStringLiteral("CHOOSESTREAM")) { if (l_Parts.size() >= 4) { QString l_Stream = QString::fromUtf8(l_Parts[1].trimmed()); m_SelectedStream = l_Stream; m_Audiomute = l_Parts[2].toInt(); m_Outputdevice = QString::fromUtf8(l_Parts[3].trimmed()); QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); if (m_SelectedStream == QString::fromUtf8(u8"Video 52-1(S)")) { m_Position = QDateTime::fromMSecsSinceEpoch(1255515414 * 1000LL + 860); l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1255515414.86 1255634077.89 118663.03 STREAMINFO")); } else if (m_SelectedStream == QString::fromUtf8(u8"Video 52-2(L)")) { m_Position = QDateTime::fromMSecsSinceEpoch(1255512414 * 1000LL + 860); l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1255515414.86 1255634077.89 118663.03 STREAMINFO")); } else if (m_SelectedStream == QString::fromUtf8(u8"Videöäü 50-5(S)")) { m_Position = QDateTime::fromMSecsSinceEpoch(1255512414 * 1000LL + 860); l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1255515414.86 1255634077.89 118663.03 STREAMINFO")); } else if (m_SelectedStream == QString::fromUtf8(u8"Video 3")) { m_Position = QDateTime::fromMSecsSinceEpoch(1234215414 * 1000LL + 860); l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1234215414.86 1235434077.89 1218663.03 STREAMINFO")); } else if (m_SelectedStream == QString::fromUtf8(u8"Video 4")) { m_Position = QDateTime::fromMSecsSinceEpoch(1234215414 * 1000LL + 860); l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1234215414.86 1234215524.89 110.03 STREAMINFO")); } else if (m_SelectedStream == QString::fromUtf8(u8"Audiostream 1")) { m_Position = QDateTime::fromMSecsSinceEpoch(1255512414 * 1000LL + 860); l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1255512414.86 1255634077.89 118663.03 STREAMINFO")); } else if (m_SelectedStream == QString::fromUtf8(u8"Audiostream 2")) { m_Position = QDateTime::fromMSecsSinceEpoch(1255515414 * 1000LL + 860); l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1255515414.86 1255634077.89 118663.03 STREAMINFO")); } else if (m_SelectedStream == QString::fromUtf8(u8"TrSpFuKr12")) { m_Position = QDateTime::fromMSecsSinceEpoch(1234215414 * 1000LL + 860); l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1234215414.86 1235434077.89 1218663.03 STREAMINFO")); } sendData(l_Send); l_Send = QString::fromUtf8(u8"221 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" %1.%2 STREAMPOS").arg(m_Position.toMSecsSinceEpoch() / 1000).arg(m_Position.toString(QStringLiteral("z")))); sendData(l_Send); l_Send = QString::fromUtf8(u8"222 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" %1 STREAMSPEED").arg(m_StreamSpeed)); sendData(l_Send); l_Send = QString::fromUtf8(u8"223 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" %1 STREAMSTATE").arg(m_StreamState)); sendData(l_Send); l_Send = QString::fromUtf8(u8"224 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" %1 %2 STREAMMODE").arg(m_SignalPause).arg(m_PlayMode)); sendData(l_Send); l_Send = QString::fromUtf8(u8"225 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" %1 STREAMAUDIOMUTE").arg(m_Audiomute)); sendData(l_Send); l_Send = QString::fromUtf8(u8"226 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1 STREAMAUDIOSTATE")); sendData(l_Send); } } else if (l_StringCode == QStringLiteral("RELEASESTREAM")) { if (l_Parts.size() >= 3) { QString l_Stream = QString::fromUtf8(l_Parts[1].trimmed()); m_Outputdevice = QString::fromUtf8(l_Parts[2].trimmed()); QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); l_Send = QString::fromUtf8(u8"223 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 0 STREAMSTATE")); sendData(l_Send); m_SelectedStream = QString(); m_Position = QDateTime(); } } else if (l_StringCode == QStringLiteral("STREAMCONTROL")) { if (l_Parts.size() >= 4) { QString l_Stream = QString::fromUtf8(l_Parts[1].trimmed()); m_Outputdevice = QString::fromUtf8(l_Parts[2].trimmed()); QString l_Type = QString::fromUtf8(l_Parts[3].trimmed()); qDebug() << "Streamcontrol " << m_Outputdevice << " Type " << l_Type; if (l_Type == QStringLiteral("PINT")) { if (l_Parts.size() >= 5) m_SignalPause = QString::fromUtf8(l_Parts[4].trimmed()); } else if (l_Type == QStringLiteral("START")) { if (l_Parts.size() >= 5) { int l_Speed = l_Parts[4].trimmed().toInt(); l_Speed < 0 ? m_ReversPlay = true : m_ReversPlay = false; m_StreamSpeed = l_Speed; if (m_PosUpdateTime != 0) m_PosUpdate->start(m_PosUpdateTime); else m_PosUpdate->start(1000); m_StreamState = 1; } } else if (l_Type == QStringLiteral("STOP")) { m_PosUpdate->stop(); m_StreamState = 0; } else if (l_Type == QStringLiteral("PAUSE")) { m_PosUpdate->stop(); m_StreamState = 2; } else if (l_Type == QStringLiteral("SPED")) { if (l_Parts.size() >= 5) { int l_Speed = l_Parts[4].trimmed().toInt(); //int l_Speed = (l_Sentences.at(i).section(' ', -1, -1)).toInt(); l_Speed < 0 ? m_ReversPlay = true : m_ReversPlay = false; m_StreamSpeed = l_Speed; qDebug() << "Spped is: " << m_StreamSpeed; } } else if (l_Type == QStringLiteral("STFW")) { } else if (l_Type == QStringLiteral("STRW")) { } else if (l_Type == QStringLiteral("POSA")) { if (l_Parts.size() >= 5) { QString l_Time = QString::fromUtf8(l_Parts[4].trimmed()); m_Position = avTimeToQDateTime(l_Time); } } else if (l_Type == QStringLiteral("POSR")) { if (l_Parts.size() >= 5) { int l_TimeInt = l_Parts[4].trimmed().toInt(); bool l_Neg = false; qDebug() << "Timeint " << l_TimeInt << " / " << l_Parts[4]; if (l_TimeInt < 0) l_Neg = true; QDateTime l_Time = QDateTime::fromMSecsSinceEpoch(std::abs(l_TimeInt) * 1000); qDebug() << "time is " << l_Time.toString(QStringLiteral("dd.MMM.yyyy hh:mm:ss.zzz")); qDebug() << "Pos old " << m_Position.toString(QStringLiteral("dd.MMM.yyyy hh:mm:ss.zzz")); const qint64 secs = l_Time.toMSecsSinceEpoch() / 1000; if (l_Neg) m_Position = m_Position.addSecs(-secs); else m_Position = m_Position.addSecs(secs); qDebug() << "Pos new " << m_Position.toString(QStringLiteral("dd.MMM.yyyy hh:mm:ss.zzz")); } } else if (l_Type == QStringLiteral("MODE")) { if (l_Parts.size() >= 5) { bool l_Mode = l_Parts[4].trimmed().toInt(); qDebug() << "Mode " << l_Mode; m_PlayMode = l_Mode; } } else if (l_Type == QStringLiteral("MUTE")) { if (l_Parts.size() >= 5) { m_Audiomute = (bool)l_Parts[4].trimmed().toInt(); qDebug() << "Audiomute " << m_Audiomute << " / " << l_Parts[4].trimmed(); } } else if (l_Type == QStringLiteral("POSU")) { if (l_Parts.size() >= 5) { m_PosUpdateTime = l_Parts[4].trimmed().toInt(); if (m_PosUpdateTime != 0) m_PosUpdate->start(m_PosUpdateTime); else m_PosUpdate->start(1000); } } QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); if (m_SelectedStream == QString::fromUtf8(u8"Video 52-1 (S)")) l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1255515414.86 1255634077.89 118663.03 STREAMINFO")); else if (m_SelectedStream == QString::fromUtf8(u8"Video 52-2 (L)")) l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1255512414.86 1255631077.89 118663.03 STREAMINFO")); else if (m_SelectedStream == QString::fromUtf8(u8"Videöäü 50-5 (S)")) l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1255512414.86 1255631077.89 118663.03 STREAMINFO")); else if (m_SelectedStream == QString::fromUtf8(u8"Video 3")) l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1234215414.86 1235434077.89 1218663.03 STREAMINFO")); else if (m_SelectedStream == QString::fromUtf8(u8"Video 4")) l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1234215414.86 1234215524.89 110.03 STREAMINFO")); else if (m_SelectedStream == QString::fromUtf8(u8"Audiostream 1")) l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1255512414.86 1255631077.89 118663.03 STREAMINFO")); else if (m_SelectedStream == QString::fromUtf8(u8"Audiostream 2")) l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1255515414.86 1255634077.89 118663.03 STREAMINFO")); else if (m_SelectedStream == QString::fromUtf8(u8"TrSpFuKr12")) l_Send = QString::fromUtf8(u8"220 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" 1234215414.86 1235434077.89 1218663.03 STREAMINFO")); sendData(l_Send); l_Send = QString::fromUtf8(u8"221 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" %1.%2 STREAMPOS").arg(m_Position.toMSecsSinceEpoch() / 1000).arg(m_Position.toString(QStringLiteral("z")))); sendData(l_Send); l_Send = QString::fromUtf8(u8"222 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" %1 STREAMSPEED").arg(m_StreamSpeed)); sendData(l_Send); l_Send = QString::fromUtf8(u8"223 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" %1 STREAMSTATE").arg(m_StreamState)); sendData(l_Send); l_Send = QString::fromUtf8(u8"224 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" %1 %2 STREAMMODE").arg(m_SignalPause).arg(m_PlayMode)); sendData(l_Send); l_Send = QString::fromUtf8(u8"225 \"%1\" \"%2\" ").arg(l_Stream, m_Outputdevice).append(QString::fromUtf8(u8" %1 STREAMAUDIOMUTE").arg(m_Audiomute)); sendData(l_Send); } } else if (l_StringCode == QStringLiteral("RELEASESCRIPT")) { if (l_Parts.size() >= 3) { QString l_Script = QString::fromUtf8(l_Parts[1]); m_Outputdevice = QString::fromUtf8(l_Parts[2]); QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); l_Send = QString::fromUtf8(u8"231 \"%1\" \"%2\" 0 SCRIPTSTATE").arg(l_Script, m_Outputdevice); sendData(l_Send); m_SelectedScript = QString(); //m_Position = QDateTime(); } } else if (l_StringCode == QStringLiteral("SETSCRIPT")) { if (l_Parts.size() >= 5) { m_Script = ScrEdAVScript(); m_PendingListReading = 1; QString l_Script = QString::fromUtf8(l_Parts[1].trimmed()); QString l_Category = QString::fromUtf8(l_Parts[2].trimmed()); m_Outputdevice = QString::fromUtf8(l_Parts[3].trimmed()); qDebug() << "Script is " << l_Script << " category is " << l_Category; m_Script.setName(l_Script); m_Script.setCategory(l_Category.toInt()); m_Script.setStartTime(QDateTime::fromMSecsSinceEpoch(0)); m_Script.setEndTime(QDateTime::fromMSecsSinceEpoch(0)); m_Script.setDuration(0); m_RelScriptPos = 0; m_AbsScriptPos = 0; m_ScriptState = 0; //Parse first part QByteArray l_StreamToParse = l_Parts[4].trimmed(); QList l_Parsed = parse(l_StreamToParse, 0); //Q_FOREACH(QString str, l_Parsed) qDebug() << "Parts = " << str; QString l_Name = QString::fromUtf8(l_Parsed[0].trimmed().replace("{", "").replace("}", "")); int l_Speed = l_Parsed[1].trimmed().toInt(); bool l_Mute = l_Parsed[2].trimmed().toInt(); QString l_StrBegin = QString::fromUtf8(l_Parsed[3].trimmed()); QDateTime l_Begin = avTimeToQDateTime(l_StrBegin); QString l_StrEnd = QString::fromUtf8(l_Parsed[4].trimmed()); QDateTime l_End = avTimeToQDateTime(l_StrEnd); bool l_Pint = l_Parsed[5].trimmed().toInt(); ScrEdAVStream l_Stream; l_Stream.setName(l_Name); l_Stream.setCategory(2); l_Stream.setSpeed(l_Speed); l_Stream.setMute(l_Mute); l_Stream.setStartTime(l_Begin); l_Stream.setEndTime(l_End); l_Stream.setSignalPauseHandling(l_Pint); l_Stream.setDuration(l_Stream.getStartTime().secsTo(l_Stream.getEndTime())); QVector m_Sequences = m_Script.getStreamSequences(); m_Sequences.push_back(l_Stream); m_Script.setStreamSequences(m_Sequences); m_Script.setEndTime(m_Script.getEndTime().addSecs(l_Stream.getStartTime().secsTo(l_Stream.getEndTime()))); m_Script.setDuration(m_Script.getDuration() + l_Stream.getStartTime().secsTo(l_Stream.getEndTime())); } } else if (l_StringCode == QStringLiteral("SCRIPTCONTROL")) { if (l_Parts.size() >= 4) { //end list reading if (m_PendingListReading == 1) { QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); l_Send = QString::fromUtf8(u8"230 \"%1\" \"%2\" %3 %4 %5 SCRIPTINFO").arg(m_Script.getName(), m_Outputdevice, qDateTimeToAVTime(m_Script.getStartTime()), qDateTimeToAVTime(m_Script.getEndTime()), floatToAVTime(m_Script.getDuration())); sendData(l_Send); l_Send = QString::fromUtf8(u8"231 \"%1\" \"%2\" %3 SCRIPTSTATE").arg(m_Script.getName(), m_Outputdevice).arg(m_ScriptState); sendData(l_Send); m_StreamNbr = 0; if (m_Script.getStreamSequences().size() > m_StreamNbr) m_SelStreamFromScript = m_Script.getStreamSequences().at(m_StreamNbr); QDateTime l_SendAbsPos = m_SelStreamFromScript.getStartTime().addSecs(m_RelScriptPos); l_Send = QString::fromUtf8(u8"233 \"%1\" \"%2\" \"%3\" %4 %5 SCRIPTPOS").arg(m_Script.getName(), m_Outputdevice, m_SelStreamFromScript.getName(), qDateTimeToAVTime(l_SendAbsPos), floatToAVTime(m_AbsScriptPos)); sendData(l_Send); m_PendingListReading = 0; } // QString l_Script = QString::fromUtf8(l_Parts[1].trimmed()); m_Outputdevice = QString::fromUtf8(l_Parts[2].trimmed()); QString l_Type = QString::fromUtf8(l_Parts[3].trimmed()); //qDebug() << "Scriptcontrol " << l_Device << " Type " << l_Type; if (l_Type == QStringLiteral("POSA")) { if (l_Parts.size() >= 5) { m_AbsScriptPos = avTimeToFloat(l_Parts[4].trimmed()); qDebug() << l_Parts[4].trimmed(); //check if absolute pos is in current played stream of script, and set corresponding stream as selected Stream QVectorIterator l_Iterator(m_Script.getStreamSequences()); float l_Duration = 0; while (l_Iterator.hasNext()) { ScrEdAVStream l_Stream = l_Iterator.next(); float l_OldDuration = l_Duration; l_Duration += l_Stream.getDuration(); //qDebug() << "l_Duration " << l_Duration.toString("hh:mm:ss") << " abspos " << m_AbsScriptPos.toString("hh:mm:ss") << " l_Stream = " << l_Stream.getName(); if (l_Duration > m_AbsScriptPos) { m_SelStreamFromScript = l_Stream; l_Iterator.toBack(); m_RelScriptPos = m_AbsScriptPos - l_OldDuration; qDebug() << "set stream 2" << l_Stream.getName() << " pos is " << m_RelScriptPos; //m_RelScriptPos = QDateTime::fromTime_t(0); } } } } else if (l_Type == QStringLiteral("START")) { if (l_Parts.size() >= 5) { int m_PosUpdateTime = l_Parts[4].trimmed().toInt(); m_ScriptPosUpdate->start(m_PosUpdateTime); m_ScriptState = 1; } } else if (l_Type == QStringLiteral("STOP")) { m_ScriptPosUpdate->stop(); m_ScriptState = 0; } else if (l_Type == QStringLiteral("PAUSE")) { m_ScriptPosUpdate->stop(); m_ScriptState = 2; } QString l_Send = QString::fromUtf8(u8"200 OK"); sendData(l_Send); l_Send = QString::fromUtf8(u8"230 \"%1\" \"%2\" %3 %4 %5 SCRIPTINFO").arg(m_Script.getName(), m_Outputdevice, qDateTimeToAVTime(m_Script.getStartTime()), qDateTimeToAVTime(m_Script.getEndTime()), floatToAVTime(m_Script.getDuration())); sendData(l_Send); l_Send = QString::fromUtf8(u8"231 \"%1\" \"%2\" %3 SCRIPTSTATE").arg(m_Script.getName(), m_Outputdevice).arg(m_ScriptState); sendData(l_Send); QDateTime l_SendAbsPos = m_SelStreamFromScript.getStartTime().addSecs(m_RelScriptPos); l_Send = QString::fromUtf8(u8"233 \"%1\" \"%2\" \"%3\" %4 %5 SCRIPTPOS").arg(m_Script.getName(), m_Outputdevice, m_SelStreamFromScript.getName(), qDateTimeToAVTime(l_SendAbsPos), floatToAVTime(m_AbsScriptPos)); sendData(l_Send); } } else if (l_StringCode == QStringLiteral("QUERYTIMELINE")) { QString streamName = QString::fromUtf8(l_Parts.at(1).trimmed()); replyOk(); QString cmd = QStringLiteral("297 \"%1\" TIMELINELIST"); sendData(cmd.arg(streamName)); sendData(QStringLiteral("1499415421.77-1499416659.03")); sendData(QStringLiteral("1499417373.77-1499417842.06")); sendData(QStringLiteral("299 ENDOFPARAMETERLIST")); } else if (m_PendingListReading == 1) { if (l_Parts.size() >= 1) { QByteArray l_StreamToParse = l_Parts[0].trimmed(); QList l_Parsed = parse(l_StreamToParse, 0); if (l_Parsed.size() >= 6) { QString l_Name = QString::fromUtf8(l_Parsed[0].trimmed().replace("{", "").replace("}", "")); int l_Speed = l_Parsed[1].trimmed().toInt(); bool l_Mute = l_Parsed[2].trimmed().toInt(); QDateTime l_Begin = avTimeToQDateTime(QString::fromUtf8(l_Parsed[3].trimmed())); QDateTime l_End = avTimeToQDateTime(QString::fromUtf8(l_Parsed[4].trimmed())); bool l_Pint = l_Parsed[5].trimmed().toInt(); ScrEdAVStream l_Stream; l_Stream.setName(l_Name); l_Stream.setCategory(2); l_Stream.setSpeed(l_Speed); l_Stream.setMute(l_Mute); l_Stream.setStartTime(l_Begin); l_Stream.setEndTime(l_End); l_Stream.setSignalPauseHandling(l_Pint); l_Stream.setDuration(l_Stream.getStartTime().secsTo(l_Stream.getEndTime())); QVector m_Sequences = m_Script.getStreamSequences(); m_Sequences.push_back(l_Stream); m_Script.setStreamSequences(m_Sequences); m_Script.setEndTime(m_Script.getEndTime().addSecs(l_Stream.getStartTime().secsTo(l_Stream.getEndTime()))); m_Script.setDuration(m_Script.getDuration() + l_Stream.getStartTime().secsTo(l_Stream.getEndTime())); } } } else { replyBadCommand(); } } float AvaTestServer::avTimeToFloat(const QByteArray &a_avTime) { int idx = a_avTime.indexOf('.'); if (idx < 0) return a_avTime.toULong(); const QByteArray s = a_avTime.left(idx); const QByteArray ms = a_avTime.mid(idx + 1); return s.toULong() + ms.toULong() / 1000.; } QDateTime AvaTestServer::avTimeToQDateTime(const QString &a_avTime) { const qint64 sec = a_avTime.section(QLatin1Char('.'), 0, 0).toInt(); const qint64 msec = a_avTime.section(QLatin1Char('.'), 1, 1).toInt(); return QDateTime::fromMSecsSinceEpoch(sec * 1000 + msec); } QString AvaTestServer::qDateTimeToAVTime(const QDateTime &a_qDateTime) { const qint64 sec = a_qDateTime.toMSecsSinceEpoch() / 1000; const qint64 msec = a_qDateTime.toMSecsSinceEpoch() % 1000; QString l_String = QString::number(sec) + QLatin1Char('.') + QString::number(msec); return l_String; } QString AvaTestServer::floatToAVTime(float a_time) { return QString::number(a_time, 'f', 4); } QList AvaTestServer::parse(const QByteArray &a_byteArray, int a_i) { QList l_Array; const char *p = a_byteArray.constData() + a_i; const int l_Length = a_byteArray.length(); const char *p_end = a_byteArray.constData() + l_Length; if (l_Length <= a_i) return l_Array; while (*p && p < p_end) { while (isspace(*p)) ++p; if (*p && p < p_end) { //Remove additional end brackets if (*p == '}') ++p; else { bool l_Escaped = false; bool l_Quoted = (*p == '\"'); bool l_Bracketed = (*p == '{'); if (l_Quoted) ++p; //Remove additional entry brackets.... else if (l_Bracketed) { ++p; while (*p == '{') ++p; } const char *start = p; while (true) { if (l_Quoted) { while (p < p_end && *p != (l_Quoted ? '\"' : ' ')) ++p; } else if (l_Bracketed) { while (p < p_end && *p != (l_Bracketed ? '}' : ' ')) ++p; } else { while (p < p_end && *p != ' ') ++p; } if (l_Quoted || l_Bracketed) { // escaped '\"' ? if (* (p - 1) == '\\') { ++p; l_Escaped = true; continue; } } QByteArray l_Result = QByteArray(start, p - start); if (l_Escaped) l_Result = l_Result.replace("\\\"", "\""); l_Array += l_Result; ++p; break; } } } } return l_Array; } void AvaTestServer::sendData(const QString &data_) { static const QString EOL = QStringLiteral("\r\n"); qDebug() << "Outgoing RCP_AVA: " << data_; QString data = data_; data.append(EOL); QVectorIterator l_It(m_Conns); while (l_It.hasNext()) { QTcpSocket *l_Conn = l_It.next(); if (l_Conn->state() == QAbstractSocket::ConnectedState) { //qDebug() << "sent to conn " << l_Conn; l_Conn->write(data.toUtf8()); } } } void AvaTestServer::replyOk() { sendData(QStringLiteral("200 OK")); } void AvaTestServer::replyBadArguments() { sendData(QStringLiteral("402 BAD ARGUMENTS")); } void AvaTestServer::replyBadCommand() { sendData(QStringLiteral("400 BAD COMMAND")); } void AvaTestServer::replyCommandNotAllowed() { sendData(QStringLiteral("405 COMMAND NOT ALLOWED")); } } // namespace AudioVideoManagement