mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-06-14 21:01:39 -05:00
Add 'OBS stats' condition type (#414)
It supports various different types of stats: * fps * cpu * ram * frame time * skipped frames * missed frames * dropped frames * data size sent * bitrate
This commit is contained in:
parent
88dff37776
commit
4e5aae7e5f
|
|
@ -229,6 +229,7 @@ set(advanced-scene-switcher_HEADERS
|
|||
src/headers/macro-condition-idle.hpp
|
||||
src/headers/macro-condition-macro.hpp
|
||||
src/headers/macro-condition-media.hpp
|
||||
src/headers/macro-condition-obs-stats.hpp
|
||||
src/headers/macro-condition-plugin-state.hpp
|
||||
src/headers/macro-condition-process.hpp
|
||||
src/headers/macro-condition-recording.hpp
|
||||
|
|
@ -330,6 +331,7 @@ set(advanced-scene-switcher_SOURCES
|
|||
src/macro-condition-idle.cpp
|
||||
src/macro-condition-macro.cpp
|
||||
src/macro-condition-media.cpp
|
||||
src/macro-condition-obs-stats.cpp
|
||||
src/macro-condition-plugin-state.cpp
|
||||
src/macro-condition-process.cpp
|
||||
src/macro-condition-recording.cpp
|
||||
|
|
|
|||
|
|
@ -291,6 +291,25 @@ AdvSceneSwitcher.condition.errorStatus="OpenVR error: "
|
|||
AdvSceneSwitcher.condition.openvr.entry.line1="HMD is in ..."
|
||||
AdvSceneSwitcher.condition.openvr.entry.line2="{{controls}}"
|
||||
AdvSceneSwitcher.condition.openvr.entry.line3="HMD is currently at {{xPos}} x {{yPos}} x {{zPos}}"
|
||||
AdvSceneSwitcher.condition.stats="OBS stats"
|
||||
AdvSceneSwitcher.condition.stats.type.fps="FPS"
|
||||
AdvSceneSwitcher.condition.stats.type.CPUUsage="CPU Usage"
|
||||
AdvSceneSwitcher.condition.stats.type.HDDSpaceAvailable="Disk space available"
|
||||
AdvSceneSwitcher.condition.stats.type.memoryUsage="Memory Usage"
|
||||
AdvSceneSwitcher.condition.stats.type.averageTimeToRender="Average time to render frame"
|
||||
AdvSceneSwitcher.condition.stats.type.skippedFrames="Skipped frames due to encoding lag"
|
||||
AdvSceneSwitcher.condition.stats.type.missedFrames="Frames missed due to rendering lag"
|
||||
AdvSceneSwitcher.condition.stats.type.droppedFrames.stream="Stream dropped frames"
|
||||
AdvSceneSwitcher.condition.stats.type.megabytesSent.stream="Stream total data output"
|
||||
AdvSceneSwitcher.condition.stats.type.bitrate.stream="Stream bitrate"
|
||||
AdvSceneSwitcher.condition.stats.type.droppedFrames.recording="Recording dropped frames"
|
||||
AdvSceneSwitcher.condition.stats.type.megabytesSent.recording="Recording total data output"
|
||||
AdvSceneSwitcher.condition.stats.type.bitrate.recording="Recording bitrate"
|
||||
AdvSceneSwitcher.condition.stats.condition.above="above"
|
||||
AdvSceneSwitcher.condition.stats.condition.equals="equal to"
|
||||
AdvSceneSwitcher.condition.stats.condition.below="below"
|
||||
AdvSceneSwitcher.condition.stats.dockHint="You can open the \"Stats\" dock to view the current status"
|
||||
AdvSceneSwitcher.condition.stats.entry="{{stats}} is {{condition}} {{value}}"
|
||||
|
||||
; Macro Actions
|
||||
AdvSceneSwitcher.action.switchScene="Switch scene"
|
||||
|
|
|
|||
118
src/headers/macro-condition-obs-stats.hpp
Normal file
118
src/headers/macro-condition-obs-stats.hpp
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <util/platform.h>
|
||||
|
||||
enum class StatsType {
|
||||
FPS,
|
||||
CPU_USAGE,
|
||||
DISK_USAGE, // not implemented
|
||||
MEM_USAGE,
|
||||
AVG_FRAMETIME,
|
||||
RENDER_LAG,
|
||||
ENCODE_LAG,
|
||||
STREAM_DROPPED_FRAMES,
|
||||
STREAM_BITRATE,
|
||||
STREAM_MB_SENT,
|
||||
RECORDING_DROPPED_FRAMES, // not sure if this makes sense
|
||||
RECORDING_BITRATE,
|
||||
RECORDING_MB_SENT,
|
||||
};
|
||||
|
||||
enum class StatsCondition {
|
||||
ABOVE,
|
||||
EQUALS,
|
||||
BELOW,
|
||||
};
|
||||
|
||||
class MacroConditionStats : public MacroCondition {
|
||||
public:
|
||||
MacroConditionStats(Macro *m);
|
||||
~MacroConditionStats();
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create(Macro *m)
|
||||
{
|
||||
return std::make_shared<MacroConditionStats>(m);
|
||||
}
|
||||
|
||||
double _value = 0;
|
||||
StatsType _type = StatsType::FPS;
|
||||
StatsCondition _condition = StatsCondition::ABOVE;
|
||||
|
||||
private:
|
||||
bool CheckFPS();
|
||||
bool CheckCPU();
|
||||
bool CheckMemory();
|
||||
bool CheckAvgFrametime();
|
||||
bool CheckRenderLag();
|
||||
bool CheckEncodeLag();
|
||||
bool CheckStreamDroppedFrames();
|
||||
bool CheckStreamBitrate();
|
||||
bool CheckStreamMBSent();
|
||||
bool CheckRecordingDroppedFrames();
|
||||
bool CheckRecordingBitrate();
|
||||
bool CheckRecordingMBSent();
|
||||
|
||||
os_cpu_usage_info_t *_cpu_info = nullptr;
|
||||
uint32_t _first_encoded = 0xFFFFFFFF;
|
||||
uint32_t _first_skipped = 0xFFFFFFFF;
|
||||
uint32_t _first_rendered = 0xFFFFFFFF;
|
||||
uint32_t _first_lagged = 0xFFFFFFFF;
|
||||
struct OutputInfo {
|
||||
void Update(obs_output_t *output);
|
||||
|
||||
uint64_t lastBytesSent = 0;
|
||||
uint64_t lastBytesSentTime = 0;
|
||||
int first_total = 0;
|
||||
int first_dropped = 0;
|
||||
double dropped_relative = 0.0;
|
||||
long double kbps = 0.0l;
|
||||
};
|
||||
OutputInfo _streamInfo;
|
||||
OutputInfo _recordingInfo;
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionStatsEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionStatsEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionStats> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionStatsEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionStats>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ValueChanged(double value);
|
||||
void StatsTypeChanged(int type);
|
||||
void ConditionChanged(int cond);
|
||||
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_stats;
|
||||
QComboBox *_condition;
|
||||
QDoubleSpinBox *_value;
|
||||
std::shared_ptr<MacroConditionStats> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
bool _loading = true;
|
||||
};
|
||||
584
src/macro-condition-obs-stats.cpp
Normal file
584
src/macro-condition-obs-stats.cpp
Normal file
|
|
@ -0,0 +1,584 @@
|
|||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-obs-stats.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
const std::string MacroConditionStats::id = "obs_stats";
|
||||
|
||||
bool MacroConditionStats::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionStats::id,
|
||||
{MacroConditionStats::Create, MacroConditionStatsEdit::Create,
|
||||
"AdvSceneSwitcher.condition.stats"});
|
||||
|
||||
static std::map<StatsType, std::string> statsTypes = {
|
||||
{StatsType::FPS, "AdvSceneSwitcher.condition.stats.type.fps"},
|
||||
{StatsType::CPU_USAGE,
|
||||
"AdvSceneSwitcher.condition.stats.type.CPUUsage"},
|
||||
{StatsType::DISK_USAGE,
|
||||
"AdvSceneSwitcher.condition.stats.type.HDDSpaceAvailable"},
|
||||
{StatsType::MEM_USAGE,
|
||||
"AdvSceneSwitcher.condition.stats.type.memoryUsage"},
|
||||
{StatsType::AVG_FRAMETIME,
|
||||
"AdvSceneSwitcher.condition.stats.type.averageTimeToRender"},
|
||||
{StatsType::RENDER_LAG,
|
||||
"AdvSceneSwitcher.condition.stats.type.missedFrames"},
|
||||
{StatsType::ENCODE_LAG,
|
||||
"AdvSceneSwitcher.condition.stats.type.skippedFrames"},
|
||||
{StatsType::STREAM_DROPPED_FRAMES,
|
||||
"AdvSceneSwitcher.condition.stats.type.droppedFrames.stream"},
|
||||
{StatsType::STREAM_BITRATE,
|
||||
"AdvSceneSwitcher.condition.stats.type.bitrate.stream"},
|
||||
{StatsType::STREAM_MB_SENT,
|
||||
"AdvSceneSwitcher.condition.stats.type.megabytesSent.stream"},
|
||||
{StatsType::RECORDING_DROPPED_FRAMES,
|
||||
"AdvSceneSwitcher.condition.stats.type.droppedFrames.recording"},
|
||||
{StatsType::RECORDING_BITRATE,
|
||||
"AdvSceneSwitcher.condition.stats.type.bitrate.recording"},
|
||||
{StatsType::RECORDING_MB_SENT,
|
||||
"AdvSceneSwitcher.condition.stats.type.megabytesSent.recording"},
|
||||
};
|
||||
|
||||
static std::map<StatsCondition, std::string> statsConditionTypes = {
|
||||
{StatsCondition::ABOVE,
|
||||
"AdvSceneSwitcher.condition.stats.condition.above"},
|
||||
{StatsCondition::EQUALS,
|
||||
"AdvSceneSwitcher.condition.stats.condition.equals"},
|
||||
{StatsCondition::BELOW,
|
||||
"AdvSceneSwitcher.condition.stats.condition.below"},
|
||||
};
|
||||
|
||||
MacroConditionStats::MacroConditionStats(Macro *m)
|
||||
: MacroCondition(m), _cpu_info(os_cpu_usage_info_start())
|
||||
{
|
||||
}
|
||||
|
||||
MacroConditionStats::~MacroConditionStats()
|
||||
{
|
||||
os_cpu_usage_info_destroy(_cpu_info);
|
||||
}
|
||||
|
||||
bool doubleEquals(double left, double right, double epsilon)
|
||||
{
|
||||
return (fabs(left - right) < epsilon);
|
||||
}
|
||||
|
||||
bool MacroConditionStats::CheckFPS()
|
||||
{
|
||||
switch (_condition) {
|
||||
case StatsCondition::ABOVE:
|
||||
return obs_get_active_fps() > _value;
|
||||
case StatsCondition::EQUALS:
|
||||
return doubleEquals(obs_get_active_fps(), _value, 0.01);
|
||||
case StatsCondition::BELOW:
|
||||
return obs_get_active_fps() < _value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionStats::CheckCPU()
|
||||
{
|
||||
double usage = os_cpu_usage_info_query(_cpu_info);
|
||||
|
||||
switch (_condition) {
|
||||
case StatsCondition::ABOVE:
|
||||
return usage > _value;
|
||||
case StatsCondition::EQUALS:
|
||||
return doubleEquals(usage, _value, 0.1);
|
||||
case StatsCondition::BELOW:
|
||||
return usage < _value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionStats::CheckMemory()
|
||||
{
|
||||
auto rss =
|
||||
(long double)os_get_proc_resident_size() / (1024.0l * 1024.0l);
|
||||
|
||||
switch (_condition) {
|
||||
case StatsCondition::ABOVE:
|
||||
return rss > _value;
|
||||
case StatsCondition::EQUALS:
|
||||
return doubleEquals(rss, _value, 0.1);
|
||||
case StatsCondition::BELOW:
|
||||
return rss < _value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionStats::CheckAvgFrametime()
|
||||
{
|
||||
auto num = (long double)obs_get_average_frame_time_ns() / 1000000.0l;
|
||||
|
||||
switch (_condition) {
|
||||
case StatsCondition::ABOVE:
|
||||
return num > _value;
|
||||
case StatsCondition::EQUALS:
|
||||
return doubleEquals(num, _value, 0.1);
|
||||
case StatsCondition::BELOW:
|
||||
return num < _value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionStats::CheckRenderLag()
|
||||
{
|
||||
uint32_t total_rendered = obs_get_total_frames();
|
||||
uint32_t total_lagged = obs_get_lagged_frames();
|
||||
|
||||
if (total_rendered < _first_rendered || total_lagged < _first_lagged) {
|
||||
_first_rendered = total_rendered;
|
||||
_first_lagged = total_lagged;
|
||||
}
|
||||
total_rendered -= _first_rendered;
|
||||
total_lagged -= _first_lagged;
|
||||
|
||||
auto num = total_rendered ? (long double)total_lagged /
|
||||
(long double)total_rendered
|
||||
: 0.0l;
|
||||
num *= 100.0l;
|
||||
|
||||
switch (_condition) {
|
||||
case StatsCondition::ABOVE:
|
||||
return num > _value;
|
||||
case StatsCondition::EQUALS:
|
||||
return doubleEquals(num, _value, 0.1);
|
||||
case StatsCondition::BELOW:
|
||||
return num < _value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionStats::CheckEncodeLag()
|
||||
{
|
||||
video_t *video = obs_get_video();
|
||||
uint32_t total_encoded = video_output_get_total_frames(video);
|
||||
uint32_t total_skipped = video_output_get_skipped_frames(video);
|
||||
|
||||
if (total_encoded < _first_encoded || total_skipped < _first_encoded) {
|
||||
_first_encoded = total_encoded;
|
||||
_first_skipped = total_skipped;
|
||||
}
|
||||
total_encoded -= _first_encoded;
|
||||
total_skipped -= _first_skipped;
|
||||
|
||||
auto num = total_encoded ? (long double)total_skipped /
|
||||
(long double)total_encoded
|
||||
: 0.0l;
|
||||
num *= 100.0l;
|
||||
|
||||
switch (_condition) {
|
||||
case StatsCondition::ABOVE:
|
||||
return num > _value;
|
||||
case StatsCondition::EQUALS:
|
||||
return doubleEquals(num, _value, 0.1);
|
||||
case StatsCondition::BELOW:
|
||||
return num < _value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MacroConditionStats::OutputInfo::Update(obs_output_t *output)
|
||||
{
|
||||
uint64_t totalBytes = output ? obs_output_get_total_bytes(output) : 0;
|
||||
uint64_t curTime = os_gettime_ns();
|
||||
uint64_t bytesSent = totalBytes;
|
||||
|
||||
if (bytesSent < lastBytesSent)
|
||||
bytesSent = 0;
|
||||
if (bytesSent == 0)
|
||||
lastBytesSent = 0;
|
||||
|
||||
uint64_t bitsBetween = (bytesSent - lastBytesSent) * 8;
|
||||
long double timePassed =
|
||||
(long double)(curTime - lastBytesSentTime) / 1000000000.0l;
|
||||
kbps = (long double)bitsBetween / timePassed / 1000.0l;
|
||||
|
||||
if (timePassed < 0.01l)
|
||||
kbps = 0.0l;
|
||||
|
||||
int total = output ? obs_output_get_total_frames(output) : 0;
|
||||
int dropped = output ? obs_output_get_frames_dropped(output) : 0;
|
||||
|
||||
if (total < first_total || dropped < first_dropped) {
|
||||
first_total = 0;
|
||||
first_dropped = 0;
|
||||
}
|
||||
|
||||
total -= first_total;
|
||||
dropped -= first_dropped;
|
||||
|
||||
dropped_relative =
|
||||
total ? (long double)dropped / (long double)total * 100.0l
|
||||
: 0.0l;
|
||||
|
||||
lastBytesSent = bytesSent;
|
||||
lastBytesSentTime = curTime;
|
||||
}
|
||||
|
||||
bool MacroConditionStats::CheckStreamDroppedFrames()
|
||||
{
|
||||
auto output = obs_frontend_get_streaming_output();
|
||||
_streamInfo.Update(output);
|
||||
obs_output_release(output);
|
||||
|
||||
switch (_condition) {
|
||||
case StatsCondition::ABOVE:
|
||||
return _streamInfo.dropped_relative > _value;
|
||||
case StatsCondition::EQUALS:
|
||||
return doubleEquals(_streamInfo.dropped_relative, _value, 0.1);
|
||||
case StatsCondition::BELOW:
|
||||
return _streamInfo.dropped_relative < _value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionStats::CheckStreamBitrate()
|
||||
{
|
||||
auto output = obs_frontend_get_streaming_output();
|
||||
_streamInfo.Update(output);
|
||||
obs_output_release(output);
|
||||
|
||||
switch (_condition) {
|
||||
case StatsCondition::ABOVE:
|
||||
return _streamInfo.kbps > _value;
|
||||
case StatsCondition::EQUALS:
|
||||
return doubleEquals(_streamInfo.kbps, _value, 1.0);
|
||||
case StatsCondition::BELOW:
|
||||
return _streamInfo.kbps < _value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionStats::CheckStreamMBSent()
|
||||
{
|
||||
auto output = obs_frontend_get_streaming_output();
|
||||
uint64_t totalBytes = output ? obs_output_get_total_bytes(output) : 0;
|
||||
obs_output_release(output);
|
||||
long double num = (long double)totalBytes / (1024.0l * 1024.0l);
|
||||
|
||||
switch (_condition) {
|
||||
case StatsCondition::ABOVE:
|
||||
return num > _value;
|
||||
case StatsCondition::EQUALS:
|
||||
return doubleEquals(num, _value, 0.1);
|
||||
case StatsCondition::BELOW:
|
||||
return num < _value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionStats::CheckRecordingDroppedFrames()
|
||||
{
|
||||
auto output = obs_frontend_get_recording_output();
|
||||
_recordingInfo.Update(output);
|
||||
obs_output_release(output);
|
||||
|
||||
switch (_condition) {
|
||||
case StatsCondition::ABOVE:
|
||||
return _recordingInfo.dropped_relative > _value;
|
||||
case StatsCondition::EQUALS:
|
||||
return doubleEquals(_recordingInfo.dropped_relative, _value,
|
||||
0.1);
|
||||
case StatsCondition::BELOW:
|
||||
return _recordingInfo.dropped_relative < _value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionStats::CheckRecordingBitrate()
|
||||
{
|
||||
auto output = obs_frontend_get_recording_output();
|
||||
_recordingInfo.Update(output);
|
||||
obs_output_release(output);
|
||||
|
||||
switch (_condition) {
|
||||
case StatsCondition::ABOVE:
|
||||
return _recordingInfo.kbps > _value;
|
||||
case StatsCondition::EQUALS:
|
||||
return doubleEquals(_recordingInfo.kbps, _value, 1.0);
|
||||
case StatsCondition::BELOW:
|
||||
return _recordingInfo.kbps < _value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionStats::CheckRecordingMBSent()
|
||||
{
|
||||
auto output = obs_frontend_get_recording_output();
|
||||
uint64_t totalBytes = output ? obs_output_get_total_bytes(output) : 0;
|
||||
obs_output_release(output);
|
||||
long double num = (long double)totalBytes / (1024.0l * 1024.0l);
|
||||
|
||||
switch (_condition) {
|
||||
case StatsCondition::ABOVE:
|
||||
return num > _value;
|
||||
case StatsCondition::EQUALS:
|
||||
return doubleEquals(num, _value, 0.1);
|
||||
case StatsCondition::BELOW:
|
||||
return num < _value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionStats::CheckCondition()
|
||||
{
|
||||
switch (_type) {
|
||||
case StatsType::FPS:
|
||||
return CheckFPS();
|
||||
case StatsType::CPU_USAGE:
|
||||
return CheckCPU();
|
||||
case StatsType::DISK_USAGE:
|
||||
// TODO: not implemented
|
||||
break;
|
||||
case StatsType::MEM_USAGE:
|
||||
return CheckMemory();
|
||||
case StatsType::AVG_FRAMETIME:
|
||||
return CheckAvgFrametime();
|
||||
case StatsType::RENDER_LAG:
|
||||
return CheckRenderLag();
|
||||
case StatsType::ENCODE_LAG:
|
||||
return CheckEncodeLag();
|
||||
case StatsType::STREAM_DROPPED_FRAMES:
|
||||
return CheckStreamDroppedFrames();
|
||||
case StatsType::STREAM_BITRATE:
|
||||
return CheckStreamBitrate();
|
||||
case StatsType::STREAM_MB_SENT:
|
||||
return CheckStreamMBSent();
|
||||
case StatsType::RECORDING_DROPPED_FRAMES:
|
||||
return CheckRecordingDroppedFrames();
|
||||
case StatsType::RECORDING_BITRATE:
|
||||
return CheckRecordingBitrate();
|
||||
case StatsType::RECORDING_MB_SENT:
|
||||
return CheckRecordingMBSent();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionStats::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
obs_data_set_double(obj, "value", _value);
|
||||
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionStats::Load(obs_data_t *obj)
|
||||
{
|
||||
|
||||
MacroCondition::Load(obj);
|
||||
_value = obs_data_get_double(obj, "value");
|
||||
_type = static_cast<StatsType>(obs_data_get_int(obj, "type"));
|
||||
_condition =
|
||||
static_cast<StatsCondition>(obs_data_get_int(obj, "condition"));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionStats::GetShortDesc()
|
||||
{
|
||||
auto it = statsTypes.find(_type);
|
||||
if (it != statsTypes.end()) {
|
||||
return obs_module_text(it->second.c_str());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateStatsTypes(QComboBox *list)
|
||||
{
|
||||
list->clear();
|
||||
for (auto entry : statsTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
// TODO: not implemented
|
||||
if (entry.first == StatsType::DISK_USAGE) {
|
||||
qobject_cast<QListView *>(list->view())
|
||||
->setRowHidden(list->count() - 1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
list->clear();
|
||||
for (auto entry : statsConditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroConditionStatsEdit::MacroConditionStatsEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionStats> entryData)
|
||||
: QWidget(parent),
|
||||
_stats(new QComboBox),
|
||||
_condition(new QComboBox),
|
||||
_value(new QDoubleSpinBox)
|
||||
{
|
||||
_value->setMaximum(999999999999);
|
||||
|
||||
populateStatsTypes(_stats);
|
||||
populateConditionSelection(_condition);
|
||||
|
||||
setToolTip(
|
||||
obs_module_text("AdvSceneSwitcher.condition.stats.dockHint"));
|
||||
|
||||
QWidget::connect(_value, SIGNAL(valueChanged(double)), this,
|
||||
SLOT(ValueChanged(double)));
|
||||
QWidget::connect(_stats, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(StatsTypeChanged(int)));
|
||||
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{value}}", _value},
|
||||
{"{{stats}}", _stats},
|
||||
{"{{condition}}", _condition},
|
||||
};
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.condition.stats.entry"),
|
||||
layout, widgetPlaceholders);
|
||||
setLayout(layout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionStatsEdit::ValueChanged(double value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_value = value;
|
||||
}
|
||||
|
||||
void MacroConditionStatsEdit::StatsTypeChanged(int type)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_type = static_cast<StatsType>(type);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
_value->setValue(0);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionStatsEdit::ConditionChanged(int cond)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_condition = static_cast<StatsCondition>(cond);
|
||||
}
|
||||
|
||||
void MacroConditionStatsEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_value->setValue(_entryData->_value);
|
||||
_stats->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
_condition->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionStatsEdit::SetWidgetVisibility()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_entryData->_type) {
|
||||
case StatsType::FPS:
|
||||
_value->setMaximum(1000);
|
||||
_value->setSuffix("");
|
||||
break;
|
||||
case StatsType::CPU_USAGE:
|
||||
_value->setMaximum(100);
|
||||
_value->setSuffix("%");
|
||||
break;
|
||||
case StatsType::DISK_USAGE:
|
||||
_value->setMaximum(999999999999);
|
||||
_value->setSuffix("MB");
|
||||
break;
|
||||
case StatsType::MEM_USAGE:
|
||||
_value->setMaximum(999999999999);
|
||||
_value->setSuffix("MB");
|
||||
break;
|
||||
case StatsType::AVG_FRAMETIME:
|
||||
_value->setMaximum(999999999999);
|
||||
_value->setSuffix("ms");
|
||||
break;
|
||||
case StatsType::RENDER_LAG:
|
||||
_value->setMaximum(100);
|
||||
_value->setSuffix("%");
|
||||
break;
|
||||
case StatsType::ENCODE_LAG:
|
||||
_value->setMaximum(100);
|
||||
_value->setSuffix("%");
|
||||
break;
|
||||
case StatsType::STREAM_DROPPED_FRAMES:
|
||||
_value->setMaximum(100);
|
||||
_value->setSuffix("%");
|
||||
break;
|
||||
case StatsType::STREAM_BITRATE:
|
||||
_value->setMaximum(999999999999);
|
||||
_value->setSuffix("kb/s");
|
||||
break;
|
||||
case StatsType::STREAM_MB_SENT:
|
||||
_value->setMaximum(999999999999);
|
||||
_value->setSuffix("MB");
|
||||
break;
|
||||
case StatsType::RECORDING_DROPPED_FRAMES:
|
||||
_value->setMaximum(100);
|
||||
_value->setSuffix("%");
|
||||
break;
|
||||
case StatsType::RECORDING_BITRATE:
|
||||
_value->setMaximum(999999999999);
|
||||
_value->setSuffix("kb/s");
|
||||
break;
|
||||
case StatsType::RECORDING_MB_SENT:
|
||||
_value->setMaximum(999999999999);
|
||||
_value->setSuffix("MB");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
adjustSize();
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user