Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+40
View File
@@ -0,0 +1,40 @@
#
# @RDE_HEADER@
# $Id$
# $HeadURL$
# $Author$
# Created by Christian Fröbel, NLSE, 2018-04-19
#
set(SRCS
avs_app.cpp
avs_app.h
playback_app.cpp
playback_app.h
plugin_settings.cpp
plugin_settings.h
project_settings.cpp
project_settings.h
stream_list_result.h
stream_list_result.cpp
)
#
# Shared Lib used by several Plugins.
# It has a dependency to LtsMultiMonitor and thus cannot be integrated into svcAvmCommon
# which needs to be built on SV, too.
#
NGL_ADD_LIBRARY2(WS AvmShared SHARED ${SRCS})
NGL_TARGET_LINK_LIBRARIES(AvmShared
PUBLIC
Qt5::Core
svcAvmCommon
Boost::boost
PRIVATE
LtsMultiMonitor
LtsUtilsSettings
Qt5::Gui
nglsettings
ngltools
)
NGL_INSTALL_TARGET(AvmShared)
+217
View File
@@ -0,0 +1,217 @@
/**
* @RDE_HEADER@
* AvsApp
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Fröbel, NLSE, 2018-04-16
*/
#include "avs_app.h"
#include <AudioVideoManagement/ava_control.h>
#include <LtsMultiMonitor/lts_dummy_widget.h>
#include <LtsMultiMonitor/lts_multi_monitor.h>
#include <QGuiApplication>
#include <QScreen>
#include <QPoint>
#include <QtGlobal>
#include <QDebug>
namespace
{
QScreen* screenAt(const QPoint &pos)
{
const auto screens = QGuiApplication::screens();
for (auto screen : screens)
if (screen->geometry().contains(pos))
return screen;
return QGuiApplication::primaryScreen();
}
QRect screenGeometryOf(const QPoint &pos)
{
// QScreen *screen = QGuiApplication::screenAt(pos); // since Qt 5.10
QScreen *screen = screenAt(pos);
return screen->geometry();
}
} // anonymous namespace
namespace AudioVideoManagement
{
const QString AvsApp::ALL_STREAMS = QStringLiteral("*");
AvsApp::AvsApp(const QString &dialogId, AvaControl *avaControl)
: m_dialogId(dialogId)
, m_avaControl(avaControl)
, m_visible(false)
{
Q_ASSERT(avaControl);
}
AvsApp::~AvsApp()
{
if (m_screenPlacementHelper)
m_screenPlacementHelper->deleteLater();
}
void AvsApp::show(const QVector<QWidget *> irreplacableWidgets)
{
qWarning() << "AvsApp::show";
Q_ASSERT(!m_presetGeometry);
if (m_screenPlacementHelper)
return;
m_screenPlacementHelper = new LtsMultiMonitor::FullscreenVideoDummyWidget;
connect(m_screenPlacementHelper, &LtsMultiMonitor::FullscreenVideoDummyWidget::signalWidgetPlaced, this, &AvsApp::onWidgetPlaced);
connect(m_screenPlacementHelper, &LtsMultiMonitor::FullscreenVideoDummyWidget::signalHideVideo, this, &AvsApp::onHideVideo);
connect(m_screenPlacementHelper, &LtsMultiMonitor::FullscreenVideoDummyWidget::signalShowVideo, this, &AvsApp::onShowVideo);
connect(m_screenPlacementHelper, &LtsMultiMonitor::FullscreenVideoDummyWidget::destroyed, this, &AvsApp::onPlacementHelperDestroyed);
LtsMultiMonitor::LtsMultiMonitor::getInstance()->selectScreen(m_screenPlacementHelper, nullptr, false, true /* ltsScreenNormalOnly */, irreplacableWidgets);
}
void AvsApp::show(const QRect &geometry)
{
qWarning() << "AvsApp::show (direct)";
showAvsDialog(geometry);
m_presetGeometry = geometry;
}
void AvsApp::hide(bool andClose)
{
qWarning() << "AvsApp::hide";
hideAvsDialog();
if (m_presetGeometry)
{
m_presetGeometry.reset();
qWarning() << "AvsApp::hide (with preset geo)";
// return;
}
// videos can now be hidden by swapping from main to secondary in mmm, so don't delete the helper - it might tell us to re-show the video later
// now wait until screen placement helper was destroyed by, so don't set m_screenPlacementHelper to 0 yet
if (andClose && m_screenPlacementHelper != nullptr)
m_screenPlacementHelper->deleteLater();
}
bool AvsApp::isVisible() const
{
return m_visible;
}
bool AvsApp::isActive() const
{
return isVisible() || (m_screenPlacementHelper != nullptr);
}
void AvsApp::releaseStreams()
{
m_avaControl->releaseStream(m_dialogId, ALL_STREAMS);
}
/**
* @param geometry is null in case we're not in MultiMonitorMode.
*/
void AvsApp::onWidgetPlaced(const QRect &geometry)
{
// In Multi-Monitor-Mode geometry is not Null.
// But the given geometry does not cover the whole screen; some space for bordering is subtracted.
// Thus we determine the screen geometry ourselves.
// In Windowed-Mode we simply pass a Null-QRect to showAvsDialog().
qWarning() << "AvsApp::onWidgetPlaced";
if (strcmp(PROJECTBUILD,"ahtc") == 0 || strcmp(PROJECTBUILD,"qatarmout") == 0 )
{
showAvsDialog(geometry);
}
else
{
QRect screenGeometry = geometry;
if (!geometry.isNull())
screenGeometry = screenGeometryOf(geometry.topLeft());
showAvsDialog(screenGeometry);
}
}
void AvsApp::onHideVideo()
{
hideAndPauseAvsDialog();
}
void AvsApp::onShowVideo()
{
showAndResumeAvsDialog();
}
void AvsApp::onPlacementHelperDestroyed()
{
qWarning() << "AvsApp::onPlacementHelperDestroyed()";
if (static_cast<LtsMultiMonitor::FullscreenVideoDummyWidget *>(sender()) != m_screenPlacementHelper)
return;
Q_ASSERT(m_screenPlacementHelper);
Q_ASSERT(!m_presetGeometry);
m_screenPlacementHelper = nullptr;
hideAvsDialog();
}
void AvsApp::showAvsDialog(const QRect &geometry)
{
qWarning() << "AvsApp::showAvsDialog";
if (geometry.isNull())
m_avaControl->setVideoDialogProfile(m_dialogId, AvaVisibility::Visible); // windowed mode; simply show the window as configured in AVS_Workstation.conf
else
m_avaControl->setVideoDialogGeometry(m_dialogId, geometry); // multi monitor mode
m_visible = true;
emit signalVisible();
}
void AvsApp::hideAvsDialog()
{
qWarning() << "AvsApp::hideAvsDialog()";
//if (!m_visible) // don't return as we
// return;
releaseStreams();
m_avaControl->setVideoDialogProfile(m_dialogId, AvaVisibility::Hidden);
m_visible = false;
}
void AvsApp::hideAndPauseAvsDialog()
{
m_visible = false;
m_avaControl->setVideoDialogProfile(m_dialogId, AvaVisibility::Hidden);
emit signalPause();
}
void AvsApp::showAndResumeAvsDialog()
{
m_visible = true;
emit signalResume();
emit signalVisible();
}
} // namespace AudioVideoManagement
+87
View File
@@ -0,0 +1,87 @@
/**
* @RDE_HEADER@
* AvsApp
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Fröbel, NLSE, 2018-04-16
*/
#pragma once
#include <Plugins/AudioVideoManagement/Shared/avmshared_export.h>
#include <QObject>
#include <QRect>
#include <boost/optional.hpp>
namespace LtsMultiMonitor
{
class FullscreenVideoDummyWidget;
}
namespace AudioVideoManagement
{
class AvaControl;
/**
* Manages an AVS-dialog in a way that it will behave like an Excon-App.
* When show() is called and the dialog is not visible yet, the Operator
* needs to choose on which screen the App shall be placed.
* The AVS-dialog will open in full-screen on the selected screen then.
* You can call hide() explicitly in order to hide the App. But usually
* this is done implicitly when a new App is placed ontop of this AvsApp.
*
* You can also call show(const QRect &geometry) in case you already know
* where the app is to be placed and thus avoid the screen selection.
*
* @author Christian Fröbel
*/
class AVMSHARED_EXPORT AvsApp : public QObject
{
Q_OBJECT
public:
AvsApp(const QString &dialogId, AvaControl *avaControl);
~AvsApp() override;
void show(const QVector<QWidget *> irreplacableWidgets = {});
void show(const QRect &geometry);
void hide(bool andClose = false);
bool isVisible() const;
bool isActive() const; // may be visible or hidden, but a ScreenPlaycementHelper is still there, so it might be hidden by the switcher
/**
* Release alls streams that might still be active in this app.
* Will be called implicitly when the dialog is hidden.
* But it can be called explicitly, e.g. when a PlaybackApp of Type Normal is released
* in which case the App remaines visible (hide() is not called then).
*/
void releaseStreams();
signals:
void signalVisible();
void signalPause();
void signalResume();
private slots:
void onWidgetPlaced(const QRect &geometry);
void onPlacementHelperDestroyed();
void onHideVideo();
void onShowVideo();
private:
void showAvsDialog(const QRect &geometry);
void hideAvsDialog();
void hideAndPauseAvsDialog();
void showAndResumeAvsDialog();
static const QString ALL_STREAMS;
const QString m_dialogId;
AvaControl *m_avaControl;
LtsMultiMonitor::FullscreenVideoDummyWidget *m_screenPlacementHelper{nullptr};
boost::optional<QRect> m_presetGeometry;
bool m_visible;
};
} // namespace AudioVideoManagement
+102
View File
@@ -0,0 +1,102 @@
/**
* @RDE_HEADER@
* PlaybackApp
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Fröbel, NLSE, 2018-04-18
*/
#include "playback_app.h"
#include "avs_app.h"
#include <AudioVideoManagement/avs_dialog.h>
#include <QtGlobal>
namespace AudioVideoManagement
{
PlaybackApp::PlaybackApp(const QString &dialogId, AvaControl *avaControl, AppType appType)
: m_dialogId(dialogId)
, m_autoHide(appType == AppType::AutoHide)
{
if (appType != AppType::AlwaysHidden)
{
m_app.reset(new AvsApp(m_dialogId, avaControl));
m_objectWrapper = new ObjectWrapper(nullptr);
QObject::connect(m_app.get(), &AvsApp::signalVisible,
m_objectWrapper, &ObjectWrapper::signalVisible);
QObject::connect(m_app.get(), &AvsApp::signalPause,
m_objectWrapper, &ObjectWrapper::signalPause);
QObject::connect(m_app.get(), &AvsApp::signalResume,
m_objectWrapper, &ObjectWrapper::signalResume);
}
}
PlaybackApp::~PlaybackApp()
{
if (m_objectWrapper)
m_objectWrapper->deleteLater();
}
void PlaybackApp::acquire()
{
Q_ASSERT(!m_inUse);
if (m_app)
m_app->show();
m_inUse = true;
}
void PlaybackApp::setGeometry(const QRect &geometry)
{
Q_ASSERT(m_app);
m_app->show(geometry);
}
void PlaybackApp::acquire(const QRect &geometry)
{
Q_ASSERT(!m_inUse);
setGeometry(geometry);
m_inUse = true;
}
void PlaybackApp::release()
{
Q_ASSERT(m_inUse);
// Hint: when m_autoHide == true, m_app is set.
// Otherwise (appType == Normal or AlwaysHidden) m_app might not be set (when appType == AlwaysHidden).
if (m_autoHide)
m_app->hide(true /* and close */); // implicitly releases all streams
else if (m_app)
m_app->releaseStreams();
m_inUse = false;
}
void PlaybackApp::hide(bool andClose)
{
Q_ASSERT(m_inUse);
if (m_app)
m_app->hide(andClose);
}
// PlaybackAppHandle
PlaybackAppHandle::PlaybackAppHandle(PlaybackApp *app)
: m_app(app, [] (PlaybackApp *app_) { app_->release(); })
{
Q_ASSERT(app);
app->acquire();
}
PlaybackAppHandle::PlaybackAppHandle(PlaybackApp *app, const QRect &geometry)
: m_app(app, [] (PlaybackApp *app_) { app_->release(); })
{
Q_ASSERT(app);
app->acquire(geometry);
}
} // namespace AudioVideoManagement
+127
View File
@@ -0,0 +1,127 @@
/**
* @RDE_HEADER@
* PlaybackApp
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Fröbel, NLSE, 2018-04-18
*/
#pragma once
#include <Plugins/AudioVideoManagement/Shared/avmshared_export.h>
#include <QString>
#include <QObject>
#include <memory>
#include <functional>
class QRect;
namespace AudioVideoManagement
{
class AvsApp;
class AvaControl;
// PlaybackApp cannot be a QObject, so we need a wrapper that takes signals, etc.
class AVMSHARED_EXPORT ObjectWrapper : public QObject
{
Q_OBJECT
public:
ObjectWrapper(QObject *parent) : QObject(parent) {}
signals:
void signalVisible();
void signalPause();
void signalResume();
};
/**
* Represents a playback application -- either for video or for audio.
* Audio does not require the AVS dialog to be visible and we don't need
* a separate application in the Excon-sense for that. Use AppType::AlwaysHidden
* for audio.
*
* The Video PlaybackApp will cover a whole screen as all the other Excon apps do
* and will be placed in the same way (see AvsApp).
*
* PlaybackApp is a resource and can only be used by one client at the same time.
*
* @author Christian Fröbel
*/
class AVMSHARED_EXPORT PlaybackApp
{
public:
enum class AppType
{
Normal = 1, //!< Visible AVS-dialog, no auto-hide on release()
AutoHide, //!< Visible AVS-dialog, auto-hide on release()
AlwaysHidden //!< No visible AVS-dialog (for audio playback)
};
/**
* Use AppType::AlwaysHidden for Audio.
*/
PlaybackApp(const QString &dialogId, AvaControl *avaControl, AppType);
virtual ~PlaybackApp();
ObjectWrapper *objectWrapper() { return m_objectWrapper; }
const QString &dialogId() const { return m_dialogId; }
/** @return true if someone is using this App. */
bool inUse() const { return m_inUse; }
/**
* Resource acquisition.
* Don't use directly; use PlaybackAppHandle instead.
*/
///@{
/**
* May only be called when inUse() == false.
* Will implicitly show the underlying AvsApp.
*/
void acquire();
void acquire(const QRect &geometry);
void setGeometry(const QRect &geometry);
/**
* Will implicitly hide the underlying AvsApp when appType == AppType::AutoHide.
*/
void release();
void hide(bool andClose);
///@}
private:
const QString m_dialogId;
bool m_inUse{false};
bool m_autoHide;
std::unique_ptr<AvsApp> m_app; //!< only set when appType != AppType::AlwaysHidden
ObjectWrapper *m_objectWrapper { nullptr };
};
/**
* @author Christian Fröbel
*/
class AVMSHARED_EXPORT PlaybackAppHandle
{
public:
PlaybackAppHandle() = default;
explicit PlaybackAppHandle(PlaybackApp *app);
PlaybackAppHandle(PlaybackApp *app, const QRect &geometry);
operator bool() const { return m_app.get() != nullptr; }
const QString &dialogId() const { return m_app->dialogId(); }
void hide(bool andClose = false) { m_app->hide(andClose); }
ObjectWrapper *objectWrapper() { return m_app->objectWrapper(); }
private:
using Releaser = std::function<void (PlaybackApp *)>;
std::unique_ptr<PlaybackApp, Releaser> m_app;
};
} // namespace AudioVideoManagement
@@ -0,0 +1,93 @@
/**
* @RDE_HEADER@
* PluginSettings
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Fröbel, NLSE, 2018-04-25
*/
#include "plugin_settings.h"
#include <nglsettings/nglsettings_settings.h>
#include <nglsettings/nglsettings_connections.h>
#include <ngltools/ngltools_filesystem.h>
#include <QtGlobal>
#include <QSettings>
namespace
{
const QString &AVA_SECTION()
{
static const QString key = QStringLiteral("AVS_WORKSTATION");
return key;
}
const QString &VD_SECTION()
{
static const QString key = QStringLiteral("AVS_WORKSTATION_VD");
return key;
}
//constexpr std::chrono::milliseconds DEFAULT_TIMEOUT(3000);
constexpr std::chrono::milliseconds DEFAULT_TIMEOUT(10000);
constexpr std::chrono::milliseconds DEFAULT_TIMEOUT_VD(60000); // export may take some time
} // anonymous namespace
namespace AudioVideoManagement
{
PluginSettings *PluginSettings::s_instance = nullptr;
PluginSettings::PluginSettings()
: PluginSettings(NGL::findProjectConfigFile())
{
Q_ASSERT(!s_instance);
s_instance = this;
}
PluginSettings::PluginSettings(const QString &pathToConfigFile)
: m_settings(new NGL::Settings(pathToConfigFile))
{
NGL::Connections::setIniFile(pathToConfigFile);
}
PluginSettings::~PluginSettings()
{
s_instance = nullptr;
}
PluginSettings *PluginSettings::instance()
{
Q_ASSERT(s_instance);
return s_instance;
}
bool PluginSettings::avaKeepAliveEnabled() const
{
static const QString key = QStringLiteral("%1/KeepAlive").arg(AVA_SECTION());
return m_settings->settings()->value(key, true).toBool();
}
std::chrono::milliseconds PluginSettings::avaTimeout() const
{
static const QString key = QStringLiteral("%1/Timeout").arg(AVA_SECTION());
return std::chrono::milliseconds(m_settings->settings()->value(key, static_cast<unsigned>(DEFAULT_TIMEOUT.count())).toUInt());
}
bool PluginSettings::vdKeepAliveEnabled() const
{
static const QString key = QStringLiteral("%1/KeepAlive").arg(VD_SECTION());
return m_settings->settings()->value(key, true).toBool();
}
std::chrono::milliseconds PluginSettings::vdTimeout() const
{
static const QString key = QStringLiteral("%1/Timeout").arg(VD_SECTION());
return std::chrono::milliseconds(m_settings->settings()->value(key, static_cast<unsigned>(DEFAULT_TIMEOUT_VD.count())).toUInt());
}
} // namespace AudioVideoManagement
+65
View File
@@ -0,0 +1,65 @@
/**
* @RDE_HEADER@
* PluginSettings
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Fröbel, NLSE, 2018-04-25
*/
#pragma once
#include <Plugins/AudioVideoManagement/Shared/avmshared_export.h>
#include <QString>
#include <memory>
#include <chrono>
namespace NGL
{
class Settings;
}
namespace AudioVideoManagement
{
/**
* PluginSettings singleton.
* At any given time at maximum one instance of this class exists.
* Construction and destruction of the singleton instance is done
* the usual way: by using the (public) constructors and destructor.
* After construction the singleton instance can be accessed
* via instance().
*
* @author Christian Fröbel
*/
class AVMSHARED_EXPORT PluginSettings
{
public:
/** Use the config file provided by NGL::findProjectConfigFile(). */
PluginSettings();
explicit PluginSettings(const QString &pathToConfigFile);
~PluginSettings();
/**
* May only be called *after* the singleton instance has been created.
* @return never nullptr
*/
static PluginSettings *instance();
bool avaKeepAliveEnabled() const;
std::chrono::milliseconds avaTimeout() const;
bool vdKeepAliveEnabled() const;
std::chrono::milliseconds vdTimeout() const;
NGL::Settings *settings() const { return m_settings.get(); }
private:
std::unique_ptr<NGL::Settings> m_settings;
static PluginSettings *s_instance; //!< singleton instance
};
} // namespace AudioVideoManagement
@@ -0,0 +1,37 @@
/**
* @RDE_HEADER@
* ProjectSettings
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Fröbel, NLE, 2019-02-08
*/
#include "project_settings.h"
#include <LtsUtilsSettings/settings.h>
#include <QString>
#include <QVariant>
namespace
{
template<typename T>
T value(const QString &identifier, const T &defaultValue)
{
LtsUtils::ProjectSettings *settings = LtsUtils::ProjectSettings::getInstance();
QVariant variant = settings->value(QStringLiteral("avm"), identifier, defaultValue);
return variant.value<T>();
}
} // anonymous namespace
namespace AudioVideoManagement
{
bool ProjectSettings::isAlwaysRecording()
{
return value(QStringLiteral("recording"), false);
}
} // namespace AudioVideoManagement
+28
View File
@@ -0,0 +1,28 @@
/**
* @RDE_HEADER@
* ProjectSettings
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Fröbel, NLE, 2019-02-08
*/
#pragma once
#include <Plugins/AudioVideoManagement/Shared/avmshared_export.h>
namespace AudioVideoManagement
{
/**
* Some helper functions to ease access to AVM-related project settings.
*
* @author Christian Fröbel
*/
class ProjectSettings
{
public:
AVMSHARED_EXPORT static bool isAlwaysRecording();
};
} // namespace AudioVideoManagement
@@ -0,0 +1,35 @@
#include "stream_list_result.h"
#include <QMap>
namespace AudioVideoManagement {
StreamListResult::StreamListResult()
: QObject(nullptr)
{
}
void StreamListResult::onStreamListReceived(const QVector<AvaStream> &streams)
{
QMap<QString, QString> streamInternalNameToDisplayName;
for(const auto &stream : streams)
{
streamInternalNameToDisplayName.insert(stream.toString(), stream.displayName);
}
emit emitStreamList(streamInternalNameToDisplayName);
}
StreamClipsResult::StreamClipsResult()
: QObject(nullptr)
{
}
void StreamClipsResult::onClipsListReceived(const AvaTimeline &clips)
{
emit emitClipsList(clips);
}
} // namespace AudioVideoManagement
@@ -0,0 +1,36 @@
#pragma once
#include <QObject>
#include <AudioVideoManagement/ava_types.h>
#include <Plugins/AudioVideoManagement/Shared/avmshared_export.h>
namespace AudioVideoManagement {
class AVMSHARED_EXPORT StreamClipsResult : public QObject
{
Q_OBJECT
public:
StreamClipsResult();
public slots:
void onClipsListReceived(const AvaTimeline &clips);
signals:
void emitClipsList(const AvaTimeline &clips);
};
class AVMSHARED_EXPORT StreamListResult : public QObject
{
Q_OBJECT
public:
StreamListResult();
public slots:
void onStreamListReceived(const QVector<AvaStream> &streams);
signals:
void emitStreamList(const QMap<QString, QString> &streams);
};
} //namespace AudioVideoManagement