/** * @RDE_HEADER@ * AvaControl * $Id$ * $HeadURL$ * $Author$ * Created by Christian Fröbel, SLSE, 2017-06-26 */ #include "ava_control.h" #include "iava_comm.h" #include "ava_types.h" #include "AvsCommands/simple_command.h" #include "AvsCommands/choose_stream.h" #include "AvsCommands/choose_stream_overview.h" #include "AvsCommands/get_stream_list.h" #include "AvsCommands/query_timeline.h" #include "AvsCommands/get_eloka_list.h" #include "AvsCommands/query_eloka.h" #include "AvsCommands/set_script.h" #include "AvsCommands/start_script.h" #include "AvsCommands/set_rt_profile.h" #include "AvsCommands/change_rt_profile_circuit_name.h" #include "AvsCommands/set_rt_profile_base.h" #include "AvsCommands/set_announcement_profile.h" #include "AvsCommands/set_video_profile.h" #include "AvsCommands/set_abs_position.h" #include "AvsCommands/set_volume.h" #include "AvsCommands/keep_alive.h" #include #include #include #include #include #include namespace AudioVideoManagement { AvaControl::AvaControl(IAvaComm *comm, StreamNameMapping *streamNameMapping, std::chrono::milliseconds commandTimeout) : m_comm(comm) , m_streamNameMapping(streamNameMapping) , m_queue(commandTimeout) , m_logger(getLogger("AvaControl")) { Q_ASSERT(comm); Q_ASSERT(streamNameMapping); connect(comm, &IAvaComm::connected, this, &AvaControl::onConnected); connect(comm, &IAvaComm::disconnected, this, &AvaControl::onDisconnected); connect(&m_queue, &AvsCommandQueue::queueEmpty, this, &AvaControl::commandQueueEmpty); // signal -> signal connect(&m_queue, &AvsCommandQueue::timeout, this, &AvaControl::onTimeout); } void AvaControl::switchContext(int exerciseId) { queue(new AvaCommands::SimpleCommand(QLatin1String("SwitchContext"), m_comm, this, [ = ](IAvaComm * comm) { comm->switchContext(exerciseId); })); } void AvaControl::setUserProfile(const QString &userName, const QString &langCode, AvaAudioPrio audioPrio, AvaGuiStyle style) { queue(new AvaCommands::SimpleCommand(QLatin1String("SetUserProfile"), m_comm, this, [ = ](IAvaComm * comm) { comm->setUserProfile(userName, langCode, audioPrio, style); })); } void AvaControl::setTimezone(QChar tz) { queue(new AvaCommands::SimpleCommand(QLatin1String("SetTimezone"), m_comm, this, [ = ](IAvaComm * comm) { comm->setTimezone(tz); })); } void AvaControl::setVideoDialogProfile(const QString &dialogId, AvaVisibility visibility) { const int OK_COUNT = 2; queue(new AvaCommands::SimpleCommand(QLatin1String("SetVideoDialogProfile"), m_comm, this, [ = ](IAvaComm * comm) { comm->setVideoDialogProfile(dialogId, visibility); }, OK_COUNT)); } void AvaControl::setVideoDialogGeometry(const QString &dialogId, const QRect &geometry) { const int OK_COUNT = 2; queue(new AvaCommands::SimpleCommand(QLatin1String("SetVideoDialogGeometry"), m_comm, this, [ = ](IAvaComm * comm) { comm->setVideoDialogGeometry(dialogId, geometry); }, OK_COUNT)); } void AvaControl::setVideoProfile(const QString &dialogId, const QString &menuDef) { setVideoProfile(dialogId, menuDef, new LtsUtils::DummyConnection); } void AvaControl::setVideoProfile(const QString &dialogId, const QString &menuDef, LtsUtils::IConnection *connection) { queue(new AvaCommands::SetVideoProfile(m_comm, this, dialogId, menuDef), connection); } void AvaControl::setRtProfile(RtState *rtState, const QVector &radioCircuits) { setRtProfile(rtState, radioCircuits, new LtsUtils::DummyConnection); } void AvaControl::setRtProfile(RtState *rtState, const QVector &radioCircuits, LtsUtils::IConnection *connection) { queue(new AvaCommands::SetRtProfile(m_comm, this, rtState, radioCircuits), connection); } void AvaControl::changeRtProfileCircuitName(RtState *rtState, const RtState::RadioCircuit &radioCircuit) { changeRtProfileCircuitName(rtState, radioCircuit, new LtsUtils::DummyConnection); } void AvaControl::changeRtProfileCircuitName(RtState *rtState, const RtState::RadioCircuit &radioCircuit, LtsUtils::IConnection *connection) { queue(new AvaCommands::ChangeRtProfileCircuitName(m_comm, this, rtState, radioCircuit), connection); } void AvaControl::setAnnouncementProfile(RtState *rtState, const QString &menuDef, const QString &identityList, const QString &stateList) { setAnnouncementProfile(rtState, menuDef, identityList, stateList, new LtsUtils::DummyConnection); } void AvaControl::setAnnouncementProfile(RtState *rtState, const QString &menuDef, const QString &identityList, const QString &stateList, LtsUtils::IConnection *connection) { queue(new AvaCommands::SetAnnouncementProfile(m_comm, this, rtState, menuDef, identityList, stateList), connection); } void AvaControl::getStreamList(AvaStreamType streamType, AvaStreamSource streamSource) { getStreamList(streamType, streamSource, new LtsUtils::DummyConnection); } void AvaControl::getStreamList(AvaStreamType streamType, AvaStreamSource streamSource, LtsUtils::IConnection *connection) { queue(new AvaCommands::GetStreamList(m_comm, this, streamType, streamSource, m_streamNameMapping), connection); } void AvaControl::chooseStream(const QString &dialogId, const QString &streamName) { queue(new AvaCommands::ChooseStream(m_comm, this, dialogId, streamName)); } void AvaControl::chooseStreamOverview(const QString &dialogId, const QStringList &streamNames) { const bool notMuted = false; queue(new AvaCommands::ChooseStreamOverview(m_comm, this, dialogId, streamNames, notMuted)); } void AvaControl::releaseStream(const QString &dialogId, const QString &streamName) { queue(new AvaCommands::SimpleCommand(QLatin1String("ReleaseStream"), m_comm, this, [ = ](IAvaComm * comm) { comm->releaseStream(dialogId, streamName); })); } void AvaControl::queryTimeline(const QString &streamName, const boost::optional &start, const boost::optional &end) { queryTimeline(streamName, new LtsUtils::DummyConnection, start, end); } void AvaControl::queryTimeline(const QString &streamName, LtsUtils::IConnection *connection, const boost::optional &start, const boost::optional &end) { queue(new AvaCommands::QueryTimeline(m_comm, this, streamName, start, end), connection); } void AvaControl::getElokaList(const QString &streamName, LtsUtils::IConnection *connection) { queue(new AvaCommands::GetElokaList(m_comm, this, streamName), connection); } void AvaControl::setVolume(int db) { queue(new AvaCommands::SetVolume(m_comm, this, db)); } void AvaControl::startStream(const QString &dialogId, const QString &streamName, AvaSpeed speed) { queue(new AvaCommands::SimpleCommand(QLatin1String("StartStream"), m_comm, this, [ = ](IAvaComm * comm) { comm->startStream(dialogId, streamName, speed); })); } void AvaControl::stopStream(const QString &dialogId, const QString &streamName) { queue(new AvaCommands::SimpleCommand(QLatin1String("StopStream"), m_comm, this, [ = ](IAvaComm * comm) { comm->stopStream(dialogId, streamName); })); } void AvaControl::pauseStream(const QString &dialogId, const QString &streamName) { queue(new AvaCommands::SimpleCommand(QLatin1String("PauseStream"), m_comm, this, [ = ](IAvaComm * comm) { comm->pauseStream(dialogId, streamName); })); } void AvaControl::setStreamSpeed(const QString &dialogId, const QString &streamName, AvaSpeed speed) { queue(new AvaCommands::SimpleCommand(QLatin1String("SetStreamSpeed"), m_comm, this, [ = ](IAvaComm * comm) { comm->setStreamSpeed(dialogId, streamName, speed); })); } void AvaControl::setAbsPosition(const QString &dialogId, const QString &streamName, AvaTimePoint pos) { queue(new AvaCommands::SetAbsPosition(m_comm, this, dialogId, streamName, pos)); } void AvaControl::positionUpdate(const QString &dialogId, const QString &streamName, std::chrono::milliseconds updateInterval) { queue(new AvaCommands::SimpleCommand(QLatin1String("PositionUpdate"), m_comm, this, [ = ](IAvaComm * comm) { comm->positionUpdate(dialogId, streamName, updateInterval); })); } void AvaControl::setPint(const QString &dialogId, const QString &streamName, bool doSkip) { queue(new AvaCommands::SimpleCommand(QLatin1String("SetPint"), m_comm, this, [ = ](IAvaComm * comm) { comm->setPint(dialogId, streamName, doSkip); })); } void AvaControl::getElokaList(const QString &streamName) { getElokaList(streamName, new LtsUtils::DummyConnection); } void AvaControl::chooseEloka(const QString &streamName, const QString &signalName, AvaElokaMode mode) { queue(new AvaCommands::SimpleCommand(QLatin1String("ChooseEloka"), m_comm, this, [ = ](IAvaComm * comm) { comm->chooseEloka(streamName, signalName, mode); })); } void AvaControl::releaseEloka(const QString &streamName) { queue(new AvaCommands::SimpleCommand(QLatin1String("ReleaseEloka"), m_comm, this, [ = ](IAvaComm * comm) { comm->releaseEloka(streamName); })); } void AvaControl::queryEloka(AvaQueryElokaMode mode) { // queryEloka 0 (aka Stop) is a SimpleCommad; there is no QueryElokaList-response then if (mode == AvaQueryElokaMode::Stop) queue(new AvaCommands::SimpleCommand(QLatin1String("QueryEloka"), m_comm, this, [ = ](IAvaComm * comm) { comm->queryEloka(mode); })); else queryEloka(mode, new LtsUtils::DummyConnection); } void AvaControl::queryEloka(AvaQueryElokaMode mode, LtsUtils::IConnection *connection) { queue(new AvaCommands::QueryEloka(m_comm, this, mode), connection); } void AvaControl::chooseImport(const QString &dialogId, const QString &path, int mode) { queue(new AvaCommands::SimpleCommand(QLatin1String("ChooseImport"), m_comm, this, [ = ](IAvaComm * comm) { comm->chooseImport(dialogId, path, mode); })); } void AvaControl::releaseImport(const QString &dialogId) { queue(new AvaCommands::SimpleCommand(QLatin1String("ReleaseImport"), m_comm, this, [ = ](IAvaComm * comm) { comm->releaseImport(dialogId); })); } void AvaControl::setScript(const QString &dialogId, const QString &scriptName, AvaScriptSource source, const QVector &streams, LtsUtils::IConnection *connection) { queue(new AvaCommands::SetScript(m_comm, this, dialogId, scriptName, source, streams), connection); } void AvaControl::releaseScript(const QString &dialogId, const QString &scriptName) { queue(new AvaCommands::SimpleCommand(QLatin1String("ReleaseScript"), m_comm, this, [ = ](IAvaComm * comm) { comm->releaseScript(dialogId, scriptName); })); } void AvaControl::startScript(const QString &dialogId, const QString &scriptName, LtsUtils::IConnection *connection) { queue(new AvaCommands::StartScript(m_comm, this, dialogId, scriptName, connection != nullptr), connection); } void AvaControl::stopScript(const QString &dialogId, const QString &scriptName) { queue(new AvaCommands::SimpleCommand(QLatin1String("StopScript"), m_comm, this, [ = ](IAvaComm * comm) { comm->stopScript(dialogId, scriptName); })); } void AvaControl::pauseScript(const QString &dialogId, const QString &scriptName) { queue(new AvaCommands::SimpleCommand(QLatin1String("PauseScript"), m_comm, this, [ = ](IAvaComm * comm) { comm->pauseScript(dialogId, scriptName); })); } void AvaControl::setAbsPositionScript(const QString &dialogId, const QString &scriptName, AvaTimePoint pos) { queue(new AvaCommands::SimpleCommand(QLatin1String("SetAbsPositionScript"), m_comm, this, [dialogId, scriptName, pos](IAvaComm * comm) { comm->setAbsPositionScript(dialogId, scriptName, pos); })); } void AvaControl::defineStreamNameMapping(const QString &internalName, const QString &displayName) { queue(new AvaCommands::SimpleCommand(QLatin1String("DefineStreamNameMapping"), m_comm, this, [ = ](IAvaComm * comm) { comm->defineStreamNameMapping(internalName, displayName); })); } void AvaControl::resetStreamNameMapping() { queue(new AvaCommands::SimpleCommand(QLatin1String("ResetStreamNameMapping"), m_comm, this, [ = ](IAvaComm * comm) { comm->resetStreamNameMapping(); })); } void AvaControl::keepAlive() { queue(new AvaCommands::KeepAlive(m_comm, this)); } void AvaControl::onConnected() { m_connected = true; DEBUG_LOG(m_logger) << "connected"; } void AvaControl::onDisconnected() { m_connected = false; DEBUG_LOG(m_logger) << "disconnected"; m_queue.flush(); } void AvaControl::onTimeout() { ICommand *cmd = m_queue.currentCommand(); if (cmd->canTimeout()) { INFO_LOG(m_logger) << "command '" << cmd->debug() << "' failed"; m_queue.done(); return; } ERROR_LOG(m_logger) << "command timed out"; failed(cmd); } void AvaControl::queue(ICommand *cmd, LtsUtils::IConnection *connection) { std::unique_ptr cmd_(cmd); std::unique_ptr connection_(connection); if (!m_connected) { DEBUG_LOG(m_logger) << "not connected -> dropping command"; return; } m_queue.queue(std::move(cmd_), std::move(connection_)); } /** * Default fallback for all commands that don't require special action * upon completion such as emitting a signal. */ void AvaControl::done(ICommand *cmd) { Q_ASSERT(cmd == m_queue.currentCommand()); m_queue.done(); } void AvaControl::done(AvaCommands::ChooseStream *cmd) { Q_ASSERT(cmd == m_queue.currentCommand()); emit chooseStreamResponse(cmd->streamInfo(), cmd->streamState()); m_queue.done(); } void AvaControl::done(AvaCommands::GetStreamList *cmd) { Q_ASSERT(cmd == m_queue.currentCommand()); { LtsUtils::ScopedConnection scopedConn(m_queue.currentConnection()); emit getStreamListResponse(cmd->streams()); } // extra small scope as done() deletes the instance scopedConn is operating on m_queue.done(); } void AvaControl::done(AvaCommands::QueryTimeline *cmd) { Q_ASSERT(cmd == m_queue.currentCommand()); { LtsUtils::ScopedConnection scopedConn(m_queue.currentConnection()); emit queryTimelineResponse(cmd->timeline()); } // extra small scope as done() deletes the instance scopedConn is operating on m_queue.done(); } void AvaControl::done(AvaCommands::GetElokaList *cmd) { Q_ASSERT(cmd == m_queue.currentCommand()); { LtsUtils::ScopedConnection scopedConn(m_queue.currentConnection()); emit getElokaListResponse(cmd->elokaSignals()); } // extra small scope as done() deletes the instance scopedConn is operating on m_queue.done(); } void AvaControl::done(AvaCommands::QueryEloka *cmd) { Q_ASSERT(cmd == m_queue.currentCommand()); { LtsUtils::ScopedConnection scopedConn(m_queue.currentConnection()); emit queryElokaResponse(cmd->eloka()); } // extra small scope as done() deletes the instance scopedConn is operating on m_queue.done(); } void AvaControl::done(AvaCommands::SetScript *cmd) { Q_ASSERT(cmd == m_queue.currentCommand()); if (m_queue.currentHasConnection()) { LtsUtils::ScopedConnection scopedConn(m_queue.currentConnection()); emit setScriptResponse(cmd->scriptInfo(), cmd->scriptState()); } // extra small scope as done() deletes the instance scopedConn is operating on m_queue.done(); } void AvaControl::done(AvaCommands::StartScript *cmd) { Q_ASSERT(cmd == m_queue.currentCommand()); if (m_queue.currentHasConnection()) { LtsUtils::ScopedConnection scopedConn(m_queue.currentConnection()); emit startScriptResponse(cmd->scriptState()); } // extra small scope as done() deletes the instance scopedConn is operating on m_queue.done(); } void AvaControl::done(AvaCommands::SetVideoProfile *cmd) { Q_ASSERT(cmd == m_queue.currentCommand()); { LtsUtils::ScopedConnection scopedConn(m_queue.currentConnection()); emit setVideoProfileResponse(cmd->invalidNameList()); } // extra small scope as done() deletes the instance scopedConn is operating on m_queue.done(); } void AvaControl::done(AvaCommands::SetRtProfileBase *cmd) { Q_ASSERT(cmd == m_queue.currentCommand()); { LtsUtils::ScopedConnection scopedConn(m_queue.currentConnection()); emit setRtProfileResponse(cmd->invalidNameList()); } // extra small scope as done() deletes the instance scopedConn is operating on m_queue.done(); } void AvaControl::done(AvaCommands::SetAnnouncementProfile *cmd) { Q_ASSERT(cmd == m_queue.currentCommand()); { LtsUtils::ScopedConnection scopedConn(m_queue.currentConnection()); emit setAnnouncementProfileResponse(cmd->invalidNameList()); } // extra small scope as done() deletes the instance scopedConn is operating on m_queue.done(); } void AvaControl::failed(AvaCommands::SetScript *cmd) { Q_ASSERT(cmd == m_queue.currentCommand()); if (m_queue.currentHasConnection()) { LtsUtils::ScopedConnection scopedConn(m_queue.currentConnection()); emit setScriptResponse(AvaStreamInfo(), AvaStreamState::NotPossible); } // extra small scope as done() deletes the instance scopedConn is operating on } void AvaControl::failed(ICommand *cmd) { ERROR_LOG(m_logger) << "command '" << cmd->debug() << "' failed"; Q_ASSERT(cmd == m_queue.currentCommand()); auto cmdSetScript = dynamic_cast(cmd); if (cmdSetScript) failed(cmdSetScript); m_queue.flush(); m_comm->forceDisconnect(); } void AvaControl::alive(ICommand *cmd) { Q_ASSERT(cmd == m_queue.currentCommand()); m_queue.alive(); } } // namespace AudioVideoManagement