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

281 lines
7.6 KiB
C++
Executable File

/**
* @RDE_HEADER@
* DefaultAvMenus
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Fröbel, NLSE, 2018-03-14
*/
#include "default_av_menus.h"
#include "exercise.h"
#include "object_video_team.h"
#include "audio_video_handler_impl.h"
#include <AudioVideoManagement/avm.hpp>
#include <AudioVideoManagement/avm_dts.h>
#include <AudioVideoManagement/handler_menu_struct.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <QTimer>
#include <QtGlobal>
#include <set>
#include <algorithm>
#include <iterator>
namespace
{
std::set<int32_t> mountingPointsOfInterest(const InfrastructureManagement::MainStructureElement &building)
{
std::set<int32_t> mountingPoints;
for (const auto &se : building.elements())
{
if (se.structureElementTypeId() != InfrastructureManagement::StructureElementType::MountingPoint)
continue;
if (se.mountingPointTypeId() == InfrastructureManagement::MountingPointType::AnnouncementUnit ||
se.mountingPointTypeId() == InfrastructureManagement::MountingPointType::IndoorCamera ||
se.mountingPointTypeId() == InfrastructureManagement::MountingPointType::OutdoorCamera)
mountingPoints.insert(se.id());
}
return mountingPoints;
}
bool isStreamOfInterest(const AudioVideoManagement::Stream &stream, bool isAudio)
{
using AudioVideoManagement::StreamType;
switch (stream.type().underlying())
{
case StreamType::Video:
return !isAudio;
case StreamType::AudioIn:
return false;
case StreamType::AudioOut:
case StreamType::AudioInOut:
return isAudio;
}
Q_ASSERT(false);
return false;
}
} // anonymous namespace
namespace AudioVideoManagement
{
DefaultAvMenus::DefaultAvMenus(const ExerciseContext &context, Interface::Dts *dts, HandlerVideoTeam *handlerVideoTeams, InfrastructureManagement::Interface::Dtc *ismDtc)
: m_context(context)
, m_dts(dts)
, m_videoTeamHandler(handlerVideoTeams)
, m_ismDtc(ismDtc)
, m_timer(new QTimer)
, m_logger(getLogger("DefaultAvMenus"))
, m_isInitialized(false)
{
Q_ASSERT(dts);
Q_ASSERT(ismDtc);
if(!m_ismDtc->isMainStructureElementEnabled())
m_ismDtc->enableMainStructureElement();
m_timer->setInterval(1000);
m_timer->setSingleShot(true);
connect(m_videoTeamHandler, &HandlerVideoTeam::mvsChanged, this, &DefaultAvMenus::onStreamMvsChanged);
connect(m_timer.get(), &QTimer::timeout, this, &DefaultAvMenus::updateMenus);
m_timer->start();
}
DefaultAvMenus::~DefaultAvMenus() = default;
void DefaultAvMenus::onStreamChanged(const Stream &stream)
{
m_streams[stream.id()] = stream;
m_timer->start();
}
void DefaultAvMenus::onStreamMvsChanged()
{
m_timer->start();
}
void DefaultAvMenus::onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data, DataModification modType)
{
QString buildingDisplayName = getDisplayNameForBuilding(data);
if(modType == DataModification::eRemoved)
{
m_buildingDisplayNameForId.remove(data.id());
m_timer->start();
}
else if(modType == DataModification::eAdded)
{
m_buildingDisplayNameForId[data.id()] = buildingDisplayName;
m_timer->start();
}
else
{
if(m_buildingDisplayNameForId.value(data.id(),buildingDisplayName) == buildingDisplayName)
return;
m_buildingDisplayNameForId[data.id()] = buildingDisplayName;
m_timer->start();
}
}
void DefaultAvMenus::onStreamRemoved(int32_t streamId)
{
auto removeCount = m_streams.erase(streamId);
Q_ASSERT(removeCount == 1);
m_timer->start();
}
void DefaultAvMenus::updateMenus()
{
updateMenu(true); // isAudio
updateMenu(false); // !isAudio = Video
}
void DefaultAvMenus::removeMenus()
{
m_dts->removeMenuStructByKey(menuStructId(true)); // isAudio
m_dts->removeMenuStructByKey(menuStructId(false)); // !isAudio = Video
}
void DefaultAvMenus::updateMenu(bool isAudio)
{
MenuStruct menu;
menu.id(menuStructId(isAudio));
menu.isDefault(true);
menu.name("Default");
menu.isAudio(isAudio);
std::vector<AvMenuEntry> allEntries;
const auto &buildings = m_ismDtc->mainStructureElements();
for (const auto &building : buildings)
{
m_buildingDisplayNameForId[building.id()] = getDisplayNameForBuilding(building);
std::vector<AvMenuEntry> subMenu = subMenuForBuilding(building, isAudio);
std::move(subMenu.begin(), subMenu.end(), std::back_inserter(allEntries));
}
if (!isAudio)
{
bool addMenu = false;
AvMenuEntry mvsStreams;
mvsStreams.id(1000000);
mvsStreams.parentId(menuStructId(isAudio));
mvsStreams.name().set("MVS");
mvsStreams.isGroup(true);
const auto &videoTeams = m_videoTeamHandler->videoTeams();
for (const auto &videoTeam : videoTeams)
{
if (videoTeam.exerciseId() != m_context.id())
continue;
addMenu = true;
AvMenuEntry streamEntry;
streamEntry.id(videoTeam.id());
streamEntry.parentId(mvsStreams.id());
streamEntry.mountingPointId(-1*videoTeam.id());
// Also set the stream name which makes it easier for the clients.
streamEntry.name().set(videoTeam.streamName());
streamEntry.isGroup(false);
allEntries.push_back(streamEntry);
// What about the rowId?
}
if (addMenu)
{
allEntries.push_back(mvsStreams);
}
}
menu.menuEntries(allEntries);
HandlerMenuStruct::sortEntries(menu);
m_dts->publish(menu);
if(!m_isInitialized)
{
connect(m_ismDtc, &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged, this, &DefaultAvMenus::onMainStructureElementChanged);
m_isInitialized = true;
}
}
QString DefaultAvMenus::getDisplayNameForBuilding(const InfrastructureManagement::MainStructureElement &data)
{
for (auto structure : data.elements()) {
if(structure.structureElementTypeId() == InfrastructureManagement::StructureElementType::Building)
return QString::fromStdString(structure.displayName());
}
return QString::fromStdString(data.name());
}
std::vector<AvMenuEntry> DefaultAvMenus::subMenuForBuilding(const InfrastructureManagement::MainStructureElement &building, bool isAudio)
{
std::vector<AvMenuEntry> entries;
std::vector<Stream> streams = streamsForBuilding(building, isAudio);
if (streams.empty())
return entries;
entries.reserve(streams.size() + 1);
AvMenuEntry buildingEntry;
buildingEntry.id(building.id());
buildingEntry.parentId(menuStructId(isAudio));
buildingEntry.name(getDisplayNameForBuilding(building).toStdString());
buildingEntry.isGroup(true);
// What about the rowId?
entries.push_back(buildingEntry);
for (const auto &stream : streams)
{
AvMenuEntry streamEntry;
streamEntry.id(stream.mountingPointId());
streamEntry.parentId(buildingEntry.id());
streamEntry.mountingPointId(stream.mountingPointId());
// Also set the stream name which makes it easier for the clients.
streamEntry.name().set(AudioVideoHandlerImpl::internalStreamName(stream.mountingPointId()).toStdString());
streamEntry.isGroup(false);
// What about the rowId?
entries.push_back(streamEntry);
}
return entries;
}
std::vector<Stream> DefaultAvMenus::streamsForBuilding(const InfrastructureManagement::MainStructureElement &building, bool isAudio)
{
std::set<int32_t> mountingPoints = mountingPointsOfInterest(building);
std::vector<Stream> streams;
for (const auto &keyValue : m_streams)
{
const Stream &stream = keyValue.second;
if (!isStreamOfInterest(stream, isAudio))
continue;
if (!mountingPoints.count(stream.mountingPointId()))
continue;
streams.push_back(stream);
}
return streams;
}
int32_t DefaultAvMenus::menuStructId(bool isAudio)
{
return m_context.id() + (isAudio ? 20000000 : 10000000);
}
} // namespace AudioVideoManagement