/** * @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 #include #include #include #include #include #include #include #include namespace { std::set mountingPointsOfInterest(const InfrastructureManagement::MainStructureElement &building) { std::set 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 allEntries; const auto &buildings = m_ismDtc->mainStructureElements(); for (const auto &building : buildings) { m_buildingDisplayNameForId[building.id()] = getDisplayNameForBuilding(building); std::vector 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 DefaultAvMenus::subMenuForBuilding(const InfrastructureManagement::MainStructureElement &building, bool isAudio) { std::vector entries; std::vector 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 DefaultAvMenus::streamsForBuilding(const InfrastructureManagement::MainStructureElement &building, bool isAudio) { std::set mountingPoints = mountingPointsOfInterest(building); std::vector 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