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

230 lines
7.6 KiB
C++
Executable File

/**
* @RDE_HEADER@
* ListResponseCollector
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Fröbel, NLE, 2018-12-18
*/
#include "list_response_collector.h"
#include "av_helper.h"
#include <QString>
#include <QByteArray>
#include <QtGlobal>
namespace AudioVideoManagement
{
template<class ResultContainer, class ElementFactory>
ListResponseCollectorHelper<ResultContainer, ElementFactory>::ListResponseCollectorHelper(IAvaComm *comm, const DoneCallback &doneCallback, const ElementFactory &elementFactory)
: ListResponseCollectorHelper(comm, doneCallback, AliveCallback{}, elementFactory)
{
}
template<class ResultContainer, class ElementFactory>
ListResponseCollectorHelper<ResultContainer, ElementFactory>::ListResponseCollectorHelper(IAvaComm *comm, const DoneCallback &doneCallback, const AliveCallback &aliveCallback, const ElementFactory &elementFactory)
: m_comm(comm)
, m_doneCallback(doneCallback)
, m_aliveCallback(aliveCallback)
, m_elementFactory(elementFactory)
{
Q_ASSERT(comm);
Q_ASSERT(doneCallback);
}
template<class ResultContainer, class ElementFactory>
void ListResponseCollectorHelper<ResultContainer, ElementFactory>::start()
{
using namespace std::placeholders;
Q_ASSERT(!m_started);
QObject::connect(m_comm, &IAvaComm::listValueReceived, &m_hint, std::bind(&ListResponseCollectorHelper::onListValueReceived, this, _1));
QObject::connect(m_comm, &IAvaComm::endOfListReceived, &m_hint, std::bind(&ListResponseCollectorHelper::onEndOfListReceived, this));
m_started = true;
}
template<class ResultContainer, class ElementFactory>
void ListResponseCollectorHelper<ResultContainer, ElementFactory>::reset()
{
m_comm->disconnect(&m_hint);
m_elements.clear();
m_elementCount = 0;
m_started = false;
}
template<class ResultContainer, class ElementFactory>
void ListResponseCollectorHelper<ResultContainer, ElementFactory>::onListValueReceived(const QVector<QByteArray> &parts)
{
m_elements.append(m_elementFactory(parts));
++m_elementCount;
// In case the list reponse is very long, e.g. for queryTimeline,
// we tell the issuer that we are still alive.
if (m_elementCount % 1000 == 0 && m_aliveCallback)
m_aliveCallback();
}
template<class ResultContainer, class ElementFactory>
void ListResponseCollectorHelper<ResultContainer, ElementFactory>::onEndOfListReceived()
{
using std::swap;
m_comm->disconnect(&m_hint);
ResultContainer result;
swap(result, m_elements);
m_started = false;
m_doneCallback(std::move(result));
}
//======================================================================================================================
template<class T, void (IAvaComm::*listBeginSignal)(), class ElementFactory>
ListResponseCollector<T, listBeginSignal, ElementFactory>::ListResponseCollector(IAvaComm *comm, const DoneCallback &doneCallback, const ElementFactory &elementFactory)
: m_comm(comm)
, m_doneCallback(doneCallback)
, m_helper(comm, [this] (QVector<T> &&result) { onDone(std::move(result)); }, elementFactory)
{
Q_ASSERT(comm);
Q_ASSERT(doneCallback);
}
template<class T, void (IAvaComm::*listBeginSignal)(), class ElementFactory>
void ListResponseCollector<T, listBeginSignal, ElementFactory>::start()
{
Q_ASSERT(!m_started);
QObject::connect(m_comm, listBeginSignal, &m_hint, std::bind(&ListResponseCollector::onBeginOfListReceived, this));
m_started = true;
}
template<class T, void (IAvaComm::*listBeginSignal)(), class ElementFactory>
void ListResponseCollector<T, listBeginSignal, ElementFactory>::reset()
{
m_helper.reset();
m_comm->disconnect(&m_hint);
m_started = false;
}
template<class T, void (IAvaComm::*listBeginSignal)(), class ElementFactory>
void ListResponseCollector<T, listBeginSignal, ElementFactory>::onBeginOfListReceived()
{
m_helper.start();
}
template<class T, void (IAvaComm::*listBeginSignal)(), class ElementFactory>
void ListResponseCollector<T, listBeginSignal, ElementFactory>::onDone(QVector<T> &&result)
{
m_comm->disconnect(&m_hint);
m_started = false;
m_doneCallback(std::move(result));
}
//======================================================================================================================
TimelineListCollector::TimelineListCollector(IAvaComm *comm, const QString &streamName, const TimelineListCollector::DoneCallback &doneCallback, const AliveCallback &aliveCallback)
: m_comm(comm)
, m_streamName(streamName)
, m_doneCallback(doneCallback)
, m_helper(comm, [this] (AvaTimeline &&timeline) { onDone(std::move(timeline)); }, aliveCallback)
{
Q_ASSERT(comm);
Q_ASSERT(doneCallback);
}
void TimelineListCollector::start()
{
using namespace std::placeholders;
Q_ASSERT(!m_started);
QObject::connect(m_comm, &IAvaComm::timelineListBeginReceived, &m_hint, std::bind(&TimelineListCollector::onBeginOfListReceived, this, _1));
m_started = true;
}
void TimelineListCollector::onBeginOfListReceived(const QString &streamName)
{
Q_ASSERT(streamName == m_streamName);
m_helper.start();
}
void TimelineListCollector::onDone(AvaTimeline &&timeline)
{
m_started = false;
m_comm->disconnect(&m_hint);
m_doneCallback(std::move(timeline));
}
//======================================================================================================================
StreamListElementFactory::StreamListElementFactory(AvaStreamType streamType, AvaStreamSource streamSource, StreamNameMapping *streamNameMapping)
: m_streamType(streamType)
, m_streamSource(streamSource)
, m_streamNameMapping(streamNameMapping)
{
Q_ASSERT(streamNameMapping);
}
AvaStream StreamListElementFactory::operator()(const QVector<QByteArray> &parts) const
{
Q_ASSERT(parts.size() == 3);
bool couldConvert = false;
AvaStreamType streamType = static_cast<AvaStreamType>(parts.at(0).toInt(&couldConvert));
Q_ASSERT(couldConvert);
Q_ASSERT(streamType == m_streamType);
AvaStreamSource streamSource = static_cast<AvaStreamSource>(parts.at(1).toInt(&couldConvert));
Q_ASSERT(couldConvert);
Q_ASSERT(streamSource == m_streamSource);
QString internalName = QString::fromUtf8(parts.at(2));
return AvaStream::create(streamType, streamSource, internalName, m_streamNameMapping);
}
QString InvalidNameListElementFactory::operator()(const QVector<QByteArray> &parts) const
{
Q_ASSERT(parts.size() == 1);
return QString::fromUtf8(parts.at(0));
}
AvaEloka QueryElokaListElementFactory::operator()(const QVector<QByteArray> &parts) const
{
Q_ASSERT(parts.size() == 4);
AvaEloka eloka;
eloka.signal = QString::fromUtf8(parts.at(0));
eloka.stream = QString::fromUtf8(parts.at(1));
eloka.priority = parts.at(2).toInt();
eloka.time = createTimePoint(parts.at(3));
return eloka;
}
AvaTimelinePart TimelineListElementFactory::operator()(const QVector<QByteArray> &parts) const
{
Q_ASSERT(parts.size() == 1);
QList<QByteArray> intervalParts = parts.front().split('-');
Q_ASSERT(intervalParts.size() == 2);
AvaTimePoint start = createTimePoint(intervalParts.at(0));
AvaTimePoint end = createTimePoint(intervalParts.at(1));
return {start, end};
}
/**
* Explicit template instantiations.
*/
///@{
template class AVM_COMMON_EXPORT ListResponseCollector<AvaStream, &IAvaComm::streamListBeginReceived, StreamListElementFactory>;
template class AVM_COMMON_EXPORT ListResponseCollector<QString, &IAvaComm::invalidNameListBeginReceived, InvalidNameListElementFactory>;
template class AVM_COMMON_EXPORT ListResponseCollector<QString, &IAvaComm::elokaListBeginReceived, ElokaListElementFactory>;
template class AVM_COMMON_EXPORT ListResponseCollector<AvaEloka, &IAvaComm::queryElokaListBeginReceived, QueryElokaListElementFactory>;
///@}
} // namespace AudioVideoManagement