/** * Exercises Handler - checks the avilable exercises * $Id$ * $HeadURL$ * $Author$ * Created by Christian Ehrlicher, SLSE, 2016-04-14 */ #include "exercises_handler.h" #include "dds_handler.h" #include "dds_handler_exercise.h" #include "main_handler.h" #include "exercise_handler.h" #include "audio_video_handler.h" #include "import_handler.h" #include "exercise_context.h" #include "asset_assignment_manager.h" #include "exercise.h" #include "default_av_menus.h" #include #include namespace AudioVideoManagement { /** * Small composite class that holds all parts we need for an exercise. */ class ExercisesHandler::ExerciseParts { public: ExerciseParts(MainHandler *mainHandler, Exercise *exercise) : m_ddsHandler(new DdsHandlerExercise(mainHandler->ddsHandler()->domainParticipant(), exercise->context().id())) , m_exerciseHandler(new ExerciseHandler(mainHandler, exercise->context().id())) , m_defaultAvMenus(new DefaultAvMenus(exercise->context(), m_ddsHandler->dts(), mainHandler->videoTeamHandler(), mainHandler->ddsHandler()->ismDtc())) , m_audioVideoHandler(new AudioVideoHandler(exercise, m_exerciseHandler.get(), m_defaultAvMenus.get(), mainHandler->db(), m_ddsHandler->dts())) , m_importHandler(ImportHandler::create(m_exerciseHandler.get(), mainHandler->db(), mainHandler->ddsHandler()->asmDtc())) {} ExerciseHandler *exerciseHandler() const { return m_exerciseHandler.get(); } AudioVideoHandler *audioVideoHandler() const { return m_audioVideoHandler.get(); } ImportHandler *importHandler() const { return m_importHandler.get(); } private: std::unique_ptr m_ddsHandler; std::unique_ptr m_exerciseHandler; std::unique_ptr m_defaultAvMenus; std::unique_ptr m_audioVideoHandler; std::unique_ptr m_importHandler; }; ExercisesHandler::ExercisesHandler(MainHandler *mainHandler) : m_mainHandler(mainHandler) , m_triggerAvUpdateTimer(new QTimer(this)) , m_assetAssignmentManager(AssetAssignmentManager::create(mainHandler->ddsHandler()->ismDtc())) , m_logger(getLogger("ExercisesHandler")) { m_triggerAvUpdateTimer->setSingleShot(true); m_triggerAvUpdateTimer->setInterval(1000); connect(m_triggerAvUpdateTimer, &QTimer::timeout, m_mainHandler->avControl(), &AVControl::triggerAVUpdate); } ExercisesHandler::~ExercisesHandler() = default; bool ExercisesHandler::init() { const auto cbLastSeen = [this] (const Database::AvmExerciseLastSeen &lastSeen) { createExerciseHandlerFromLastSeen(lastSeen); }; if (!db()->select(cbLastSeen)) return false; // Don't use select with callback here as the callback (body of for-loop below) would use the DB, too. QVector avmDeviceConfig; if (!db()->select(avmDeviceConfig)) return false; DBTransaction trans(db()->database()); for (const Database::AvmDeviceConfig &dc : qAsConst(avmDeviceConfig)) { // nur hinzufuegen, wenn es record/replay session ist // alle anderen -> aus DB loeschen if (dc.type != ExerciseHandler::avTypeRecordSession() && dc.type != ExerciseHandler::avTypePlaybackSession()) { db()->removeAvmDeviceConfig(dc.id); continue; } const int exerciseId = ExerciseContext::fromString(dc.context).id(); ExerciseHandler *exH = getOrCreateExerciseHandler(exerciseId); exH->addDeviceConfig(dc); } trans.commit(); connect(exmDtc(), &ExerciseManagement::Interface::Dtc::exerciseChanged, this, &ExercisesHandler::onExerciseChanged); DEBUG_LOG(m_logger) << LOGFUNCTION << " done"; return true; } void ExercisesHandler::exerciseModified(int exerciseId, const ExerciseManagement::ExerciseState &state) { ExerciseHandler *exH = getOrCreateExerciseHandler(exerciseId); exH->setNewExerciseState(state); } void ExercisesHandler::onExerciseChanged(const ExerciseManagement::Exercise &data, DataModification modType) { switch (modType) { case DataModification::eAdded: case DataModification::eModified: exerciseModified(data.id(), data.state()); break; case DataModification::eRemoved: // nothing to do here // The removal of an exercise is handled by the corresponding ExerciseHandler itself. // see ExerciseHandler::onLastSeenTimerTimeout() break; } } ExerciseHandler *ExercisesHandler::exerciseHandler(int exerciseId) const { auto it = m_exercises.find(exerciseId); if (it == m_exercises.end()) return nullptr; else return it->second.exerciseHandler(); } AudioVideoHandler *ExercisesHandler::audioVideoHandler(int exerciseId) const { auto it = m_exercises.find(exerciseId); if (it == m_exercises.end()) return nullptr; else return it->second.audioVideoHandler(); } void ExercisesHandler::onAvDbReloadNeeded() { m_triggerAvUpdateTimer->start(); } void ExercisesHandler::createExerciseHandlerFromLastSeen(const Database::AvmExerciseLastSeen &lastSeen) { ExerciseHandler *exH = createExerciseHandler(ExerciseContext::fromString(lastSeen.context).id()); exH->setLastSeen(lastSeen); } ExerciseHandler *ExercisesHandler::getOrCreateExerciseHandler(int exerciseId) { ExerciseHandler *exH = exerciseHandler(exerciseId); if (exH) return exH; else return createExerciseHandler(exerciseId); } ExerciseHandler *ExercisesHandler::createExerciseHandler(int exerciseId) { DEBUG_LOG(m_logger) << "Creating handler for exercise " << exerciseId; ExerciseParts parts(m_mainHandler, m_assetAssignmentManager->exercise(exerciseId)); ExerciseHandler *exH = parts.exerciseHandler(); AudioVideoHandler *avH = parts.audioVideoHandler(); ImportHandler *impH = parts.importHandler(); auto insertResult = m_exercises.insert(std::make_pair(exerciseId, std::move(parts))); Q_ASSERT(insertResult.second); connect(exH, &ExerciseHandler::removeMeImFinished, this, &ExercisesHandler::exerciseFinished, Qt::QueuedConnection); connect(exH, &ExerciseHandler::contextActivated, this, [this, exH] { emit contextActivated(exH->context()); }); connect(exH, &ExerciseHandler::contextDeactivated, this, [this, exH] { emit contextDeactivated(exH->context()); }); connect(exH, &ExerciseHandler::avDbReloadNeeded, this, &ExercisesHandler::onAvDbReloadNeeded); connect(avH, &AudioVideoHandler::avDbReloadNeeded, this, &ExercisesHandler::onAvDbReloadNeeded); connect(impH, &ImportHandler::avDbReloadNeeded, this, &ExercisesHandler::onAvDbReloadNeeded); return exH; } void ExercisesHandler::exerciseFinished(int exerciseId) { auto count = m_exercises.erase(exerciseId); Q_ASSERT(count == 1); m_assetAssignmentManager->removeExercise(exerciseId); } DatabaseInterface *ExercisesHandler::db() { return m_mainHandler->db(); } ExerciseManagement::Interface::Dtc *ExercisesHandler::exmDtc() { return m_mainHandler->ddsHandler()->exmDtc(); } } // namespace AudioVideoManagement