Files
qt5-legatus-legacy/Lts/Services/AudioVideoManagement/ava_control.cpp
T
2026-08-13 18:33:10 +02:00

470 lines
17 KiB
C++
Executable File

/**
* @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 <LtsUtilsCore/scoped_connection.h>
#include <QTimer>
#include <QRect>
#include <QtGlobal>
#include <chrono>
#include <QDebug>
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<RtState::RadioCircuit> &radioCircuits)
{
setRtProfile(rtState, radioCircuits, new LtsUtils::DummyConnection);
}
void AvaControl::setRtProfile(RtState *rtState, const QVector<RtState::RadioCircuit> &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<AvaTimePoint> &start, const boost::optional<AvaTimePoint> &end)
{
queryTimeline(streamName, new LtsUtils::DummyConnection, start, end);
}
void AvaControl::queryTimeline(const QString &streamName, LtsUtils::IConnection *connection, const boost::optional<AvaTimePoint> &start, const boost::optional<AvaTimePoint> &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<AvaScriptEntry> &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<ICommand> cmd_(cmd);
std::unique_ptr<LtsUtils::IConnection> 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<AvaCommands::SetScript*>(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