/** * @RDE_HEADER@ * StreamNameMapping * $Id$ * $HeadURL$ * $Author$ * Created by Christian Fröbel, NLSE, 2018-03-12 */ #include "stream_name_mapping.h" #include "audio_video_handler_impl.h" #include #include #include #include #include namespace { /** * Same as in AudioVideoHandlerImpl::internalStreamName() but only used as a fallback * in case someone requests a name for an unknown MountingPoint. * * This would not be needed if we could rely on consistent data. */ QString fallbackStreamName(int mountingPointId) { return AudioVideoManagement::AudioVideoHandlerImpl::internalStreamName(mountingPointId); } } // anonymous namespace namespace AudioVideoManagement { StreamNameMapping *StreamNameMapping::create(Interface::Dtc *dtc) { Q_ASSERT(dtc); StreamNameMapping *mapping = new StreamNameMapping; QObject::connect(dtc, &Interface::Dtc::streamNameChanged, mapping, &StreamNameMapping::onStreamNameChanged); dtc->streamNames([mapping](const StreamName & streamName) { mapping->onStreamNameChanged(streamName, DataModification::eAdded); }); return mapping; } QString StreamNameMapping::internalName(int32_t mountingPointId) const { const auto &found = m_mpToNames.find(mountingPointId); if (found != m_mpToNames.end()) return found->second.internal; // We can never be sure that DDS-based data is consistent. // In case someone refers to a MountingPoint that either does not exist anymore // or for which the mapping was not yet published, we supply a fallback stream name. return fallbackStreamName(mountingPointId); } QString StreamNameMapping::displayName(int32_t mountingPointId) const { const auto &found = m_mpToNames.find(mountingPointId); if (found != m_mpToNames.end()) return found->second.display; return fallbackStreamName(mountingPointId); } QString StreamNameMapping::internalName(const QString &displayName) { for (const auto &keyValue : m_mpToNames) if (keyValue.second.display == displayName) return keyValue.second.internal ; return (displayName); } QString StreamNameMapping::displayName(const QString &internalName) const { bool matched = m_extractor.exactMatch(internalName); const QString effectiveStreamName = matched ? m_extractor.cap(1) : internalName; const QString sourceSpecifier = matched ? m_extractor.cap(2) : QString(); const auto &found = m_internalToDisplay.find(effectiveStreamName); if (found == m_internalToDisplay.end()) return internalName; // no translation return found->second + sourceSpecifier; } std::vector StreamNameMapping::allNames() const { std::vector names; names.reserve(m_mpToNames.size()); for (const auto &keyValue : m_mpToNames) names.push_back(keyValue.second); return names; } void StreamNameMapping::onStreamNameChanged(const StreamName &streamName, DataModification modType) { switch (modType) { case DataModification::eAdded: case DataModification::eModified: define(streamName.mountingPointId(), {QString::fromStdString(streamName.internalName()), QString::fromStdString(streamName.displayName())}); return; case DataModification::eRemoved: remove(streamName.mountingPointId()); return; } Q_ASSERT(false); } void StreamNameMapping::define(int32_t mountingPointId, const StreamNameMapping::Names &names) { m_mpToNames[mountingPointId] = names; m_internalToDisplay[names.internal] = names.display; emit changed(mountingPointId, names.internal, names.display); } void StreamNameMapping::remove(int32_t mountingPointId) { const auto found = m_mpToNames.find(mountingPointId); Q_ASSERT(found != m_mpToNames.end()); // sometimes we get a double remove during logout so make sure we don't crash here if (found == m_mpToNames.end()) return; const Names &names = found->second; QString internalName = names.internal; size_t removeCount = m_internalToDisplay.erase(names.internal); Q_ASSERT(removeCount == 1); m_mpToNames.erase(found); emit changed(mountingPointId, internalName, internalName); } } // namespace AudioVideoManagement