/** * @RDE_HEADER@ * AudioVideoHandler * $Id$ * $HeadURL$ * $Author$ * Created by Christian Fröbel, SLSE, 2017-11-27 */ #include "audio_video_handler.h" #include "audio_video_handler_impl.h" #include "asset.h" #include "mounting_point.h" #include "exercise_handler.h" #include "default_av_menus.h" #include #include #include #include #include #include namespace AudioVideoManagement { /** * All DB-operations are done via this class in order to keep an internal cache * that mirrors the entries in the DB. * Initially there are no entries as the ExercisesHandler removes all * device-related entries from the DB. */ class AudioVideoHandler::DbProxy : public AudioVideoHandlerImpl::IDbProxy { public: explicit DbProxy(DatabaseInterface *db) : m_db(db) { Q_ASSERT(db); } const Streams &findStreams(AssetId id) const override { auto found = m_cache.find(id); Q_ASSERT(found != m_cache.end()); return found->second; } const Streams &findStreams(Asset *asset) override { Q_ASSERT(asset); return findStreams(asset->data().id()); } void insert(Streams &streams) override { Q_ASSERT(streams.first.id <= 0); m_db->insert(streams.first); if (streams.second) { Q_ASSERT(streams.second->id <= 0); streams.second->link = streams.first.id; m_db->insert(*streams.second); streams.first.link = streams.second->id; m_db->update(streams.first); } auto insertResult = m_cache.insert(std::make_pair(streams.assetId(), streams)); Q_ASSERT(insertResult.second); } void update(Streams &newStreams) override { Q_ASSERT(newStreams.first.id <= 0); Q_ASSERT(!newStreams.second || newStreams.second->id <= 0); auto found = m_cache.find(newStreams.assetId()); Q_ASSERT(found != m_cache.end()); const Streams oldStreams = found->second; // The update of the Asset can also imply that an additional stream will be created // or that one stream will be removed. if (!oldStreams.second && !newStreams.second) { // no change, one stream newStreams.first.id = oldStreams.first.id; m_db->update(newStreams.first); } else if (oldStreams.second && newStreams.second) { // no change, two streams newStreams.first.id = oldStreams.first.id; newStreams.first.link = oldStreams.first.link; newStreams.second->id = oldStreams.second->id; newStreams.second->link = oldStreams.second->link; m_db->update(newStreams.first); m_db->update(*newStreams.second); } else if (!oldStreams.second && newStreams.second) { // one additional stream newStreams.second->link = oldStreams.first.id; m_db->insert(*newStreams.second); newStreams.first.id = oldStreams.first.id; newStreams.first.link = newStreams.second->id; m_db->update(newStreams.first); } else { // one stream removed newStreams.first.id = oldStreams.first.id; m_db->update(newStreams.first); m_db->removeAvmDeviceConfig(oldStreams.second->id); } found->second = newStreams; // update cache } void remove(Asset *asset) override { Q_ASSERT(asset); auto found = m_cache.find(asset->data().id()); Q_ASSERT(found != m_cache.end()); const Streams &streams = found->second; m_db->removeAvmDeviceConfig(streams.first.id); if (streams.second) m_db->removeAvmDeviceConfig(streams.second->id); m_cache.erase(found); } private: std::map m_cache; DatabaseInterface *m_db; }; class AudioVideoHandler::DtsProxy : public AudioVideoHandlerImpl::IDtsProxy { public: DtsProxy(Interface::Dts *dts, DefaultAvMenus *defaultAvMenus) : m_dts(dts) , m_defaultAvMenus(defaultAvMenus) { Q_ASSERT(dts); Q_ASSERT(defaultAvMenus); } void publish(const Stream &stream) override { m_defaultAvMenus->onStreamChanged(stream); m_dts->publish(stream); } void remove(uint64_t streamId) override { m_defaultAvMenus->onStreamRemoved(streamId); m_dts->removeStreamByKey(streamId); } private: Interface::Dts *m_dts; DefaultAvMenus *m_defaultAvMenus; }; AudioVideoHandler::AudioVideoHandler(Exercise *exercise, ExerciseHandler *exerciseHandler, DefaultAvMenus *defaultAvMenus, DatabaseInterface *db, Interface::Dts *dts) : m_dbProxy(new DbProxy(db)) , m_dtsProxy(new DtsProxy(dts, defaultAvMenus)) , m_impl(new AudioVideoHandlerImpl(exercise, m_dbProxy.get(), m_dtsProxy.get())) { Q_ASSERT(exerciseHandler); connect(m_impl.get(), &AudioVideoHandlerImpl::avDbReloadNeeded, this, &AudioVideoHandler::avDbReloadNeeded); connect(exerciseHandler, &ExerciseHandler::contextActivated, m_impl.get(), &AudioVideoHandlerImpl::onContextActivated); connect(exerciseHandler, &ExerciseHandler::contextDeactivated, m_impl.get(), &AudioVideoHandlerImpl::onContextDeactivated); } AudioVideoHandler::~AudioVideoHandler() = default; } // namespace AudioVideoManagement