Files
2026-10-03 09:20:13 +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 <QtCore/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)
{
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_logger(getLogger("DefaultAvMenus"))
, m_isInitialized(false)
, m_context(context)
, m_dts(dts)
, m_videoTeamHandler(handlerVideoTeams)
, m_ismDtc(ismDtc)
, m_timer(new QTimer)
{
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 = "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 = 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 = 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