/** * @RDE_HEADER@ * ListResponseCollector * $Id$ * $HeadURL$ * $Author$ * Created by Christian Fröbel, NLE, 2018-12-18 */ #pragma once #include "iava_comm.h" #include "ava_types.h" #include "avm_export.h" #include #include #include #include class QString; class QByteArray; namespace AudioVideoManagement { class StreamNameMapping; /** * Internal helper class for ListResponseCollector. * * @author Christian Fröbel */ template class ListResponseCollectorHelper { public: using DoneCallback = std::function; using AliveCallback = std::function; ListResponseCollectorHelper(IAvaComm *comm, const DoneCallback &doneCallback, const ElementFactory &elementFactory = {}); /** * @param aliveCallback may be empty, i.e. no callback given. */ ListResponseCollectorHelper(IAvaComm *comm, const DoneCallback &doneCallback, const AliveCallback &aliveCallback, const ElementFactory &elementFactory = {}); /** * Connect to the signals and start collecting; stop after the list was collected. * May be called again when the doneCallback was called. */ void start(); void reset(); private: void onListValueReceived(const QVector &parts); void onEndOfListReceived(); QObject m_hint; //!< used to control the lifetime of the signal-to-lambda connections IAvaComm *m_comm; DoneCallback m_doneCallback; AliveCallback m_aliveCallback; ElementFactory m_elementFactory; bool m_started{false}; ResultContainer m_elements; unsigned m_elementCount{0}; }; /** * Template class for collecting the list responses on the RCP_AVA interface to AVS_Workstation. * * It works ontop of IAvaComm. It connects to the following three signals: * - a list-specific signal that marks the begin of the list, e.g. IAvaComm::invalidNameListBeginReceived() * - IAvaComm::listValueReceived(const QVector &parts) * - IAvaComm::endOfListReceived() * The first list-specific signal must be specified as 2nd template parameter. * The 3rd template parameter is a factory functor that creates an element of type T * from the parts as signalled by IAvaComm::listValueReceived(). * As a result a QVector is built where T is the 1st template parameter. * When the list response is finished the DoneCallback given to the constructor will be called. * * The user does not need to specify the template parameters himself. * There are predefined type aliases for the different types of list responses. * * For the list response of QueryTimeline there exists a separate collector-class: TimelineListCollector * * @see StreamListCollector * @see InvalidNameListCollector * @see ElokaListCollector * @see QueryElokaListCollector * @see TimelineListCollector * * @author Christian Fröbel */ template class ListResponseCollector { private: using Helper = ListResponseCollectorHelper, ElementFactory>; public: using DoneCallback = typename Helper::DoneCallback; ListResponseCollector(IAvaComm *comm, const DoneCallback &doneCallback, const ElementFactory &elementFactory = ElementFactory{}); /** * Connect to the signals and start collecting; stop after the list was collected. * May be called again when the doneCallback was called. */ void start(); /** * Reset the collector. * Can be useful in case the connection to AVS breaks in the middle of receiving a list. */ void reset(); private: void onBeginOfListReceived(); void onDone(QVector &&result); QObject m_hint; IAvaComm *m_comm; DoneCallback m_doneCallback; bool m_started{false}; Helper m_helper; }; struct AVM_COMMON_EXPORT TimelineListElementFactory { AvaTimelinePart operator()(const QVector &parts) const; }; /** * A special collector-implementation for the list-reponse of QueryTimeline. * The reason for this is that the list-begin-signal takes a parameter (IAvaComm::timelineListBegin(const QString&)) * and thus we cannot use the generalized ListCollector. * * The result as passed to the DoneCallback is an AvaTimeline. * * @author Christian Fröbel */ class AVM_COMMON_EXPORT TimelineListCollector { private: using Helper = ListResponseCollectorHelper; public: using DoneCallback = typename Helper::DoneCallback; using AliveCallback = typename Helper::AliveCallback; /** * @param aliveCallback may be empty, i.e. no callback given. */ TimelineListCollector(IAvaComm *comm, const QString &streamName, const DoneCallback &doneCallback, const AliveCallback &aliveCallback); /** * Connect to the signals and start collecting; stop after the list was collected. * May be called again when the doneCallback was called. */ void start(); private: void onBeginOfListReceived(const QString &streamName); void onDone(AvaTimeline &&timeline); QObject m_hint; IAvaComm *m_comm; const QString m_streamName; DoneCallback m_doneCallback; bool m_started{false}; Helper m_helper; }; class StreamListElementFactory { public: StreamListElementFactory(AvaStreamType streamType, AvaStreamSource streamSource, StreamNameMapping *streamNameMapping); AvaStream operator()(const QVector &parts) const; private: const AvaStreamType m_streamType; const AvaStreamSource m_streamSource; StreamNameMapping *m_streamNameMapping; }; struct InvalidNameListElementFactory { QString operator()(const QVector &parts) const; }; using ElokaListElementFactory = InvalidNameListElementFactory; struct QueryElokaListElementFactory { AvaEloka operator()(const QVector &parts) const; }; /** @name Concrete collector types. */ ///@{ using StreamListCollector = ListResponseCollector; using InvalidNameListCollector = ListResponseCollector; using ElokaListCollector = ListResponseCollector; using QueryElokaListCollector = ListResponseCollector; ///@} } // namespace AudioVideoManagement