/** * @RDE_HEADER@ * AvsSessionContext * $Id$ * $HeadURL$ * $Author$ * Created by Christian Fröbel, SLSE, 2017-08-03 */ #pragma once #include #include #include #include namespace OperatorManagement { namespace Interface { class Dtc; } } namespace AudioVideoManagement { namespace Interface { class Dtc; } class AvaSession; class AvaState; class StreamNameMapping; class AvsMenus; class VdSession; class AvmExerciseContextHandle; class AvsApp; class PlaybackApp; /** * AvsSessionContext ensures that there can only be one communication * channel to AVS_Workstation and AVS_Export with a defined exercise context at * any given time. * AvsSessionContext must not be used with the global exercise (exerciseId 0). * * The application can have many users of the communication channels at the same time. * The reason for this is that the AvmDataPlugin will be instantiated for every * exercise (also live and replay) and possibly multiple times for an exercise. * All these users shall share the same communication channels. * But all parallel users must use the same exercise context. * * AvsSessionContext creates the communication channels (AvaSession, VdSession) when the first user * calls acquire(). Subsequent users can get access to the same channels by also * calling acquire() -- but the exercise context must match. * When a user no longer needs these communication channels it calls release(). * When all users released the communication channels, they will be deleted. * After that another user can call acquire() with a different exercise context. * * Use AvsSessionContextHandle to automatically acquire() and release() * the communication channel. * * See AvmExerciseContext for a visualization of lifetimes of Apps, PluginInterface-instances * and ExerciseContext. * * @see AvmExerciseContext * @author Christian Fröbel */ class AvsSessionContext { public: /** * Small helper struct that holds all parts that make up a session. * Only useful for AvsSessionContextHandle in order to access those parts. */ struct Composite; AvsSessionContext(); ~AvsSessionContext(); /** * Check whether a AvsSessionContext with the given exerciseId can be acquired. * Yields true when no AvsSessionContext was created yet or when the currently active * AvsSessionContext is for the same exericse. */ bool canAcquire(int exerciseId) const; /** * Need not to be called directly; use AvsSessionContextHandle instead. */ ///@{ Composite *acquire(int exerciseId, int operatorId, const QString &langCode, AvaGuiStyle, const AvmExerciseContextHandle &exerciseContextHandle); void release(Composite *composite); ///@} private: std::unique_ptr m_composite; int m_refCount{0}; }; /** * Helper class to automatically call AvsSessionContext::acquire() * and AvsSessionContext::release() in the ctor and dtor respectively. * Instances can be moved but not copied. */ class AvsSessionContextHandle { public: AvsSessionContextHandle() = default; AvsSessionContextHandle(AvsSessionContext *context, int exerciseId, int operatorId, const QString &langCode, AvaGuiStyle, const AvmExerciseContextHandle &exerciseContextHandle); operator bool() const { return m_composite.get(); } AvaSession *avaSession() const; AvaState *avaState() const; AvsMenus *menus() const; VdSession *vdSession() const; AvsApp *liveVideoApp() const; PlaybackApp *videoPlaybackApp() const; PlaybackApp *audioPlaybackApp() const; PlaybackApp *videoPresentationApp() const; PlaybackApp *audioPresentationApp() const; private: using Releaser = std::function; std::unique_ptr m_composite; }; } // namespace AudioVideoManagement