first commit

This commit is contained in:
2026-02-21 17:11:31 +09:00
commit 18b4338361
4001 changed files with 365464 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,274 @@
#ifndef __STACKWALKER_H__
#define __STACKWALKER_H__
#if (REPORT_CRASH_LOG)
#if defined(_MSC_VER)
/**********************************************************************
*
* StackWalker.h
*
*
*
* LICENSE (http://www.opensource.org/licenses/bsd-license.php)
*
* Copyright (c) 2005-2009, Jochen Kalmbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Jochen Kalmbach nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* **********************************************************************/
// #pragma once is supported starting with _MSC_VER 1000,
// so we need not to check the version (because we only support _MSC_VER >= 1100)!
#pragma once
#include <windows.h>
// special defines for VC5/6 (if no actual PSDK is installed):
#if _MSC_VER < 1300
typedef unsigned __int64 DWORD64, *PDWORD64;
#if defined(_WIN64)
typedef unsigned __int64 SIZE_T, *PSIZE_T;
#else
typedef unsigned long SIZE_T, *PSIZE_T;
#endif
#endif // _MSC_VER < 1300
class StackWalkerInternal; // forward
class StackWalker
{
public:
typedef enum ExceptType
{
NonExcept = 0, // RtlCaptureContext
AfterExcept = 1,
AfterCatch = 2, // get_current_exception_context
} ExceptType;
typedef enum StackWalkOptions
{
// No addition info will be retrieved
// (only the address is available)
RetrieveNone = 0,
// Try to get the symbol-name
RetrieveSymbol = 1,
// Try to get the line for this symbol
RetrieveLine = 2,
// Try to retrieve the module-infos
RetrieveModuleInfo = 4,
// Also retrieve the version for the DLL/EXE
RetrieveFileVersion = 8,
// Contains all the above
RetrieveVerbose = 0xF,
// Generate a "good" symbol-search-path
SymBuildPath = 0x10,
// Also use the public Microsoft-Symbol-Server
SymUseSymSrv = 0x20,
// Contains all the above "Sym"-options
SymAll = 0x30,
// Contains all options (default)
OptionsAll = 0x3F
} StackWalkOptions;
StackWalker(ExceptType extype, int options = OptionsAll, PEXCEPTION_POINTERS exp = NULL);
StackWalker(int options = OptionsAll, // 'int' is by design, to combine the enum-flags
LPCSTR szSymPath = NULL,
DWORD dwProcessId = GetCurrentProcessId(),
HANDLE hProcess = GetCurrentProcess());
StackWalker(DWORD dwProcessId, HANDLE hProcess);
virtual ~StackWalker();
bool SetSymPath(LPCSTR szSymPath);
bool SetTargetProcess(DWORD dwProcessId, HANDLE hProcess);
PCONTEXT GetCurrentExceptionContext();
private:
bool Init(ExceptType extype, int options, LPCSTR szSymPath, DWORD dwProcessId,
HANDLE hProcess, PEXCEPTION_POINTERS exp = NULL);
public:
typedef BOOL(__stdcall* PReadProcessMemoryRoutine)(
HANDLE hProcess,
DWORD64 qwBaseAddress,
PVOID lpBuffer,
DWORD nSize,
LPDWORD lpNumberOfBytesRead,
LPVOID pUserData // optional data, which was passed in "ShowCallstack"
);
BOOL LoadModules();
BOOL ShowCallstack(
HANDLE hThread = GetCurrentThread(),
const CONTEXT* context = NULL,
PReadProcessMemoryRoutine readMemoryFunction = NULL,
LPVOID pUserData = NULL // optional to identify some data in the 'readMemoryFunction'-callback
);
BOOL ShowObject(LPVOID pObject);
#if _MSC_VER >= 1300
// due to some reasons, the "STACKWALK_MAX_NAMELEN" must be declared as "public"
// in older compilers in order to use it... starting with VC7 we can declare it as "protected"
protected:
#endif
enum
{
STACKWALK_MAX_NAMELEN = 1024
}; // max name length for found symbols
protected:
// Entry for each Callstack-Entry
typedef struct CallstackEntry
{
DWORD64 offset; // if 0, we have no valid entry
CHAR name[STACKWALK_MAX_NAMELEN];
CHAR undName[STACKWALK_MAX_NAMELEN];
CHAR undFullName[STACKWALK_MAX_NAMELEN];
DWORD64 offsetFromSmybol;
DWORD offsetFromLine;
DWORD lineNumber;
CHAR lineFileName[STACKWALK_MAX_NAMELEN];
DWORD symType;
LPCSTR symTypeString;
CHAR moduleName[STACKWALK_MAX_NAMELEN];
DWORD64 baseOfImage;
CHAR loadedImageName[STACKWALK_MAX_NAMELEN];
} CallstackEntry;
typedef enum CallstackEntryType
{
firstEntry,
nextEntry,
lastEntry
} CallstackEntryType;
virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName);
virtual void OnLoadModule(LPCSTR img,
LPCSTR mod,
DWORD64 baseAddr,
DWORD size,
DWORD result,
LPCSTR symType,
LPCSTR pdbName,
ULONGLONG fileVersion);
virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry& entry);
virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr);
virtual void OnOutput(LPCSTR szText);
StackWalkerInternal* m_sw;
HANDLE m_hProcess;
DWORD m_dwProcessId;
BOOL m_modulesLoaded;
LPSTR m_szSymPath;
int m_options;
int m_MaxRecursionCount;
static BOOL __stdcall myReadProcMem(HANDLE hProcess,
DWORD64 qwBaseAddress,
PVOID lpBuffer,
DWORD nSize,
LPDWORD lpNumberOfBytesRead);
friend StackWalkerInternal;
}; // class StackWalker
// The "ugly" assembler-implementation is needed for systems before XP
// If you have a new PSDK and you only compile for XP and later, then you can use
// the "RtlCaptureContext"
// Currently there is no define which determines the PSDK-Version...
// So we just use the compiler-version (and assumes that the PSDK is
// the one which was installed by the VS-IDE)
// INFO: If you want, you can use the RtlCaptureContext if you only target XP and later...
// But I currently use it in x64/IA64 environments...
//#if defined(_M_IX86) && (_WIN32_WINNT <= 0x0500) && (_MSC_VER < 1400)
#if defined(_M_IX86)
#ifdef CURRENT_THREAD_VIA_EXCEPTION
// TODO: The following is not a "good" implementation,
// because the callstack is only valid in the "__except" block...
#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \
do \
{ \
memset(&c, 0, sizeof(CONTEXT)); \
EXCEPTION_POINTERS* pExp = NULL; \
__try \
{ \
throw 0; \
} \
__except (((pExp = GetExceptionInformation()) ? EXCEPTION_EXECUTE_HANDLER \
: EXCEPTION_EXECUTE_HANDLER)) \
{ \
} \
if (pExp != NULL) \
memcpy(&c, pExp->ContextRecord, sizeof(CONTEXT)); \
c.ContextFlags = contextFlags; \
} while (0);
#else
// clang-format off
// The following should be enough for walking the callstack...
#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \
do \
{ \
memset(&c, 0, sizeof(CONTEXT)); \
c.ContextFlags = contextFlags; \
__asm call x \
__asm x: pop eax \
__asm mov c.Eip, eax \
__asm mov c.Ebp, ebp \
__asm mov c.Esp, esp \
} while (0)
// clang-format on
#endif
#else
// The following is defined for x86 (XP and higher), x64 and IA64:
#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \
do \
{ \
memset(&c, 0, sizeof(CONTEXT)); \
c.ContextFlags = contextFlags; \
RtlCaptureContext(&c); \
} while (0);
#endif
#endif //defined(_MSC_VER)
#endif // #if (REPORT_CRASH_LOG)
#endif // __STACKWALKER_H__

View File

@@ -0,0 +1,236 @@
#include "fe_log.h"
#if (FE_LOG_VERSION)
#include <Windows.h>
#include <QVBoxLayout>
#include <QPlainTextEdit>
#include <QDateTime>
#include <QSysInfo>
#include <QStorageInfo>
#include <QSettings>
#include <QDebug>
#include <QProcess>
#include <QDateTime>
#include <QCryptographicHash>
#include <QScrollBar>
#include <QFileDialog>
QVector<QString> FELogHandler::buffer = QVector<QString>();
void FELogHandler::messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QString ds = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz ");
buffer.append(ds + msg);
emit FELogHandler::instance()->appended(msg);
//printDebug(__FUNCTION__ + msg);
//OutputDebugString(reinterpret_cast<const wchar_t *>(msg.utf16()));
// QByteArray localMsg = msg.toLocal8Bit();
// switch (type) {
// case QtDebugMsg:
// fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
// break;
// case QtInfoMsg:
// fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
// break;
// case QtWarningMsg:
// fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
// break;
// case QtCriticalMsg:
// fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
// break;
// case QtFatalMsg:
// fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
// abort();
// }
// fflush(stderr);
}
void FELogHandler::printDebug(QString msg)
{
OutputDebugString(reinterpret_cast<const wchar_t *>(msg.utf16()));
}
void FELogDialog::onButton()
{
QPushButton* btn = qobject_cast<QPushButton*>(sender());
QString cmd = btn->text().toUpper();
if(cmd == "SAVE")
{
QString savePath = QFileDialog::getSaveFileName(0,
"LOG SAVE FILE",
NULL,
"Log files (*.log)",0,QFileDialog::DontConfirmOverwrite);
if(!savePath.isEmpty())
{
QFile file(savePath);
if (file.open(QIODevice::WriteOnly)) {
QTextStream stream(&file);
stream << _text->toPlainText() << endl;
}
}
}
}
QPushButton* FELogDialog::button(QWidget* parent,QLayout* layout,QString title)
{
QPushButton* btn = new QPushButton(parent);
btn->setText(title);
//btn->setStyleSheet("font-family: Arial;font-size: 9px;");
btn->setStyleSheet("QPushButton{font-family: Fixedsys;color : white;}"
"QPushButton[enabled=\"false\"]{color : #AAAAAA;}");
btn->setFixedWidth(title.length() * 10);
layout->addWidget(btn);
connect(btn,SIGNAL(clicked()),SLOT(onButton()));
return btn;
}
FELogDialog::FELogDialog(QWidget *parent,Qt::WindowFlags f) : QDialog(parent,f)
{
setWindowTitle("LOG.");
//setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint);
setWindowModality(Qt::NonModal);
// 시작시 표시 및 처리되지 않도록 시작
#if !(TOGGLE_PLAYER)
setAttribute(Qt::WA_DontShowOnScreen,true);
setAttribute(Qt::WA_ShowWithoutActivating,true);
#endif
resize(640,480);
_layout = new QVBoxLayout(this);
_layout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
_layout->setMargin(0);
_layout->setSpacing(0);
_toolbar = new QWidget(this);
_toolbar->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
_toolbar->setFixedHeight(36);
_layout->addWidget(_toolbar);
_toolbar->setStyleSheet("background-color: #818181;");
//_toolbar->setObjectName("test_widget");
QHBoxLayout* toolLayout = new QHBoxLayout(_toolbar);
toolLayout->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
toolLayout->setSpacing(6);
toolLayout->setMargin(2);
QPushButton* btn;
btn = button(_toolbar,toolLayout,"SAVE");
// _openButton = button(_toolbar,toolLayout,"OPEN");
// _reloadButton = button(_toolbar,toolLayout,"RELOAD");
// _stopButton = button(_toolbar,toolLayout,"STOP");
// _stopButton->setEnabled(false);
// btn = button(_toolbar,toolLayout,"CLEAR");
// btn = button(_toolbar,toolLayout,"DIR");
_text = new QPlainTextEdit(this);
_text->setReadOnly(true);
_text->setStyleSheet("font-family: Fixedsys;color : #00FF00;background-color: #111111;border:1px;border-style:solid;border-color:#313131;");
_text->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
_layout->addWidget(_text);
_addSystemInfo();
}
FELogDialog* FELogDialog::instance(QWidget* parent)
{
static FELogDialog * _instance = NULL;
if ( _instance == NULL )
{
_instance = new FELogDialog(parent);
}
return _instance;
}
void FELogDialog::showEvent( QShowEvent* event )
{
QDialog::showEvent(event);
//qInfo() << __FUNCTION__;
setUpdatesEnabled(false);
_text->clear();
QVectorIterator<QString> iter(FELogHandler::buffer);
while (iter.hasNext()) {
_text->insertPlainText(iter.next() + "\n");
}
connect(FELogHandler::instance(),SIGNAL(appended(QString)),SLOT(onAppended(QString)),Qt::UniqueConnection);
//QMetaObject::invokeMethod(this, "afterWindowShown", Qt::ConnectionType::QueuedConnection);
setUpdatesEnabled(true);
}
void FELogDialog::onAppended(QString msg)
{
QString ds = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz ");
//FELogHandler::printDebug(__FUNCTION__ + msg);
_text->insertPlainText(ds + msg + "\n");
_text->verticalScrollBar()->setValue(_text->verticalScrollBar()->maximum());
}
void FELogDialog::onClose()
{
disconnect(FELogHandler::instance(),SIGNAL(appended(QString)),this,SLOT(onAppended(QString)));
//qInfo() << __FUNCTION__;
//_hideOnFullScreen = false;
setHidden(true);
close();
//RMApp::instance()->pMainWindow->setFocus();
}
bool FELogDialog::isHiddenReal()
{
if(testAttribute(Qt::WA_DontShowOnScreen))
{
setAttribute(Qt::WA_DontShowOnScreen,false);
setAttribute(Qt::WA_ShowWithoutActivating,false);
setHidden(true);
return true;
}
return isHidden();
}
void FELogDialog::_addSystemInfo()
{
FELogHandler::buffer.append("---------------------------------------------");
FELogHandler::buffer.append("SYSTEM INFO.");
FELogHandler::buffer.append("OS:" + QSysInfo::prettyProductName() + " (" + QSysInfo::currentCpuArchitecture() + ")");
FELogHandler::buffer.append("KERNEL:" + QSysInfo::kernelType() + " VER " + QSysInfo::kernelVersion());
QSettings settings("HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\BIOS", QSettings::NativeFormat);
FELogHandler::buffer.append("Manufacturer:" + settings.value("SystemManufacturer", "0").toString());
FELogHandler::buffer.append("Product:" + settings.value("SystemProductName", "0").toString());
QProcess process_system;
QString system_output;
QString cpuname = "wmic cpu get name";
process_system.start(cpuname);
process_system.waitForFinished();
system_output = process_system.readAllStandardOutput().toUpper();
while(system_output.contains(" ")) {
system_output = system_output.replace(" "," ");
}
FELogHandler::buffer.append("CPU:" + system_output.replace("\n","").replace("\r",""));
QString gpuname = "wmic PATH Win32_videocontroller get VideoProcessor ";
process_system.start(gpuname);
process_system.waitForFinished();
system_output = process_system.readAllStandardOutput();
while(system_output.contains(" ")) {
system_output = system_output.replace(" "," ");
}
FELogHandler::buffer.append("GPU:" + system_output.replace("\n","").replace("\r",""));
FELogHandler::buffer.append("---------------------------------------------");
}
#endif // #if (FE_LOG_VERSION)

View File

@@ -0,0 +1,64 @@
#ifndef FELOG_H
#define FELOG_H
#if (FE_LOG_VERSION)
#include <QWidget>
#include <QDialog>
#include <QPushButton>
//#include <QDebug>
#define FE_LOG_FL qInfo()//"[" << __FUNCTION__ << __LINE__ << "]"
class FELogHandler : public QObject
{
Q_OBJECT
private:
FELogHandler(QObject* parent = nullptr) : QObject(parent){}
public:
static void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);
static QVector<QString> buffer;
static void printDebug(QString msg);
static FELogHandler* instance()
{
static FELogHandler _instance;
return &_instance;
}
//static void myMessageHandler(QtMsgType, const QMessageLogContext &, const QString &);
signals:
void appended(QString msg);
};
class QPlainTextEdit;
class QVBoxLayout;
class FELogDialog : public QDialog
{
Q_OBJECT
private:
explicit FELogDialog(QWidget *parent = nullptr,Qt::WindowFlags f= Qt::WindowTitleHint | Qt::Dialog | Qt::WindowCloseButtonHint | Qt::CustomizeWindowHint);
QWidget* _toolbar;
QPlainTextEdit* _text;
QVBoxLayout* _layout;
void _addSystemInfo();
QPushButton* button(QWidget* parent,QLayout* layout,QString title);
protected:
void showEvent( QShowEvent* event );
public:
static FELogDialog* instance(QWidget* parent = nullptr);
bool isHiddenReal();
void onClose();
signals:
public slots:
void onAppended(QString msg);
void onButton();
};
#endif // FE_LOG_VERSION
#endif // FELOG_H

View File

@@ -0,0 +1,249 @@
#include "rm_design_dialog.h"
#if (DESIGN_LAYOUT_MODE)
#include "../rm_include.h"
#include "../ui/window_main.h"
#include <windows.h>
#include <QDebug>
#include <QMainWindow>
#include <QDesktopServices>
#include <QUrl>
#include <QFileDialog>
#include <QStyle>
#include <QMessageBox>
#include <QScrollBar>
#include <QGraphicsOpacityEffect>
#include <QMouseEvent>
FMDesignDialog* FMDesignDialog::instance(QWidget* parent)
{
static FMDesignDialog * _instance = NULL;
if ( _instance == NULL )
{
_instance = new FMDesignDialog(parent);
}
return _instance;
}
FMDesignDialog::FMDesignDialog(QWidget *parent) : QDialog(parent)
{
QString version;
version.sprintf("model:%s %d.%d.%d.%d",WINDOW_TITLE,RM_MODEL_VERSION_0,RM_MODEL_VERSION_1,RM_MODEL_VERSION_1,RM_MODEL_SVN_VERSION);
this->setWindowModality(Qt::NonModal);
this->setWindowTitle("DESIGN (" + version + ")");
this->setWindowFlags(Qt::Window | Qt::Tool | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
this->setWindowModality(Qt::NonModal);
setMinimumSize(300,500);
_layout = new QVBoxLayout(this);
_layout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
_layout->setMargin(0);
_layout->setSpacing(0);
//_swap = false;
createToolbar();
createSliderPanel();
createParamConsole();
}
void FMDesignDialog::showEvent(QShowEvent * event)
{
Q_UNUSED(event)
QRect r = RMApp::instance()->pMainWindow->geometry();
r.moveLeft(1480);
r.moveTop(190);
setGeometry(r.right(),r.top(),300,500);
//loadPreset();
}
void FMDesignDialog::createToolbar()
{
_toolbar = new QWidget(this);
_toolbar->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
_toolbar->setFixedHeight(36);
_layout->addWidget(_toolbar);
_toolbar->setStyleSheet("background-color: #818181;");
//_toolbar->setObjectName("test_widget");
QHBoxLayout* toolLayout = new QHBoxLayout(_toolbar);
toolLayout->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
toolLayout->setSpacing(6);
toolLayout->setMargin(2);
_resetButton = _button(_toolbar,toolLayout,"RESET");
_button(_toolbar,toolLayout,"VR");
_button(_toolbar,toolLayout,"WIDE");
_button(_toolbar,toolLayout,"GET");
_button(_toolbar,toolLayout,"SET");
_button(_toolbar,toolLayout,"SWAP");
}
void FMDesignDialog::createSliderPanel()
{
QWidget* info = new QWidget(this);
info->setStyleSheet("background-color: #616161;");
//info->setObjectName("test_widget");
info->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred);
//info->setFixedHeight(48);
_layout->addWidget(info);
//info->setStyleSheet("background-color: #000000;");
QVBoxLayout* infoLayout = new QVBoxLayout(info);
infoLayout->setAlignment(Qt::AlignLeft | Qt::AlignTop);
infoLayout->setSpacing(2);
infoLayout->setMargin(2);
_labels = new QList<QLabel*>();
_sliders = new QList<QSlider*>();
_resetButtons = new QList<QPushButton*>();
_slider(info,infoLayout,"ALPHA");
}
void FMDesignDialog::createParamConsole()
{
_paramTextEdit = new QPlainTextEdit(this);
//_paramTextEdit->setReadOnly(true);
_paramTextEdit->setStyleSheet("font-family: Fixedsys;color : #00FF00;background-color: #111111;border:1px;border-style:solid;border-color:#313131;");
_paramTextEdit->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
_layout->addWidget(_paramTextEdit);
QString scrollStyle = "QScrollBar:vertical\
{\
border-width: 0px;\
border-style: solid;\
background: #3B3B3B;\
width: 10px;\
margin: 21px 0 21px 0;\
}\
QScrollBar::handle:vertical:disabled{background: #3B3B3B;}\
QScrollBar::handle:vertical\
{\
border-width: 0px;\
background: #6A74FF;\
min-height: 25px;\
}\
QScrollBar::add-line:vertical\
{\
border: none;\
background: none;\
height: 20px;\
width: 15px;\
subcontrol-position: bottom;\
subcontrol-origin: margin;\
}\
QScrollBar::sub-line:vertical\
{\
border: none;\
background: none;\
height: 20px;\
width: 15px;\
subcontrol-position: top;\
subcontrol-origin: margin;\
}\
QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical\
{\
background: none;\
}\
QScrollBar::up-arrow:vertical\
{\
border: none;\
background: #5A5A5A;\
}\
QScrollBar::down-arrow:vertical\
{\
border: none;\
background: #5A5A5A;\
}";
_paramTextEdit->verticalScrollBar()->setStyleSheet(scrollStyle);
}
QSlider* FMDesignDialog::_slider(QWidget* parent,QLayout* layout, QString title)
{
QWidget* view = new QWidget(parent);
QHBoxLayout* viewLayout = new QHBoxLayout(view);
viewLayout->setAlignment(Qt::AlignCenter);
layout->addWidget(view);
QLabel* tl = new QLabel(view);
tl->setText(title);
tl->setStyleSheet("font-family: Fixedsys;color : #F0F0F0;");
viewLayout->addWidget(tl);
QSlider* slider = new QSlider(view);
slider->setOrientation(Qt::Horizontal);
slider->setMinimum(0);
slider->setMaximum(100);
slider->setValue(100);
slider->setWindowTitle(title);
connect(slider,SIGNAL(valueChanged(int)),SLOT(onSliderChange(int)));
_sliders->append(slider);
viewLayout->addWidget(slider);
QLabel* label = new QLabel(view);
label->setText("0.500");
label->setStyleSheet("font-family: Fixedsys;color : #F0F0F0;");
_labels->append(label);
viewLayout->addWidget(label);
QPushButton* reset = _button(view,viewLayout,"RS");
_resetButtons->append(reset);
return slider;
}
QPushButton* FMDesignDialog::_button(QWidget* parent,QLayout* layout,QString title)
{
QPushButton* btn = new QPushButton(parent);
btn->setText(title);
btn->setStyleSheet("QPushButton{font-family: Fixedsys;color : white;}"
"QPushButton[enabled=\"false\"]{color : #AAAAAA;}");
btn->setFixedWidth(title.length() * 10);
layout->addWidget(btn);
connect(btn,SIGNAL(clicked()),SLOT(onButton()));
return btn;
}
void FMDesignDialog::onSliderChange(int value)
{
QSlider* slider = qobject_cast<QSlider*>(sender());
int index = _sliders->indexOf(slider);
QLabel* label = _labels->at(index);
QString str;
double v = ((double)value)/((double)100.0);
label->setText(str.sprintf("%.3f",v));
QString key = slider->windowTitle();
if(key == "ALPHA")
{
WindowMain::instance()->alpha->setOpacity(v);
}
}
void FMDesignDialog::onButton()
{
QPushButton* btn = qobject_cast<QPushButton*>(sender());
QString cmd = btn->text().toUpper();
//FAV::OpenGLVideo* opengl = (FAV::OpenGLVideo*)gl();
if(cmd == "RESET")
{
for(int i=0;i<_sliders->count();i++)
{
_sliders->at(i)->setValue(0);
}
}
else if (cmd == "RS")
{
int index = _resetButtons->indexOf(btn);
_sliders->at(index)->setValue(0);
}
}
#endif // DESIGN_LAYOUT_MODE

View File

@@ -0,0 +1,46 @@
#ifndef RM_DESIGN_DIALOG_H
#define RM_DESIGN_DIALOG_H
#if (DESIGN_LAYOUT_MODE)
#include <QDialog>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QPlainTextEdit>
#include <QLineEdit>
#include <QSlider>
class FMDesignDialog : public QDialog
{
Q_OBJECT
public:
static FMDesignDialog* instance(QWidget* parent = nullptr);
private:
QVBoxLayout* _layout;
QWidget* _toolbar;
QPushButton* _resetButton;
QList<QLabel*>* _labels;
QList<QSlider*>* _sliders;
QList<QPushButton*>* _resetButtons;
QPlainTextEdit* _paramTextEdit;
//bool _swap;
explicit FMDesignDialog(QWidget *parent = nullptr);
void showEvent(QShowEvent * event);
void createToolbar();
void createSliderPanel();
void createParamConsole();
QPushButton* _button(QWidget* parent,QLayout* layout,QString title);
QSlider* _slider(QWidget* parent,QLayout* layout, QString title);
signals:
public slots:
void onSliderChange(int value);
void onButton();
};
#endif // DESIGN_LAYOUT_MODE
#endif // RM_DESIGN_DIALOG_H

View File

@@ -0,0 +1,8 @@
#include "rm_test_controls.h"
#if (RM_TESTING)
RMTestControls::RMTestControls(QObject *parent) : QObject(parent)
{
}
#endif

View File

@@ -0,0 +1,25 @@
#ifndef RM_TEST_CONTROLS_H
#define RM_TEST_CONTROLS_H
#if (RM_TESTING)
#include <QObject>
class RMTestControls : public QObject
{
Q_OBJECT
public:
explicit RMTestControls(QObject *parent = nullptr);
static RMTestControls* instance()
{
static RMTestControls * _instance = 0;
if ( _instance == 0 ) {
_instance = new RMTestControls();
}
return _instance;
}
signals:
public slots:
};
#endif
#endif // RM_TEST_CONTROLS_H

View File

@@ -0,0 +1,385 @@
#include "rm_test_dialog.h"
#if (RM_TESTING)
#include <windows.h>
#include <QDebug>
#include <QMainWindow>
#include <QDesktopServices>
#include <QUrl>
#include <QFileDialog>
#include <QStyle>
#include <QMessageBox>
#include <QScrollBar>
#include "../rm_app.h"
#include "../rm_settings.h"
RMDialogTest::RMDialogTest(QWidget *parent) : QDialog(parent)
{
QString version;
version.sprintf("model:%s %d.%d.%d.%d",WINDOW_TITLE,RM_MODEL_VERSION_0,RM_MODEL_VERSION_1,RM_MODEL_VERSION_1,RM_MODEL_SVN_VERSION);
this->setWindowModality(Qt::NonModal);
this->setWindowTitle("DVR TESTER (" + version + ")");
this->setWindowFlags(Qt::Window | Qt::Tool | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
this->setWindowModality(Qt::NonModal);
setMinimumSize(300,500);
_layout = new QVBoxLayout(this);
_layout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
_layout->setMargin(0);
_layout->setSpacing(0);
createToolbar();
createInfoPanel();
createLogConsole();
createFilterEditor();
_process = NULL;
}
void RMDialogTest::createToolbar()
{
_toolbar = new QWidget(this);
_toolbar->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
_toolbar->setFixedHeight(36);
_layout->addWidget(_toolbar);
_toolbar->setStyleSheet("background-color: #818181;");
//_toolbar->setObjectName("test_widget");
QHBoxLayout* toolLayout = new QHBoxLayout(_toolbar);
toolLayout->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
toolLayout->setSpacing(6);
toolLayout->setMargin(2);
QPushButton* btn;
_runButton = button(_toolbar,toolLayout,"RUN");
_runButton->setEnabled(false);
_openButton = button(_toolbar,toolLayout,"OPEN");
_reloadButton = button(_toolbar,toolLayout,"RELOAD");
_stopButton = button(_toolbar,toolLayout,"STOP");
_stopButton->setEnabled(false);
btn = button(_toolbar,toolLayout,"CLEAR");
btn = button(_toolbar,toolLayout,"DIR");
}
void RMDialogTest::createInfoPanel()
{
QWidget* info = new QWidget(this);
info->setStyleSheet("background-color: #616161;");
//info->setObjectName("test_widget");
info->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred);
//info->setFixedHeight(48);
_layout->addWidget(info);
QVBoxLayout* infoLayout = new QVBoxLayout(info);
infoLayout->setAlignment(Qt::AlignLeft | Qt::AlignTop);
infoLayout->setSpacing(2);
infoLayout->setMargin(2);
_scriptLabel = label(info,infoLayout,"Script:","NONE");
_statusLabel = label(info,infoLayout,"Status:","----");
_timerLabel = label(info,infoLayout,"Timer:","00:00:00");
_loopLabel = label(info,infoLayout,"Loop:","000");
}
void RMDialogTest::createFilterEditor()
{
QWidget* filter = new QWidget(this);
filter->setStyleSheet("background-color: #818181;");
_layout->addWidget(filter);
QHBoxLayout* filterLayout = new QHBoxLayout(filter);
filterLayout->setMargin(0);
filterLayout->setSpacing(0);
_filterEdit = new QLineEdit(filter);
_filterEdit->setStyleSheet("font-family: Fixedsys;color : #6666FF;background-color: #111111;border:1px;border-style:solid;border-color:#313131;");
_filterEdit->setText("format=pix_fmts=rgb24,lenscorrection=cx=0.5:cy=0.5:k1=-.8:k2=-.0");
filterLayout->addWidget(_filterEdit);
button(filter,filterLayout,"FA");
button(filter,filterLayout,"FC");
}
void RMDialogTest::createLogConsole()
{
_logTextEdit = new QPlainTextEdit(this);
_logTextEdit->setReadOnly(true);
_logTextEdit->setStyleSheet("font-family: Fixedsys;color : #00FF00;background-color: #111111;border:1px;border-style:solid;border-color:#313131;");
_logTextEdit->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
_layout->addWidget(_logTextEdit);
QString scrollStyle = "QScrollBar:vertical\
{\
border-width: 0px;\
border-style: solid;\
background: #3B3B3B;\
width: 10px;\
margin: 21px 0 21px 0;\
}\
QScrollBar::handle:vertical:disabled{background: #3B3B3B;}\
QScrollBar::handle:vertical\
{\
border-width: 0px;\
background: #6A74FF;\
min-height: 25px;\
}\
QScrollBar::add-line:vertical\
{\
border: none;\
background: none;\
height: 20px;\
width: 15px;\
subcontrol-position: bottom;\
subcontrol-origin: margin;\
}\
QScrollBar::sub-line:vertical\
{\
border: none;\
background: none;\
height: 20px;\
width: 15px;\
subcontrol-position: top;\
subcontrol-origin: margin;\
}\
QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical\
{\
background: none;\
}\
QScrollBar::up-arrow:vertical\
{\
border: none;\
background: #5A5A5A;\
}\
QScrollBar::down-arrow:vertical\
{\
border: none;\
background: #5A5A5A;\
}";
_logTextEdit->verticalScrollBar()->setStyleSheet(scrollStyle);
}
QLabel* RMDialogTest::label(QWidget* parent,QLayout* layout,QString title,QString text)
{
QWidget* row = new QWidget(parent);
layout->addWidget(row);
QHBoxLayout* hLayout = new QHBoxLayout(row);
hLayout->setMargin(0);
hLayout->setSpacing(0);
hLayout->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
QLabel* label = new QLabel(row);
label->setText(title);
label->setStyleSheet("font-family: Fixedsys;color : #F0F0F0;");
hLayout->addWidget(label);
label->setFixedWidth(72);
QLabel* textLabel = new QLabel(row);
textLabel->setText(text);
textLabel->setStyleSheet("font-family: Fixedsys;color : white;");
hLayout->addWidget(textLabel);
return textLabel;
}
QPushButton* RMDialogTest::button(QWidget* parent,QLayout* layout,QString title)
{
QPushButton* btn = new QPushButton(parent);
btn->setText(title);
//btn->setStyleSheet("font-family: Arial;font-size: 9px;");
btn->setStyleSheet("QPushButton{font-family: Fixedsys;color : white;}"
"QPushButton[enabled=\"false\"]{color : #AAAAAA;}");
btn->setFixedWidth(title.length() * 10);
layout->addWidget(btn);
connect(btn,SIGNAL(clicked()),SLOT(onButton()));
return btn;
}
void RMDialogTest::onButton()
{
QPushButton* btn = qobject_cast<QPushButton*>(sender());
QString cmd = btn->text().toUpper();
if(cmd == "DIR")
{
QDesktopServices::openUrl(QUrl::fromLocalFile(RMApp::instance()->appPath(RMApp::SCRIPT)));
}
else if(cmd == "OPEN")
{
QString fileName = QFileDialog::getOpenFileName(
this,
"OPEN",
RMApp::instance()->appPath(RMApp::SCRIPT),
"SCRIPT (*.txt)");
if(fileName.length() > 0)
{
openScript(fileName);
}
}
else if(cmd == "RELOAD" && _process != NULL)
{
openScript(_process->filePath);
}
else if(cmd == "CLEAR")
{
_logTextEdit->clear();
}
else if (cmd == "FA")
{
RMPlayer::instance()->applyTestFilter(_filterEdit->text());
}
else if (cmd == "FC")
{
RMPlayer::instance()->applyTestFilter("");
}
}
void RMDialogTest::onStatusMessage(QString message)
{
_statusLabel->setText(message);
}
void RMDialogTest::clearProcess()
{
if (_process != NULL)
{
disconnect(_runButton,SIGNAL(clicked()),this,SLOT(onRunProcess()));
disconnect(_stopButton,SIGNAL(clicked()),this,SLOT(onStopProcess()));
disconnect(_process,SIGNAL(statusChange(QString)),this,SLOT(onStatusMessage(QString)));
disconnect(_process,SIGNAL(log(QString)),this,SLOT(onLog(QString)));
disconnect(_process,SIGNAL(error(QString)),this,SLOT(onError(QString)));
delete _process;
_process = NULL;
}
}
void RMDialogTest::openScript(QString path)
{
clearProcess();
_process = new RMTestProcess(this,path);
connect(_runButton,SIGNAL(clicked()),SLOT(onRunProcess()));
connect(_stopButton,SIGNAL(clicked()),SLOT(onStopProcess()));
connect(_process,SIGNAL(statusChange(QString)),this,SLOT(onStatusMessage(QString)));
connect(_process,SIGNAL(log(QString)),this,SLOT(onLog(QString)));
connect(_process,SIGNAL(error(QString)),this,SLOT(onError(QString)));
refreshRunStopButton();
QFileInfo fi(path);
_scriptLabel->setText(fi.baseName() + "(" + QString::number(_process->count()) + ")");
RMSettings::instance()->setLastScript(path);
}
void RMDialogTest::refreshRunStopButton()
{
_runButton->setEnabled((_process != NULL && _process->isRunning() == false));
_runButton->style()->unpolish(_runButton);
_runButton->style()->polish(_runButton);
_openButton->setEnabled((_process == NULL || _process->isRunning() == false));
_openButton->style()->unpolish(_openButton);
_openButton->style()->polish(_openButton);
_reloadButton->setEnabled((_process != NULL && _process->isRunning() == false));
_reloadButton->style()->unpolish(_reloadButton);
_reloadButton->style()->polish(_reloadButton);
_stopButton->setEnabled((_process != NULL && _process->isRunning() == true));
_stopButton->style()->unpolish(_stopButton);
_stopButton->style()->polish(_stopButton);
_statusLabel->setText((_process != NULL && _process->isRunning()) ? "running" : "stopped");
}
void RMDialogTest::onRunProcess()
{
if(_process == NULL || _process->isRunning())
{
return;
}
connect(_process,SIGNAL(timer(qint64)),SLOT(onTimer(qint64)));
connect(_process,SIGNAL(loopChange(int)),SLOT(onLoopChange(int)));
_process->onRun();
refreshRunStopButton();
}
void RMDialogTest::onStopProcess()
{
if(_process == NULL || _process->isRunning() == false)
{
return;
}
disconnect(_process,SIGNAL(timer(qint64)),this,SLOT(onTimer(qint64)));
disconnect(_process,SIGNAL(loopChange(int)),this,SLOT(onLoopChange(int)));
_process->onStop();
refreshRunStopButton();
}
void RMDialogTest::onTimer(qint64 msec)
{
int sec = msec;
int h = 0;
int m = 0;
int s = 0;
if(sec > 3600000)
{
h = sec / 3600000;
sec = sec - (h * 3600000);
}
if(sec > 60)
{
m = sec / 60000;
sec = sec - (m * 60000);
}
s = sec;
QString timeString;
timeString.sprintf("%02d:%02d:%04.1f",h,m,(double)s/1000.0);
_timerLabel->setText(timeString);
}
void RMDialogTest::onLoopChange(int loop)
{
QString str;
str.sprintf("%03d",loop);
_loopLabel->setText(str);
}
void RMDialogTest::onLog(QString log)
{
_logTextEdit->appendPlainText(log);
}
void RMDialogTest::onError(QString message)
{
// 일단 정지
// if(RMPlayer::instance()->playerF()->isPaused() == false)
// {
// RMPlayer::instance()->onPlayOrPause();
// }
::Beep(500,1000);
onStopProcess();
clearProcess();
refreshRunStopButton();
QMessageBox::warning(this,"ERROR",message,QMessageBox::Ok,QMessageBox::NoButton);
}
RMDialogTest* RMDialogTest::instance(QWidget* parent)
{
static RMDialogTest * _instance = NULL;
if ( _instance == NULL )
{
_instance = new RMDialogTest(parent);
}
return _instance;
}
void RMDialogTest::showEvent(QShowEvent * event)
{
Q_UNUSED(event)
QRect r = RMApp::instance()->pMainWindow->geometry();
r.moveLeft(460);
r.moveTop(190);
setGeometry(r.right(),r.top(),300,500);
QString script = RMSettings::instance()->lastScript();
if(script.length() > 0 && QFile::exists(script))
{
openScript(script);
}
}
#endif // #if (RM_TESTING)

View File

@@ -0,0 +1,67 @@
#ifndef RM_TEST_DIALOG_H
#define RM_TEST_DIALOG_H
#if (RM_TESTING)
#include <QDialog>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QPlainTextEdit>
#include <QLineEdit>
#include "rm_test_process.h"
class RMDialogTest : public QDialog
{
Q_OBJECT
public:
static RMDialogTest* instance(QWidget* parent = nullptr);
private:
QVBoxLayout* _layout;
RMTestProcess* _process;
QWidget* _toolbar;
QPushButton* _openButton;
QPushButton* _runButton;
QPushButton* _stopButton;
QPushButton* _reloadButton;
QLabel* _scriptLabel;
QLabel* _statusLabel;
QLabel* _timerLabel;
QLabel* _loopLabel;
QPlainTextEdit* _logTextEdit;
QLineEdit* _filterEdit;
explicit RMDialogTest(QWidget *parent = nullptr);
void showEvent(QShowEvent * event);
void createToolbar();
QPushButton* button(QWidget* parent,QLayout* layout,QString title);
void createInfoPanel();
QLabel* label(QWidget* parent,QLayout* layout,QString title,QString text);
void createLogConsole();
void createFilterEditor();
void refreshRunStopButton();
void clearProcess();
void openScript(QString path);
void beep();
signals:
public slots:
void onButton();
void onRunProcess();
void onStopProcess();
void onTimer(qint64 msec);
void onLoopChange(int loop);
void onStatusMessage(QString message);
void onLog(QString log);
void onError(QString message);
};
#endif // #if (RM_TESTING)
#endif // RM_TEST_DIALOG_H

View File

@@ -0,0 +1,461 @@
#include "rm_test_process.h"
#if (RM_TESTING)
//#include <windows.h>
#include <QDebug>
#include <QFile>
#include <QMessageBox>
#include <QMouseEvent>
#include <QFileInfo>
#include "../data/rm_video_list.h"
#include "../ui/window_main.h"
#include "../ui/rm_frame_right.h"
#include "../ui/rm_frame_left.h"
#include "../ui/rm_frame_list.h"
#include "../ui/rm_frame_play.h"
#include "../ui/rm_frame_slider.h"
#include "../ui/rm_button.h"
#include "../ui/rm_play_slider.h"
#include "../ui/rm_slider.h"
#include "../ui/rm_frame_video_sub.h"
#include "../ui/rm_frame_video_main.h"
RMTestProcess::RMTestProcess(QObject *parent,QString path) : QObject(parent)
{
_optionLogDrawFrame = false;
_optionLogFileName = false;
_timer = NULL;
_running = false;
_processDelay = 1000; // 기본값 1초?
_loop = 0;
_nextFileTimeout = -1;
_nextFileWatchTimer = NULL;
load(path);
// PLAY_EVENT
connect(RMPlayer::instance(),SIGNAL(playEvent(PLAY_EVENT,RMVideoItem*)),SLOT(onPlayEvent(PLAY_EVENT,RMVideoItem*)));
}
void RMTestProcess::onPlayEvent(PLAY_EVENT event,RMVideoItem* item)
{
if(_running == false) {
return;
}
// LOG 처리
if (event == PLAY_DID_LOADED)
{
QFileInfo f1(item->filePath);
QString name = f1.baseName();
#if !(DUAL_CH_FILE)
if(name.endsWith("_1") || name.endsWith("_2"))
{
name = name.remove(name.length()-3,2);
}
#endif
lastFileName = name;
// 파일명 표시 로그
if(_optionLogFileName)
{
//QApplication::beep();
emit log("->" + name);
}
if(_nextFileTimeout > 0)
{
if(_nextFileWatchTimer != NULL)
{
_nextFileWatchTimer->stop();
delete _nextFileWatchTimer;
_nextFileWatchTimer = NULL;
}
_nextFileWatchTimer = new QTimer(this);
_nextFileWatchTimer->setSingleShot(true);
_nextFileWatchTimer->setInterval(_nextFileTimeout);
connect(_nextFileWatchTimer,SIGNAL(timeout()),SLOT(onFileTimeout()));
_nextFileWatchTimer->start();
}
}
else if(event == PLAY_DID_CLEARED)
{
// DRAW FRAME COUNT 표시
if(_optionLogDrawFrame)
{
int f = RMPlayer::instance()->playerF()->displyedFrameCount();
#if !(SINGLE_CH_VIEWER)
int r = RMPlayer::instance()->playerR()->displyedFrameCount();
if(f > 0 || r > 0)
#else
if(f > 0)
#endif
{
QString str;
#if (SINGLE_CH_VIEWER)
str.sprintf("DRAW FRAME:F:%d",RMPlayer::instance()->playerF()->displyedFrameCount());
#else
str.sprintf("DRAW FRAME:F:%d,R:%d",RMPlayer::instance()->playerF()->displyedFrameCount(),RMPlayer::instance()->playerR()->displyedFrameCount());
#endif
emit log(str);
#if (SINGLE_CH_VIEWER)
if(f <= 0)
#else
if(f <= 0 || r <= 0)
#endif
{
_running = false;
emit error(str);
return;
}
}
}
}
if(_waitPlayEvent == event)
{
// 다음 프로세스로 이동
QTimer::singleShot(_processDelay,Qt::PreciseTimer,this,SLOT(onProcessNext()));
_waitPlayEvent = PLAY_UNDEFINED;
}
}
void RMTestProcess::onFileTimeout()
{
if(_nextFileWatchTimer != NULL)
{
_nextFileWatchTimer->stop();
delete _nextFileWatchTimer;
_nextFileWatchTimer = NULL;
}
_running = false;
emit error("FILE TIME OUT");
}
void RMTestProcess::load(QString path)
{
QFile file(path);
if(!file.open(QIODevice::ReadOnly)) {
QMessageBox::information(0, "error", file.errorString());
}
QTextStream in(&file);
while(!in.atEnd()) {
QString line = in.readLine();
// comment 처리
if(line.length() < 2 || line.startsWith("#")) {
continue;
}
// 전체 옵션 처리
if(line.startsWith("$"))
{
if(line.toUpper() == "$LOG_DRAW_FRAME")
{
_optionLogDrawFrame = true;
}
else if(line.toUpper() == "$LOG_FILE_NAME")
{
_optionLogFileName = true;
}
else if(line.toUpper().startsWith("$PROCESS_DELAY") && line.contains("="))
{
_processDelay = line.split("=").last().toInt();
}
else if(line.toUpper().startsWith("$WATCH_TIMEOUT") && line.contains("="))
{
_nextFileTimeout = line.split("=").last().toInt();
}
continue;
}
QStringList fields = line.split(",");
processes.append(fields);
//model->appendRow(fields);
}
file.close();
filePath = path;
_running = false;
}
int RMTestProcess::count()
{
return processes.count();
}
bool RMTestProcess::isRunning()
{
return _running;
}
void RMTestProcess::onRun()
{
// foreach (QStringList process, processes) {
// qInfo() << "CMD:" << process.first() << ":" << process.last();
// }
_processIndex = 0;
_running = true;
elapsedTimer.start();
_timer = new QTimer(this);
_timer->setSingleShot(false);
_timer->setInterval(100);
connect(_timer,SIGNAL(timeout()),SLOT(onSyncTime()));
_timer->start();
//qInfo() << "TIMER START";
_loop = 1;
emit loopChange(_loop);
QTimer::singleShot(_processDelay,Qt::PreciseTimer,this,SLOT(onProcessNext()));
}
void RMTestProcess::makeClick(QWidget* control,float x)
{
//qInfo() << __FUNCTION__ << control << x;
QPoint pos = control->rect().center();
if(x > 0.0f)
{
pos.setX( (int)(((float)control->rect().size().width()) * (float)x));
}
//qInfo() << __FUNCTION__ << pos << " global:" << control->mapToGlobal(pos);
QMouseEvent* pEvent = new QMouseEvent(QEvent::MouseButtonPress,
pos,
control->mapToGlobal(pos),
Qt::LeftButton,
Qt::LeftButton,
Qt::NoModifier);
QApplication::instance()->sendEvent(control,pEvent);
QThread::msleep((rand() % 20) + 10);
pos.setX(pos.x() + ((rand() % 4) - 2));
pos.setY(pos.y() + ((rand() % 4) - 2));
QMouseEvent* pEventM = new QMouseEvent(QEvent::MouseMove,
pos,
control->mapToGlobal(pos),
Qt::LeftButton,
Qt::LeftButton,
Qt::NoModifier);
QApplication::instance()->sendEvent(control,pEventM);
QThread::msleep((rand() % 20) + 10);
pos.setX(pos.x() + ((rand() % 4) - 2));
pos.setY(pos.y() + ((rand() % 4) - 2));
QMouseEvent* pEvent2 = new QMouseEvent(QEvent::MouseButtonRelease,
pos,
control->mapToGlobal(pos),
Qt::LeftButton,
Qt::LeftButton,
Qt::NoModifier);
QApplication::instance()->sendEvent(control,pEvent2);
}
// rand(0.7-0.9) 구문 처리
float RMTestProcess::parseRandFloat(QString range)
{
if(range.startsWith("RAND(") && range.endsWith(")") && range.contains("-"))
{
QString cleared = range.remove(0,5); // "RAND("
cleared = cleared.remove(cleared.length()-1,1); // ")"
QStringList ls = cleared.split("-");
int f1 = (int)(ls.first().toFloat() * 1000.0f);
int f2 = (int)(ls.last().toFloat() * 1000.0f);
int res = (rand() % (f2 - f1)) + f1;
return ((float)res) / 1000.0f;
}
return range.toFloat();
}
int RMTestProcess::parseRandInt(QString range)
{
if(range.startsWith("RAND(") && range.endsWith(")") && range.contains("-"))
{
QString cleared = range.remove(0,5);
cleared = cleared.remove(cleared.length()-1,1); // ")"
QStringList ls = cleared.split("-");
int f1 = ls.first().toInt();
int f2 = ls.last().toInt();
int res = (rand() % (f2 - f1)) + f1;
return res;
}
return range.toInt();
}
void RMTestProcess::onProcessNext()
{
if(_running == false)
{
//qInfo() << "STOP PROCESS";
return;
}
if(_processIndex >= processes.count())
{
_processIndex = 0;
_loop += 1;
emit loopChange(_loop);
}
QStringList list = processes.at(_processIndex);
QString cmd = list.first().toUpper();
list.removeFirst();
qint64 wait = _processDelay;
QMap<QString,QString> params;
foreach (QString param, list)
{
QStringList cmdp = param.split("=");
// 2의 배수 cmd = param
if (cmdp.count() % 2 != 0)
{
continue;
}
// PARAMETER 처리
for(int i=0;i<cmdp.count()/2;i++)
{
QString scmd = cmdp.at((i*2)+0).toUpper();
QString sparam = cmdp.at((i*2)+1).toUpper();
params.insert(scmd,sparam);
}
}
// 프로세스 추가
_processIndex += 1;
// LOOP 확인하여 처리
if(params.contains("LOOP"))
{
int loop = params.value("LOOP","0").toInt();
if(_loop != loop)
{
QTimer::singleShot(0,Qt::PreciseTimer,this,SLOT(onProcessNext()));
return;
}
}
// 대기시작 확인
if(params.contains("WAIT"))
{
wait = parseRandInt(params.value("WAIT","0"));
}
QString statusMessage = cmd;
WindowMain* pWin = (WindowMain*)RMApp::instance()->pMainWindow;
// 다음 명령 실행 or 대기
bool runNext = true;
// 명령 실행
if(cmd == "OPEN" && params.contains("PATH"))
{
// 연결 -> onLoadingListDone 에서 처리
connect(RMVideoFileList::instance(),SIGNAL(listUpdateEnd(bool)),this,SLOT(onLoadingListEnd(bool)));
pWin->_frameRight->frameList->openFolder(params.value("PATH"));
runNext = false;
}
else if(cmd == "CLICK" && params.contains("CONTROL"))
{
QString buttonName = params.value("CONTROL");
statusMessage += (" " + buttonName);
if(buttonName == "PLAY")
{
makeClick(pWin->_frameLeft->framePlay->playButton);
_waitPlayEvent = PLAY_DID_PLAYED; // 재생 시작까지 대기
runNext = false;
}
else if (buttonName == "SLIDER")
{
float x = 0.5;
if(params.contains("X"))
{
x = parseRandFloat(params.value("X"));
}
makeClick(pWin->_frameLeft->frameSlider->playSlider->slider,x);
}
else if (buttonName == "SWAP")
{
makeClick(pWin->_frameRight->frameVideoSub->_toggleButton);
}
else if (buttonName == "VOLUME")
{
float x = 0.5;
if(params.contains("X"))
{
x = parseRandFloat(params.value("X"));
}
makeClick(pWin->_frameLeft->frameSlider->volumeSlider,x);
}
//CLICK,button=play)
}
else if(cmd == "WAIT" && params.contains("FOR"))
{
QString eventName = params.value("FOR");
if(eventName == "PLAY_DID_PLAYED")
{
statusMessage += " FOR NEXT PLAY";
_waitPlayEvent = PLAY_DID_PLAYED;
}
else if(eventName == "PLAY_DID_LOADED")
{
statusMessage += " FOR NEXT LOADED";
_waitPlayEvent = PLAY_DID_LOADED;
}
else if(eventName == "PLAY_DID_CLEARED")
{
statusMessage += " FOR NEXT CLEARED";
_waitPlayEvent = PLAY_DID_CLEARED;
}
else if(eventName == "PLAY_CUSTOM_EVENT")
{
statusMessage += " FOR NEXT CUSTOM";
_waitPlayEvent = PLAY_CUSTOM_EVENT;
}
runNext = false;
}
emit statusChange(statusMessage);
// 다음 명령 실행
if(runNext == true)
{
QTimer::singleShot(wait,Qt::PreciseTimer,this,SLOT(onProcessNext()));
}
}
void RMTestProcess::onSyncTime()
{
//qInfo() << __FUNCTION__;
emit timer(elapsedTimer.elapsed());
}
void RMTestProcess::onStop()
{
elapsedTimer.invalidate();
_running = false;
}
void RMTestProcess::onLoadingListEnd(bool bLoading)
{
Q_UNUSED(bLoading);
disconnect(RMVideoFileList::instance(),SIGNAL(listUpdateEnd(bool)),this,SLOT(onLoadingListEnd(bool)));
// 다음 프로세스로 이동
QTimer::singleShot(_processDelay,Qt::PreciseTimer,this,SLOT(onProcessNext()));
}
#endif // #if (RM_TESTING)

View File

@@ -0,0 +1,73 @@
#ifndef RM_TEST_PROCESS_H
#define RM_TEST_PROCESS_H
#if (RM_TESTING)
#include <QObject>
#include <QTimer>
#include <QElapsedTimer>
#include "../core/rm_player.h"
#include "../core/rm_player_base.h"
//#define DVR_TESTER_VERSION "0.2"
class RMTestProcess : public QObject
{
Q_OBJECT
public:
explicit RMTestProcess(QObject *parent,QString path);
bool isRunning();
QString filePath;
int count();
// OPTION
private:
bool _optionLogDrawFrame; // 프레임 DRAW 확인
bool _optionLogFileName; // 재생 파일명 확인
int _nextFileTimeout; // 다음파일 대기
QTimer* _nextFileWatchTimer; // 다음파일 대기 타이머
private:
QString lastFileName;
private:
void load(QString path);
QList<QStringList> processes;
bool _running;
int _loop;
QTimer* _timer;
qint64 _processDelay;
QElapsedTimer elapsedTimer;
int _processIndex;
void connectEvents();
void makeClick(QWidget* control,float x = -1.0f);
//bool _waitForEvent;
PLAY_EVENT _waitPlayEvent; // 대기중 플레이 이벤트
float parseRandFloat(QString range);
int parseRandInt(QString range);
signals:
void timer(qint64 timer);
void loopChange(int loop);
void statusChange(QString message);
void log(QString log);
void error(QString error);
public slots:
void onRun();
void onStop();
void onSyncTime();
void onProcessNext();
void onLoadingListEnd(bool bLoading);
void onPlayEvent(PLAY_EVENT event,RMVideoItem* item);
void onFileTimeout();
};
#endif
#endif // RM_TEST_PROCESS_H

View File

@@ -0,0 +1,8 @@
#include "rm_tester.h"
#if (RM_LOG_LEVEL > RM_LOG_LEVEL_NONE)
QElapsedTimer RMTester::timer0 = QElapsedTimer();
QElapsedTimer RMTester::timer1 = QElapsedTimer();
QElapsedTimer RMTester::timer2 = QElapsedTimer();
#endif

View File

@@ -0,0 +1,96 @@
#ifndef RM_TESTER_H
#define RM_TESTER_H
// 로그 처리 레벨
#define RM_LOG_LEVEL_NONE 0
#define RM_LOG_LEVEL_TEST 1
#define RM_LOG_LEVEL_ERROR 2
#define RM_LOG_LEVEL_DEBUG 3
#define RM_LOG_LEVEL_INFO 4
// 문제가 32 로 probe 되지 않는 파일
// E:/EVENT/2/NEF_190622-172014-000001_2.avi
// E:/EVENT/2/NEF_190622-181637-000001_2.avi
// E:/EVENT/2/NEF_190622-192232-000001_2.avi
// E:/EVENT/2/NEF_190624-103821-000009_2.avi
// E:/EVENT/2/NEF_190624-105244-000032_2.avi
// 로그 레벨 설정
#define RM_LOG_LEVEL RM_LOG_LEVEL_TEST
// 레벨에 따른 감추기
#if defined(SUPPRESS_ALL_TESTER) || (RM_LOG_LEVEL < RM_LOG_LEVEL_INFO)
#define LOG_INFO /##/
#else
#define LOG_INFO qInfo()
#endif
#if defined(SUPPRESS_ALL_TESTER) || (RM_LOG_LEVEL < RM_LOG_LEVEL_DEBUG)
#define LOG_DEBUG /##/
#else
#define LOG_DEBUG qInfo()
#endif
#if defined(SUPPRESS_ALL_TESTER) || (RM_LOG_LEVEL < RM_LOG_LEVEL_ERROR)
#define LOG_ERROR /##/
#else
#define LOG_ERROR qInfo()
#endif
#if defined(SUPPRESS_ALL_TESTER) || (RM_LOG_LEVEL != RM_LOG_LEVEL_TEST)
#define LOG_TEST /##/
#else
#define LOG_TEST qInfo() << __FUNCTION__
#endif
// 커스텀 로그 설정
// 비디오 프로파일 로그
#define PROFILE_VIDEO_FILE_LOADING 0
#define PROFILE_VIDEO_FILE_LOADING_AUTOPLAY 0
#define PROFILE_TESTER_TIMER 1
#if (RM_LOG_LEVEL > RM_LOG_LEVEL_NONE)
#if !defined(SUPPRESS_ALL_TESTER) && (PROFILE_TESTER_TIMER)
#define TIMER_START RMTester::timer0.start();
#define TIMER_NOW qInfo() << __FUNCTION__ << RMTester::timer0.elapsed() << "ms"
#endif
// 비디오 개별 파일 로딩 테스트
#if !defined(SUPPRESS_ALL_TESTER) && (PROFILE_VIDEO_FILE_LOADING)
#define LOG_VLOAD qInfo()
#define LOG_VLOAD_TS RMTester::timer0.start()
#define LOG_VLOAD_T RMTester::timer0.elapsed() << "ms"
#define LOG_VLOAD_TS2 RMTester::timer1.start()
#define LOG_VLOAD_T2 RMTester::timer1.elapsed() << "ms"
#else
#define LOG_VLOAD /##/
#define LOG_VLOAD_TS /##/
#define LOG_VLOAD_T /##/
#define LOG_VLOAD_TS2 /##/
#define LOG_VLOAD_T2 /##/
#endif
// 클래스
#include <QElapsedTimer>
#include <QObject>
class RMTester : public QObject
{
Q_OBJECT
public:
// 최대 3개의 level timer 사용
static QElapsedTimer timer0;
static QElapsedTimer timer1;
static QElapsedTimer timer2;
};
#endif // (RM_LOG_LEVEL > RM_LOG_LEVEL_NONE)
#endif // RM_TESTER_H

View File

@@ -0,0 +1,32 @@
#include "rm_testing.h"
#if (RM_TESTING)
#include <QMouseEvent>
#include <QDebug>
#include <QCursor>
RMTesting::RMTesting(QObject *parent) : QObject(parent)
{
//qInfo() << __FUNCTION__;
}
bool RMTesting::eventFilter(QObject* object, QEvent* event)
{
if(event->type() == QEvent::MouseButtonPress)
{
if(QCursor::pos() == mouse && mouseFilterTimer.elapsed() < 10)
{
return false;
}
mouseFilterTimer.start();
mouse = QCursor::pos();
int x = QCursor::pos().x();
int y = QCursor::pos().y();
qInfo() << "MP -> (" + QString::number(x) + "," + QString::number(y) + ")" << object;
return false; // make it unhandled and sent to other filters.
}
else
{
}
return false;
}
#endif

View File

@@ -0,0 +1,34 @@
#ifndef RM_TESTING_H
#define RM_TESTING_H
#if (RM_TESTING)
#include <QObject>
#include <QPoint>
#include <QElapsedTimer>
class RMTesting : public QObject
{
Q_OBJECT
public:
explicit RMTesting(QObject *parent = nullptr);
static RMTesting* instance()
{
static RMTesting * _instance = 0;
if ( _instance == 0 ) {
_instance = new RMTesting();
}
return _instance;
}
private:
QElapsedTimer mouseFilterTimer;
QPoint mouse;
protected:
bool eventFilter(QObject* object, QEvent* event);
signals:
public slots:
};
#endif // RM_TESTING
#endif // RM_TESTING_H

View File

@@ -0,0 +1,383 @@
#include "rm_tune360_dialog.h"
#if (TUNE_360)
#include "../fav/OpenGLVideo.h"
#include <windows.h>
#include <QDebug>
#include <QMainWindow>
#include <QDesktopServices>
#include <QUrl>
#include <QFileDialog>
#include <QStyle>
#include <QMessageBox>
#include <QScrollBar>
#include "../rm_app.h"
#include "../rm_settings.h"
#include "../core/rm_player.h"
//#include "../core/rm_player.h"
//#include "../core/rm_play_process.h"
#define TUNE_360_RANGE 1000
#define TUNE_360_RATIO_Y 20
#define TUNE_360_RATIO_R 4
#define TUNE_360_RATIO_X 5
#define TUNE_360_RATIO_AR 20
#define TUNE_360_RATIO_RB 2
RMTune360Dialog::RMTune360Dialog(QWidget *parent) : QDialog(parent)
{
QString version;
version.sprintf("model:%s %d.%d.%d.%d",WINDOW_TITLE,RM_MODEL_VERSION_0,RM_MODEL_VERSION_1,RM_MODEL_VERSION_1,RM_MODEL_SVN_VERSION);
this->setWindowModality(Qt::NonModal);
this->setWindowTitle("360 TUNE (" + version + ")");
this->setWindowFlags(Qt::Window | Qt::Tool | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
this->setWindowModality(Qt::NonModal);
setMinimumSize(300,500);
_layout = new QVBoxLayout(this);
_layout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
_layout->setMargin(0);
_layout->setSpacing(0);
_swap = false;
createToolbar();
createSliderPanel();
createParamConsole();
}
RMTune360Dialog* RMTune360Dialog::instance(QWidget* parent)
{
static RMTune360Dialog * _instance = NULL;
if ( _instance == NULL )
{
_instance = new RMTune360Dialog(parent);
}
return _instance;
}
void RMTune360Dialog::showEvent(QShowEvent * event)
{
Q_UNUSED(event)
QRect r = RMApp::instance()->pMainWindow->geometry();
r.moveLeft(1420);
r.moveTop(190);
setGeometry(r.right(),r.top(),300,500);
loadPreset();
}
void RMTune360Dialog::createToolbar()
{
_toolbar = new QWidget(this);
_toolbar->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
_toolbar->setFixedHeight(36);
_layout->addWidget(_toolbar);
_toolbar->setStyleSheet("background-color: #818181;");
//_toolbar->setObjectName("test_widget");
QHBoxLayout* toolLayout = new QHBoxLayout(_toolbar);
toolLayout->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
toolLayout->setSpacing(6);
toolLayout->setMargin(2);
_resetButton = _button(_toolbar,toolLayout,"RESET");
_button(_toolbar,toolLayout,"VR");
_button(_toolbar,toolLayout,"WIDE");
_button(_toolbar,toolLayout,"GET");
_button(_toolbar,toolLayout,"SET");
_button(_toolbar,toolLayout,"SWAP");
}
void RMTune360Dialog::createSliderPanel()
{
QWidget* info = new QWidget(this);
info->setStyleSheet("background-color: #616161;");
//info->setObjectName("test_widget");
info->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred);
//info->setFixedHeight(48);
_layout->addWidget(info);
//info->setStyleSheet("background-color: #000000;");
QVBoxLayout* infoLayout = new QVBoxLayout(info);
infoLayout->setAlignment(Qt::AlignLeft | Qt::AlignTop);
infoLayout->setSpacing(2);
infoLayout->setMargin(2);
_labels = new QList<QLabel*>();
_sliders = new QList<QSlider*>();
_resetButtons = new QList<QPushButton*>();
#if (TUNE4)
_slider(info,infoLayout,"LX[0][0]",TUNE_360_RATIO_X);
_slider(info,infoLayout,"LY[1][0]",TUNE_360_RATIO_Y);
_slider(info,infoLayout,"LRX[2][0]",TUNE_360_RATIO_R);
_slider(info,infoLayout,"LRY[3][0]",TUNE_360_RATIO_R);
_slider(info,infoLayout,"RX[0][1]",TUNE_360_RATIO_X);
_slider(info,infoLayout,"RY[1][1]",TUNE_360_RATIO_Y);
_slider(info,infoLayout,"RRX[2][1]",TUNE_360_RATIO_R);
_slider(info,infoLayout,"RRY[3][1]",TUNE_360_RATIO_R);
_slider(info,infoLayout,"RX2[0][2]",TUNE_360_RATIO_X);
_slider(info,infoLayout,"RY2[1][2]",TUNE_360_RATIO_X);
_slider(info,infoLayout,"RRX2[2][2]",TUNE_360_RATIO_R);
_slider(info,infoLayout,"RRY2[3][2]",TUNE_360_RATIO_RB);
#else
_slider(info,infoLayout,"LX",TUNE_360_RATIO_X);
_slider(info,infoLayout,"LY",TUNE_360_RATIO_Y);
_slider(info,infoLayout,"LR",TUNE_360_RATIO_R);
_slider(info,infoLayout,"RX",TUNE_360_RATIO_X);
_slider(info,infoLayout,"RY",TUNE_360_RATIO_Y);
_slider(info,infoLayout,"RR",TUNE_360_RATIO_R);
_slider(info,infoLayout,"AR",TUNE_360_RATIO_AR);
_slider(info,infoLayout,"ARY",TUNE_360_RATIO_AR);
#endif
}
void RMTune360Dialog::createParamConsole()
{
_paramTextEdit = new QPlainTextEdit(this);
//_paramTextEdit->setReadOnly(true);
_paramTextEdit->setStyleSheet("font-family: Fixedsys;color : #00FF00;background-color: #111111;border:1px;border-style:solid;border-color:#313131;");
_paramTextEdit->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
_layout->addWidget(_paramTextEdit);
QString scrollStyle = "QScrollBar:vertical\
{\
border-width: 0px;\
border-style: solid;\
background: #3B3B3B;\
width: 10px;\
margin: 21px 0 21px 0;\
}\
QScrollBar::handle:vertical:disabled{background: #3B3B3B;}\
QScrollBar::handle:vertical\
{\
border-width: 0px;\
background: #6A74FF;\
min-height: 25px;\
}\
QScrollBar::add-line:vertical\
{\
border: none;\
background: none;\
height: 20px;\
width: 15px;\
subcontrol-position: bottom;\
subcontrol-origin: margin;\
}\
QScrollBar::sub-line:vertical\
{\
border: none;\
background: none;\
height: 20px;\
width: 15px;\
subcontrol-position: top;\
subcontrol-origin: margin;\
}\
QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical\
{\
background: none;\
}\
QScrollBar::up-arrow:vertical\
{\
border: none;\
background: #5A5A5A;\
}\
QScrollBar::down-arrow:vertical\
{\
border: none;\
background: #5A5A5A;\
}";
_paramTextEdit->verticalScrollBar()->setStyleSheet(scrollStyle);
}
QSlider* RMTune360Dialog::_slider(QWidget* parent,QLayout* layout, QString title, float ratio)
{
QWidget* view = new QWidget(parent);
QHBoxLayout* viewLayout = new QHBoxLayout(view);
viewLayout->setAlignment(Qt::AlignCenter);
layout->addWidget(view);
QLabel* tl = new QLabel(view);
tl->setText(title);
tl->setStyleSheet("font-family: Fixedsys;color : #F0F0F0;");
viewLayout->addWidget(tl);
QSlider* slider = new QSlider(view);
slider->setOrientation(Qt::Horizontal);
slider->setMinimum(-TUNE_360_RANGE);
slider->setMaximum(TUNE_360_RANGE);
slider->setValue(0);
connect(slider,SIGNAL(valueChanged(int)),SLOT(onSliderChange(int)));
_sliders->append(slider);
viewLayout->addWidget(slider);
QLabel* label = new QLabel(view);
label->setText("0.000");
label->setStyleSheet("font-family: Fixedsys;color : #F0F0F0;");
_labels->append(label);
viewLayout->addWidget(label);
QPushButton* reset = _button(view,viewLayout,"RS");
_resetButtons->append(reset);
_ratios.append(ratio);
return slider;
}
QPushButton* RMTune360Dialog::_button(QWidget* parent,QLayout* layout,QString title)
{
QPushButton* btn = new QPushButton(parent);
btn->setText(title);
//btn->setStyleSheet("font-family: Arial;font-size: 9px;");
btn->setStyleSheet("QPushButton{font-family: Fixedsys;color : white;}"
"QPushButton[enabled=\"false\"]{color : #AAAAAA;}");
btn->setFixedWidth(title.length() * 10);
layout->addWidget(btn);
connect(btn,SIGNAL(clicked()),SLOT(onButton()));
return btn;
}
void RMTune360Dialog::onSliderChange(int value)
{
QSlider* slider = qobject_cast<QSlider*>(sender());
int index = _sliders->indexOf(slider);
QLabel* label = _labels->at(index);
QString str;
double v = ((double)value)/(TUNE_360_RANGE * _ratios.at(index));
label->setText(str.sprintf("%.3f",v));
refresh();
}
void* RMTune360Dialog::gl()
{
return RMPlayer::instance()->playerF()->videoOutputs().first()->opengl();
}
void RMTune360Dialog::loadPreset()
{
FAV::OpenGLVideo* opengl = (FAV::OpenGLVideo*)gl();
QMatrix4x4& m = opengl->tune360();
float ac[16];// = m.constData();
m.copyDataTo(ac);
for(int i=0;i<_sliders->count();i++)
{
float fv = ac[i] * (TUNE_360_RANGE * _ratios.at(i));
//qInfo() << i << ":" << fv;
_sliders->at(i)->blockSignals(true);
_sliders->at(i)->setValue(fv);
_sliders->at(i)->blockSignals(false);
QLabel* label = _labels->at(i);
QString str;
//double v = ((double)value)/(TUNE_360_RANGE * _ratios.at(index));
label->setText(str.sprintf("%.3f",ac[i]));
}
}
void RMTune360Dialog::refresh()
{
float ac[16] = {0,};
for(int i=0;i<_sliders->count();i++)
{
ac[i] = ((double)_sliders->at(i)->value())/(TUNE_360_RANGE * _ratios.at(i));
//qInfo() << "I:" << i << ":"<< ac[i];
}
//ac[8] = _swap ? 1.0 : 0.0; // 3*2+2 = 8
QMatrix4x4 m(ac);
FAV::OpenGLVideo* opengl = (FAV::OpenGLVideo*)gl();
opengl->setTune360(m);
RMPlayer::instance()->playWidgetF()->update();
}
void RMTune360Dialog::onButton()
{
QPushButton* btn = qobject_cast<QPushButton*>(sender());
QString cmd = btn->text().toUpper();
FAV::OpenGLVideo* opengl = (FAV::OpenGLVideo*)gl();
if(cmd == "RESET")
{
for(int i=0;i<_sliders->count();i++)
{
_sliders->at(i)->setValue(0);
}
refresh();
}
else if(cmd == "VR")
{
opengl->setMode(1);
RMPlayer::instance()->playWidgetF()->update();
}
else if(cmd == "WIDE")
{
opengl->setMode(0);
RMPlayer::instance()->playWidgetF()->update();
}
else if (cmd == "GET")
{
QString a = "[";
for(int i=0;i<_sliders->count();i++)
{
if(i>0)
{
a += ",";
}
QString vf;
float f = ((double)_sliders->at(i)->value())/(TUNE_360_RANGE * _ratios.at(i));
vf.sprintf("%f",f);
a += vf;
}
a += "];";
_paramTextEdit->clear();
_paramTextEdit->appendPlainText(a);
}
else if(cmd == "SET")
{
QString pt = _paramTextEdit->toPlainText();
pt.replace("[","").replace("]","").replace(";","");
QStringList sl = pt.split(",");
if(sl.count() == _sliders->count())
{
for(int i=0;i<sl.count();i++)
{
QString sv = sl.at(i);
float fv = sv.toFloat() * (TUNE_360_RANGE * _ratios.at(i));
//qInfo() << sl << sv << fv;
_sliders->at(i)->setValue(fv);
}
}
}
else if(cmd == "SWAP")
{
_swap = !_swap;
qInfo() << "swap:" << _swap;
refresh();
}
else if (cmd == "RS")
{
int index = _resetButtons->indexOf(btn);
_sliders->at(index)->setValue(0);
refresh();
}
}
#endif // #if (TUNE_360)

View File

@@ -0,0 +1,56 @@
#ifndef RM_TUNE360_DIALOG_H
#define RM_TUNE360_DIALOG_H
#if (TUNE_360)
#include <QDialog>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QPlainTextEdit>
#include <QLineEdit>
#include <QSlider>
class RMTune360Dialog : public QDialog
{
Q_OBJECT
public:
static RMTune360Dialog* instance(QWidget* parent = nullptr);
private:
QVBoxLayout* _layout;
QWidget* _toolbar;
QPushButton* _resetButton;
QLineEdit* _filterEdit;
QList<QLabel*>* _labels;
QList<QSlider*>* _sliders;
QList<QPushButton*>* _resetButtons;
QList<float> _ratios;
QPlainTextEdit* _paramTextEdit;
bool _swap;
explicit RMTune360Dialog(QWidget *parent = nullptr);
void showEvent(QShowEvent * event);
void createToolbar();
void createSliderPanel();
void createParamConsole();
QPushButton* _button(QWidget* parent,QLayout* layout,QString title);
QSlider* _slider(QWidget* parent,QLayout* layout, QString title, float ratio);
void refresh();
void loadPreset();
void* gl();
signals:
public slots:
void onSliderChange(int value);
void onButton();
};
#endif // #if (TUNE_360)
#endif // RM_TUNE360_DIALOG_H