Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Plugins/AudioVideoManagement/Gui/AVMenuEdit/topic_replay.cpp
T
torstenandCopilot d6b6ffce7c Apply clang-format to Lts/Common and DTC/enum headers
- Formatted all CodeGen module files (9 files)
- Formatted LtsAppDescriptor module files
- Formatted LtsAppManager/AppChooser files
- Applied clang-format to all DTC and enum headers across modules
- Removed coordTransTests from CommonUnitTestsPlaceholder (moved to tests/)

Cosmetic changes only, no functional modifications.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-08-19 14:46:29 +02:00

442 lines
12 KiB
C++

#include "topic_replay.h"
#include <AudioVideoManagement/ava_control.h>
#include <AudioVideoManagement/ava_session.h>
#include <AudioVideoManagement/ava_types.h>
#include <AudioVideoManagement/avm_data_plugin_interface.h>
#include <AudioVideoManagement/vd_control.h>
#include <AudioVideoManagement/vd_session.h>
#include <LtsUtilsCore/json_object.h>
#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <QJsonDocument>
#include <QRect>
#include <QWidget>
#include <QtGlobal>
#include <TopicEditorBase/topic_editor_base.h>
#include <chrono>
#include <nglsettings/nglsettings_settings.h>
#include <vector>
namespace AudioVideoManagement
{
class TopicReplay::ExportScript : public QObject
{
Q_OBJECT
public:
ExportScript(const QString& topLevelExportDir, TopicEditorBase::ExportNotifier* exportStep);
public slots:
void avScriptFinished(const QString& exportDir, AvaStreamType streamType, bool success);
private:
QString audioVideoPlaylistErstellen(const QString& dir, AvaStreamType streamType);
bool writeFile(const QByteArray& data, const QString& fileName);
QString m_topLevelExportDir;
TopicEditorBase::ExportNotifier* m_exportStep;
};
TopicReplay::TopicReplay(DataInterface* dataIfc, bool isAudio) : m_isAudio(isAudio), m_dataIfc(dataIfc)
{
DEBUG_LOG(m_logger) << "TopicReplay::TopicReplay()";
Q_ASSERT(dataIfc);
}
TopicReplay::~TopicReplay()
{
DEBUG_LOG(m_logger) << "TopicReplay::~TopicReplay()";
if (m_isPlaying)
playbackStop();
}
QWidget* TopicReplay::createWidget()
{
DEBUG_LOG(m_logger) << "TopicReplay::createWidget()";
Q_ASSERT(!m_screenPlacementHelper);
if (m_isAudio)
return nullptr;
m_screenPlacementHelper.reset(new ScreenPlacementHelper());
connect(m_screenPlacementHelper.data(), &ScreenPlacementHelper::widgetPlaced, this, &TopicReplay::onWidgetPlaced);
return m_screenPlacementHelper.data();
}
void TopicReplay::slotSetScriptResponse(const AudioVideoManagement::AvaStreamInfo& streamInfo,
AudioVideoManagement::AvaStreamState streamState)
{
if (streamState == AudioVideoManagement::AvaStreamState::NotPossible)
ERROR_LOG(m_logger) << "Script could not be set";
else
ERROR_LOG(m_logger) << "Script set!";
ERROR_LOG(m_logger) << "streamInfo: start" << streamInfo.duration.count();
ERROR_LOG(m_logger) << "streamState: " << static_cast<int>(streamState);
}
bool TopicReplay::playbackInit(const QJsonObject& attributes)
{
DEBUG_LOG(m_logger) << "TopicReplay::playbackInit()";
DEBUG_LOG(m_logger) << QJsonDocument(attributes).toJson();
if (m_screenPlacementHelper && !m_isAudio)
m_screenPlacementHelper->show();
m_playbackAttributes = attributes;
AvaControl* ctrl = getAvaControl();
if (ctrl == nullptr)
{
ERROR_LOG(m_logger) << "no ava control!";
return false;
}
AvaTopicData topicData(m_playbackAttributes);
if (!topicData.isValid)
{
ERROR_LOG(m_logger) << "topicData is invalid";
return false;
}
m_scriptName = topicData.scriptName();
Q_ASSERT(topicData.isAudio() == m_isAudio);
PlaybackApp* app = m_isAudio ? m_dataIfc->audioPresentationApp() : m_dataIfc->videoPresentationApp();
if (app == nullptr || app->inUse())
{
ERROR_LOG(m_logger) << "app invalid or in use!";
return false;
}
if (!m_dialogGeometry)
{
if (m_isAudio)
m_appHandle = PlaybackAppHandle(app);
else
m_appHandle = PlaybackAppHandle(app, QRect(0, 0, 0, 0));
}
else
m_appHandle = PlaybackAppHandle(app, *m_dialogGeometry);
if (!m_appHandle)
{
ERROR_LOG(m_logger) << "appHandle: missing app after creating appHandle!";
return false;
}
NGL::Settings s({});
bool isLocal = s.isDatabaseConnectionLocal();
DEBUG_LOG(m_logger) << "isLocal? " << isLocal;
AvaScriptSource source;
if (isLocal)
{
if (m_isAudio)
source = AvaScriptSource::LocalAudio;
else
source = AvaScriptSource::LocalVideo;
}
else
{
if (m_isAudio)
source = AvaScriptSource::ServerAudio;
else
source = AvaScriptSource::ServerVideo;
}
DEBUG_LOG(m_logger) << "source: " << static_cast<int>(source);
ctrl->setScript(m_appHandle.dialogId(), m_scriptName, source, topicData.streamList(),
LtsUtils::createConnection(ctrl, &AudioVideoManagement::AvaControl::setScriptResponse, this,
&TopicReplay::slotSetScriptResponse));
return true;
}
bool TopicReplay::playbackStart(int secondsOffset)
{
DEBUG_LOG(m_logger) << "TopicReplay::playbackStart()";
if (m_screenPlacementHelper && !m_isAudio)
m_screenPlacementHelper->show();
AvaControl* ctrl = getAvaControl();
if (ctrl == nullptr)
{
ERROR_LOG(m_logger) << "ctrl == nullptr";
return false;
}
AvaTimePoint p{AvaDuration{std::chrono::seconds(secondsOffset)}};
if (!m_appHandle)
{
ERROR_LOG(m_logger) << "appHandle: missing app!";
return false;
}
ctrl->setAbsPositionScript(m_appHandle.dialogId(), m_scriptName, p);
ctrl->startScript(m_appHandle.dialogId(), m_scriptName);
m_isPlaying = true;
DEBUG_LOG(m_logger) << "m_isPlaying = true";
return true;
}
bool TopicReplay::playbackPause()
{
DEBUG_LOG(m_logger) << "TopicReplay::playbackPause()";
if (m_screenPlacementHelper)
m_screenPlacementHelper->hide();
if (!m_isPlaying)
return true;
AvaControl* ctrl = getAvaControl();
if (ctrl == nullptr)
{
ERROR_LOG(m_logger) << "no ctrl!";
return false;
}
if (!m_appHandle)
{
ERROR_LOG(m_logger) << "appHandle: missing app!";
return false;
}
ctrl->pauseScript(m_appHandle.dialogId(), m_scriptName);
return true;
}
bool TopicReplay::playbackStop()
{
DEBUG_LOG(m_logger) << "TopicReplay::playbackStop()";
if (m_screenPlacementHelper)
m_screenPlacementHelper->hide();
if (!m_isPlaying)
return true;
AvaControl* ctrl = getAvaControl();
if (ctrl == nullptr)
{
ERROR_LOG(m_logger) << "no ctrl!";
return false;
}
if (!m_appHandle)
{
ERROR_LOG(m_logger) << "appHandle: missing app!";
return false;
}
ctrl->stopScript(m_appHandle.dialogId(), m_scriptName);
ctrl->releaseScript(m_appHandle.dialogId(), m_scriptName);
m_isPlaying = false;
return true;
}
bool TopicReplay::exportTopic(const QJsonObject& attributes, const QString& folderPath,
TopicEditorBase::ExportNotifier* exportNotifier)
{
Q_ASSERT(!m_exportScript);
VdControl* ctrl = getVdControl();
if (ctrl == nullptr)
{
ERROR_LOG(m_logger) << "ctrl missing!";
exportNotifier->setExportFailed();
return false;
}
m_exportScript.reset(new ExportScript(folderPath, exportNotifier));
AvaTopicData topicData(attributes);
m_scriptName = topicData.scriptName();
if (!topicData.isValid)
{
ERROR_LOG(m_logger) << "topicData is invalid";
exportNotifier->setExportFailed();
return false;
}
QFileInfo fileInfo(QDir(folderPath).filePath(topicData.scriptName()));
Q_ASSERT(topicData.isAudio() == m_isAudio);
ctrl->vdSetScript(m_scriptName, m_isAudio ? AvaStreamType::Audio : AvaStreamType::Video, 0, topicData.streamList(),
fileInfo.baseName(), fileInfo.absolutePath(), this, &TopicReplay::avScriptFinished);
return true;
}
void TopicReplay::onWidgetPlaced(const QRect& geometry)
{
WARNING_LOG(m_logger) << "TopicReplay::onWidgetPlaced() - geo: " << geometry.x() << "/" << geometry.y()
<< " m_isAudio=" << m_isAudio;
m_dialogGeometry = geometry;
if (m_isAudio)
return;
PlaybackApp* app = m_isAudio ? m_dataIfc->audioPresentationApp() : m_dataIfc->videoPresentationApp();
if (app == nullptr)
{
ERROR_LOG(m_logger) << "app missing!";
return;
}
if (!app->inUse())
{
ERROR_LOG(m_logger) << "app not in use - waiting for playbackInit to aquire it";
return;
}
DEBUG_LOG(m_logger) << "setGeometry";
app->setGeometry(*m_dialogGeometry);
}
AvaControl* TopicReplay::getAvaControl()
{
if (!m_dataIfc->hasAvsSession())
return nullptr;
AvaSession* avaSession = m_dataIfc->avaSession();
if (!avaSession->isEstablished())
return nullptr;
return avaSession->control();
}
VdControl* TopicReplay::getVdControl()
{
if (!m_dataIfc->hasAvsSession())
return nullptr;
VdSession* vdSession = m_dataIfc->vdSession();
if (!vdSession->isEstablished())
return nullptr;
return vdSession->control();
}
void TopicReplay::avScriptFinished(const QString& exportDir, AvaStreamType streamType, bool success)
{
VdControl* ctrl = getVdControl();
ctrl->vdReleaseScript(m_scriptName);
m_exportScript->avScriptFinished(exportDir, streamType, success);
}
TopicReplay::ExportScript::ExportScript(const QString& topLevelExportDir, TopicEditorBase::ExportNotifier* exportStep)
: m_topLevelExportDir(topLevelExportDir), m_exportStep(exportStep)
{
connect(exportStep, &QObject::destroyed, this, [this]() {
if (static_cast<TopicEditorBase::ExportNotifier*>(sender()) != m_exportStep)
return;
m_exportStep = nullptr;
});
Q_ASSERT(exportStep);
}
void TopicReplay::ExportScript::avScriptFinished(const QString& exportDir, AvaStreamType streamType, bool success)
{
QString absPathToPlaylist = audioVideoPlaylistErstellen(exportDir, streamType);
QDir toplevelExportDir(m_topLevelExportDir);
QString relativePathToPlaylist = toplevelExportDir.relativeFilePath(absPathToPlaylist);
if (m_exportStep == nullptr)
return;
if (success)
m_exportStep->setExportSuccessful(relativePathToPlaylist);
else
m_exportStep->setExportFailed();
}
QString TopicReplay::ExportScript::audioVideoPlaylistErstellen(const QString& dir, AvaStreamType streamType)
{
QDir avDir(dir);
const QFileInfoList dateienList = avDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name);
QByteArray dataForFile;
QString data;
dataForFile.append("[playlist]\n");
int numberOfEntries = 0;
int i = 1;
const QString tmpl1(QStringLiteral("File %1=%2\n"));
const QString tmpl2(QStringLiteral("# File %1=%2\n"));
for (const QFileInfo& fileInfo : dateienList)
{
if (streamType == AvaStreamType::Video && fileInfo.suffix() == QLatin1String(".wav"))
{
data += tmpl2.arg(QString::number(i), fileInfo.fileName());
i--;
}
else
{
data += tmpl1.arg(QString::number(i), fileInfo.fileName());
numberOfEntries++;
}
i++;
}
QString numberOfEntriesString =
QStringLiteral("NumberOfEntries=") + QString::number(numberOfEntries) + QStringLiteral("\n");
dataForFile.append(numberOfEntriesString.toUtf8());
dataForFile.append(data.toUtf8());
QString fileName;
switch (streamType)
{
case AvaStreamType::Audio:
fileName = avDir.filePath(QStringLiteral("audio.pls"));
break;
case AvaStreamType::Video:
fileName = avDir.filePath(QStringLiteral("video.pls"));
break;
}
writeFile(dataForFile, fileName);
return fileName;
}
bool TopicReplay::ExportScript::writeFile(const QByteArray& data, const QString& fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
return false;
if (file.write(data) == -1)
{
file.close();
return false;
}
file.close();
return true;
}
} // namespace AudioVideoManagement
#include "topic_replay.moc"