mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-09-12 11:36:08 -05:00
Rework Media condition
* Split state and time check * Improve signal handling * Prevent exponential memory groth when using the "any" / "all" check * Improve layout
This commit is contained in:
@@ -159,7 +159,7 @@ AdvSceneSwitcher.condition.media.source="Quelle"
|
||||
AdvSceneSwitcher.condition.media.anyOnScene="Beliebige Medienquelle in"
|
||||
AdvSceneSwitcher.condition.media.allOnScene="Alle Medienquellen in"
|
||||
AdvSceneSwitcher.condition.media.inconsistencyInfo="Leider verhalten sich nicht alle Medien-Quell-Typen gleich (z.B. Medien-Quelle vs. VLC-Video-Quelle \"Gestoppt\"-Status).\nBitte experimentieren, was in eurem Setup funktioniert!"
|
||||
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}Status ist{{states}}und{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.media.layout.legacy="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}Status ist{{states}}und{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.video="Video"
|
||||
AdvSceneSwitcher.condition.video.condition.match="entspricht genau"
|
||||
AdvSceneSwitcher.condition.video.condition.differ="stimmt nicht überein"
|
||||
|
||||
@@ -307,11 +307,14 @@ AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{condition
|
||||
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||
AdvSceneSwitcher.condition.media="Media"
|
||||
AdvSceneSwitcher.condition.media.checkType.state="State matches"
|
||||
AdvSceneSwitcher.condition.media.checkType.time="Time restriction matches"
|
||||
AdvSceneSwitcher.condition.media.source="Source"
|
||||
AdvSceneSwitcher.condition.media.anyOnScene="Any media source on"
|
||||
AdvSceneSwitcher.condition.media.allOnScene="All media sources on"
|
||||
AdvSceneSwitcher.condition.media.inconsistencyInfo="Unfortunately not all media source types behave the same (e.g. Media Source vs. VLC Video Source \"Stopped\" state).\nSo please experiment what works for your setup!"
|
||||
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}state is{{states}}and{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.media.layout="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}{{states}}{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.media.layout.legacy="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}state is{{states}}and{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.video="Video"
|
||||
AdvSceneSwitcher.condition.video.condition.match="exactly matches"
|
||||
AdvSceneSwitcher.condition.video.condition.differ="does not match"
|
||||
|
||||
@@ -128,7 +128,7 @@ AdvSceneSwitcher.condition.media="Medios"
|
||||
AdvSceneSwitcher.condition.media.anyOnScene="Cualquier fuente multimedia activada"
|
||||
AdvSceneSwitcher.condition.media.allOnScene="Todas las fuentes de medios activadas"
|
||||
AdvSceneSwitcher.condition.media.inconsistencyInfo="Desafortunadamente, no todos los tipos de fuentes de medios se comportan de la misma manera (p. ej., fuente de medios frente a estado \"Detenido\" de fuente de video VLC).\n¡Así que experimente lo que funciona para su configuración!"
|
||||
AdvSceneSwitcher.condition.media.entry="El estado de{{sourceTypes}}{{mediaSources}}{{scenes}}es{{states}}y{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.media.layout.legacy="El estado de{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}es{{states}}y{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.video="Video"
|
||||
AdvSceneSwitcher.condition.video.condition.match="coincide exactamente"
|
||||
AdvSceneSwitcher.condition.video.condition.differ="no coincide"
|
||||
|
||||
@@ -196,7 +196,7 @@ AdvSceneSwitcher.condition.media.source="Source"
|
||||
AdvSceneSwitcher.condition.media.anyOnScene="Toute source média sur la scène"
|
||||
AdvSceneSwitcher.condition.media.allOnScene="Toutes les sources média sur la scène"
|
||||
AdvSceneSwitcher.condition.media.inconsistencyInfo="Malheureusement, toutes les sources média ne se comportent pas de la même manière (par exemple, l'état \"Arrêté\" de la source Media par rapport à la source Vidéo VLC).\nPar conséquent, veuillez expérimenter ce qui fonctionne le mieux pour votre configuration !"
|
||||
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}l'état est{{states}}et{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.media.layout.legacy="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}l'état est{{states}}et{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.video="Vidéo"
|
||||
AdvSceneSwitcher.condition.video.condition.match="correspond exactement à"
|
||||
AdvSceneSwitcher.condition.video.condition.differ="ne correspond pas à"
|
||||
|
||||
@@ -311,7 +311,7 @@ AdvSceneSwitcher.condition.media.source="ソース"
|
||||
AdvSceneSwitcher.condition.media.anyOnScene="あらゆるメディアソース"
|
||||
AdvSceneSwitcher.condition.media.allOnScene="すべてのメディアソースはこちら"
|
||||
AdvSceneSwitcher.condition.media.inconsistencyInfo="残念ながら、すべてのメディア ソース タイプが同じように動作するわけではありません (例: メディア ソースと VLC ビデオ ソースの \"Stopped\" 状態)。\nそのため、ご自身のセットアップに適したものを試してみてください。"
|
||||
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}の状態は{{states}}かつ{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.media.layout.legacy="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}の状態は{{states}}かつ{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.video="動画"
|
||||
AdvSceneSwitcher.condition.video.condition.match="完全一致"
|
||||
AdvSceneSwitcher.condition.video.condition.differ="合わない"
|
||||
|
||||
@@ -117,7 +117,7 @@ AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFil
|
||||
AdvSceneSwitcher.condition.media="Medya"
|
||||
AdvSceneSwitcher.condition.media.anyOnScene="Herhangi bir medya kaynağı"
|
||||
AdvSceneSwitcher.condition.media.allOnScene="Tüm medya kaynakları "
|
||||
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}}durumu{{states}}ve{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.media.layout.legacy="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}durumu{{states}}ve{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.video="Video"
|
||||
AdvSceneSwitcher.condition.video.condition.match="Tam olarak eşleşir"
|
||||
AdvSceneSwitcher.condition.video.condition.differ="Eşleştirme"
|
||||
|
||||
@@ -184,7 +184,7 @@ AdvSceneSwitcher.condition.media.source="源"
|
||||
AdvSceneSwitcher.condition.media.anyOnScene="任何媒体源"
|
||||
AdvSceneSwitcher.condition.media.allOnScene="所有媒体源"
|
||||
AdvSceneSwitcher.condition.media.inconsistencyInfo="不幸的是,并非所有媒体源类型的行为都相同(例如,媒体源与VLC视频源“停止”状态)。\n所以,请尝试适合您的设置!"
|
||||
AdvSceneSwitcher.condition.media.entry="{{sourceTypes}}{{mediaSources}}{{scenes}} 的状态是 {{states}} 和 {{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.media.layout.legacy="{{sourceTypes}}{{mediaSources}}{{scenes}}{{checkTypes}}的状态是{{states}}和{{timeRestrictions}}{{time}}"
|
||||
AdvSceneSwitcher.condition.video="视频"
|
||||
AdvSceneSwitcher.condition.video.condition.match="完全匹配"
|
||||
AdvSceneSwitcher.condition.video.condition.differ="不匹配"
|
||||
|
||||
@@ -52,16 +52,6 @@ static const std::map<MacroConditionMedia::State, std::string> mediaStates = {
|
||||
"AdvSceneSwitcher.mediaTab.states.any"},
|
||||
};
|
||||
|
||||
MacroConditionMedia::~MacroConditionMedia()
|
||||
{
|
||||
OBSSourceAutoRelease mediasource =
|
||||
obs_weak_source_get_source(_source.GetSource());
|
||||
signal_handler_t *sh = obs_source_get_signal_handler(mediasource);
|
||||
signal_handler_disconnect(sh, "media_stopped", MediaStopped, this);
|
||||
signal_handler_disconnect(sh, "media_ended", MediaEnded, this);
|
||||
signal_handler_disconnect(sh, "media_next", MediaNext, this);
|
||||
}
|
||||
|
||||
bool MacroConditionMedia::CheckTime()
|
||||
{
|
||||
OBSSourceAutoRelease s =
|
||||
@@ -71,7 +61,7 @@ bool MacroConditionMedia::CheckTime()
|
||||
|
||||
bool match = false;
|
||||
|
||||
switch (_restriction) {
|
||||
switch (_timeRestriction) {
|
||||
case Time::TIME_RESTRICTION_NONE:
|
||||
match = true;
|
||||
break;
|
||||
@@ -152,7 +142,21 @@ bool MacroConditionMedia::CheckMediaMatch()
|
||||
if (!_source.GetSource()) {
|
||||
return false;
|
||||
}
|
||||
bool matched = CheckState() && CheckTime();
|
||||
|
||||
bool matched = false;
|
||||
switch (_checkType) {
|
||||
case CheckType::STATE:
|
||||
matched = CheckState();
|
||||
break;
|
||||
case CheckType::TIME:
|
||||
matched = CheckTime();
|
||||
break;
|
||||
case CheckType::LEGACY:
|
||||
matched = CheckState() && CheckTime();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// reset for next check
|
||||
_stopped = false;
|
||||
@@ -168,16 +172,50 @@ void MacroConditionMedia::HandleSceneChange()
|
||||
_lastConfigureScene = GetCurrentScene();
|
||||
}
|
||||
|
||||
MacroConditionMedia::MacroConditionMedia(const MacroConditionMedia &other)
|
||||
: MacroCondition(other.GetMacro()),
|
||||
_sourceType(other._sourceType),
|
||||
_checkType(other._checkType),
|
||||
_state(other._state),
|
||||
_timeRestriction(other._timeRestriction),
|
||||
_scene(other._scene),
|
||||
_source(other._source),
|
||||
_rawSource(other._rawSource),
|
||||
_sourceGroup(),
|
||||
_time(other._time),
|
||||
_lastConfigureScene(other._lastConfigureScene)
|
||||
{
|
||||
ResetSignalHandler();
|
||||
}
|
||||
|
||||
MacroConditionMedia &
|
||||
MacroConditionMedia::operator=(const MacroConditionMedia &other)
|
||||
{
|
||||
_sourceType = other._sourceType;
|
||||
_checkType = other._checkType;
|
||||
_state = other._state;
|
||||
_timeRestriction = other._timeRestriction;
|
||||
_scene = other._scene;
|
||||
_source = other._source;
|
||||
_rawSource = other._rawSource;
|
||||
_time = other._time;
|
||||
_lastConfigureScene = other._lastConfigureScene;
|
||||
|
||||
ResetSignalHandler();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool MacroConditionMedia::CheckCondition()
|
||||
{
|
||||
bool match = false;
|
||||
switch (_sourceType) {
|
||||
case Type::ANY:
|
||||
case SourceType::ANY:
|
||||
for (auto &source : _sourceGroup) {
|
||||
match = match || source.CheckCondition();
|
||||
}
|
||||
break;
|
||||
case Type::ALL: {
|
||||
case SourceType::ALL: {
|
||||
bool res = true;
|
||||
for (auto &source : _sourceGroup) {
|
||||
res = res && source.CheckCondition();
|
||||
@@ -185,7 +223,7 @@ bool MacroConditionMedia::CheckCondition()
|
||||
match = res;
|
||||
break;
|
||||
}
|
||||
case Type::SOURCE:
|
||||
case SourceType::SOURCE:
|
||||
match = CheckMediaMatch();
|
||||
break;
|
||||
default:
|
||||
@@ -205,10 +243,12 @@ bool MacroConditionMedia::Save(obs_data_t *obj) const
|
||||
_source.Save(obj);
|
||||
_scene.Save(obj);
|
||||
obs_data_set_int(obj, "sourceType", static_cast<int>(_sourceType));
|
||||
obs_data_set_int(obj, "checkType", static_cast<int>(_checkType));
|
||||
obs_data_set_int(obj, "state", static_cast<int>(_state));
|
||||
obs_data_set_int(obj, "restriction", static_cast<int>(_restriction));
|
||||
obs_data_set_int(obj, "restriction",
|
||||
static_cast<int>(_timeRestriction));
|
||||
_time.Save(obj);
|
||||
obs_data_set_int(obj, "version", 0);
|
||||
obs_data_set_int(obj, "version", 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -245,7 +285,7 @@ void MacroConditionMedia::UpdateMediaSourcesOfSceneList()
|
||||
|
||||
for (auto &source : mediaSources) {
|
||||
MacroConditionMedia cond(*this);
|
||||
cond._sourceType = Type::SOURCE;
|
||||
cond._sourceType = SourceType::SOURCE;
|
||||
cond._source.SetSource(source);
|
||||
_sourceGroup.push_back(cond);
|
||||
}
|
||||
@@ -256,28 +296,31 @@ bool MacroConditionMedia::Load(obs_data_t *obj)
|
||||
MacroCondition::Load(obj);
|
||||
_source.Load(obj);
|
||||
_scene.Load(obj);
|
||||
_sourceType = static_cast<Type>(obs_data_get_int(obj, "sourceType"));
|
||||
_state = static_cast<MacroConditionMedia::State>(
|
||||
obs_data_get_int(obj, "state"));
|
||||
_restriction = static_cast<MacroConditionMedia::Time>(
|
||||
obs_data_get_int(obj, "restriction"));
|
||||
_sourceType =
|
||||
static_cast<SourceType>(obs_data_get_int(obj, "sourceType"));
|
||||
_state = static_cast<State>(obs_data_get_int(obj, "state"));
|
||||
_checkType = static_cast<CheckType>(obs_data_get_int(obj, "checkType"));
|
||||
_timeRestriction =
|
||||
static_cast<Time>(obs_data_get_int(obj, "restriction"));
|
||||
_time.Load(obj);
|
||||
|
||||
if (_sourceType == Type::SOURCE) {
|
||||
OBSSourceAutoRelease mediasource =
|
||||
obs_weak_source_get_source(_source.GetSource());
|
||||
signal_handler_t *sh =
|
||||
obs_source_get_signal_handler(mediasource);
|
||||
signal_handler_connect(sh, "media_stopped", MediaStopped, this);
|
||||
signal_handler_connect(sh, "media_ended", MediaEnded, this);
|
||||
signal_handler_connect(sh, "media_next", MediaNext, this);
|
||||
if (_sourceType == SourceType::SOURCE) {
|
||||
ResetSignalHandler();
|
||||
}
|
||||
|
||||
UpdateMediaSourcesOfSceneList();
|
||||
if (!obs_data_has_user_value(obj, "version")) {
|
||||
if (_state ==
|
||||
MacroConditionMedia::State::OBS_MEDIA_STATE_ENDED) {
|
||||
_state = MacroConditionMedia::State::PLAYLIST_ENDED;
|
||||
if (_state == State::OBS_MEDIA_STATE_ENDED) {
|
||||
_state = State::PLAYLIST_ENDED;
|
||||
}
|
||||
}
|
||||
if (obs_data_get_int(obj, "version") < 1) {
|
||||
if (IsUsingLegacyCheck()) {
|
||||
_checkType = CheckType::LEGACY;
|
||||
} else if (_state == State::ANY) {
|
||||
_checkType = CheckType::TIME;
|
||||
} else {
|
||||
_checkType = CheckType::STATE;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -286,16 +329,16 @@ bool MacroConditionMedia::Load(obs_data_t *obj)
|
||||
std::string MacroConditionMedia::GetShortDesc() const
|
||||
{
|
||||
switch (_sourceType) {
|
||||
case Type::SOURCE:
|
||||
case SourceType::SOURCE:
|
||||
return _source.ToString();
|
||||
case Type::ANY:
|
||||
case SourceType::ANY:
|
||||
if (_scene.GetScene(false)) {
|
||||
return obs_module_text(
|
||||
"AdvSceneSwitcher.condition.media.anyOnScene") +
|
||||
std::string(" ") + _scene.ToString();
|
||||
}
|
||||
break;
|
||||
case Type::ALL:
|
||||
case SourceType::ALL:
|
||||
if (_scene.GetScene(false)) {
|
||||
return obs_module_text(
|
||||
"AdvSceneSwitcher.condition.media.allOnScene") +
|
||||
@@ -308,27 +351,21 @@ std::string MacroConditionMedia::GetShortDesc() const
|
||||
return "";
|
||||
}
|
||||
|
||||
void MacroConditionMedia::ClearSignalHandler()
|
||||
bool MacroConditionMedia::IsUsingLegacyCheck() const
|
||||
{
|
||||
OBSSourceAutoRelease mediasource =
|
||||
obs_weak_source_get_source(_source.GetSource());
|
||||
signal_handler_t *sh = obs_source_get_signal_handler(mediasource);
|
||||
signal_handler_disconnect(sh, "media_stopped", MediaStopped, this);
|
||||
signal_handler_disconnect(sh, "media_ended", MediaEnded, this);
|
||||
signal_handler_disconnect(sh, "media_next", MediaNext, this);
|
||||
return _state != State::ANY &&
|
||||
_timeRestriction != Time::TIME_RESTRICTION_NONE;
|
||||
}
|
||||
|
||||
void MacroConditionMedia::ResetSignalHandler()
|
||||
{
|
||||
_signals.clear();
|
||||
OBSSourceAutoRelease mediasource =
|
||||
obs_weak_source_get_source(_source.GetSource());
|
||||
signal_handler_t *sh = obs_source_get_signal_handler(mediasource);
|
||||
signal_handler_disconnect(sh, "media_stopped", MediaStopped, this);
|
||||
signal_handler_disconnect(sh, "media_ended", MediaEnded, this);
|
||||
signal_handler_disconnect(sh, "media_next", MediaNext, this);
|
||||
signal_handler_connect(sh, "media_stopped", MediaStopped, this);
|
||||
signal_handler_connect(sh, "media_ended", MediaEnded, this);
|
||||
signal_handler_connect(sh, "media_next", MediaNext, this);
|
||||
_signals.emplace_back(sh, "media_stopped", MediaStopped, this);
|
||||
_signals.emplace_back(sh, "media_ended", MediaEnded, this);
|
||||
_signals.emplace_back(sh, "media_next", MediaNext, this);
|
||||
}
|
||||
|
||||
void MacroConditionMedia::MediaStopped(void *data, calldata_t *)
|
||||
@@ -361,17 +398,28 @@ void MacroConditionMedia::MediaNext(void *data, calldata_t *)
|
||||
media->_next = true;
|
||||
}
|
||||
|
||||
static void populateMediaTimes(QComboBox *list)
|
||||
static void populateSateSelection(QComboBox *list, bool addLegacyEntries)
|
||||
{
|
||||
for (auto entry : mediaTimeRestrictions) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
for (const auto &[value, name] : mediaStates) {
|
||||
if (value == MacroConditionMedia::State::ANY &&
|
||||
!addLegacyEntries) {
|
||||
continue;
|
||||
}
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(value));
|
||||
}
|
||||
}
|
||||
|
||||
static void populateMediaStates(QComboBox *list)
|
||||
static void populateTimeRestrictionSelection(QComboBox *list,
|
||||
bool addLegacyEntries)
|
||||
{
|
||||
for (auto entry : mediaStates) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
for (const auto &[value, name] : mediaTimeRestrictions) {
|
||||
if (value == MacroConditionMedia::Time::TIME_RESTRICTION_NONE &&
|
||||
!addLegacyEntries) {
|
||||
continue;
|
||||
}
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,19 +428,33 @@ static void populateSourceTypes(QComboBox *list)
|
||||
list->clear();
|
||||
list->addItem(
|
||||
obs_module_text("AdvSceneSwitcher.condition.media.source"),
|
||||
static_cast<int>(MacroConditionMedia::Type::SOURCE));
|
||||
static_cast<int>(MacroConditionMedia::SourceType::SOURCE));
|
||||
list->addItem(
|
||||
obs_module_text("AdvSceneSwitcher.condition.media.anyOnScene"),
|
||||
static_cast<int>(MacroConditionMedia::Type::ANY));
|
||||
static_cast<int>(MacroConditionMedia::SourceType::ANY));
|
||||
list->addItem(
|
||||
obs_module_text("AdvSceneSwitcher.condition.media.allOnScene"),
|
||||
static_cast<int>(MacroConditionMedia::Type::ALL));
|
||||
static_cast<int>(MacroConditionMedia::SourceType::ALL));
|
||||
}
|
||||
|
||||
static void populateCheckTypes(QComboBox *list)
|
||||
{
|
||||
list->clear();
|
||||
list->addItem(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.condition.media.checkType.state"),
|
||||
static_cast<int>(MacroConditionMedia::CheckType::STATE));
|
||||
list->addItem(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.condition.media.checkType.time"),
|
||||
static_cast<int>(MacroConditionMedia::CheckType::TIME));
|
||||
}
|
||||
|
||||
MacroConditionMediaEdit::MacroConditionMediaEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionMedia> entryData)
|
||||
: QWidget(parent),
|
||||
_sourceTypes(new QComboBox()),
|
||||
_checkTypes(new QComboBox()),
|
||||
_scenes(new SceneSelectionWidget(window(), true, true, true, true,
|
||||
true)),
|
||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||
@@ -409,6 +471,8 @@ MacroConditionMediaEdit::MacroConditionMediaEdit(
|
||||
|
||||
QWidget::connect(_sourceTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(SourceTypeChanged(int)));
|
||||
QWidget::connect(_checkTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(CheckTypeChanged(int)));
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||
SLOT(SourceChanged(const SourceSelection &)));
|
||||
@@ -422,20 +486,28 @@ MacroConditionMediaEdit::MacroConditionMediaEdit(
|
||||
SLOT(TimeChanged(const Duration &)));
|
||||
|
||||
populateSourceTypes(_sourceTypes);
|
||||
populateMediaStates(_states);
|
||||
populateMediaTimes(_timeRestrictions);
|
||||
populateCheckTypes(_checkTypes);
|
||||
const bool isUsingLegacyCheck = entryData->_checkType ==
|
||||
MacroConditionMedia::CheckType::LEGACY;
|
||||
populateSateSelection(_states, isUsingLegacyCheck);
|
||||
populateTimeRestrictionSelection(_timeRestrictions, isUsingLegacyCheck);
|
||||
|
||||
auto layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{sourceTypes}}", _sourceTypes},
|
||||
{"{{checkTypes}}", _checkTypes},
|
||||
{"{{mediaSources}}", _sources},
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{states}}", _states},
|
||||
{"{{timeRestrictions}}", _timeRestrictions},
|
||||
{"{{time}}", _time},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.condition.media.entry"),
|
||||
layout, widgetPlaceholders);
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
isUsingLegacyCheck
|
||||
? "AdvSceneSwitcher.condition.media.layout.legacy"
|
||||
: "AdvSceneSwitcher.condition.media.layout"),
|
||||
layout, widgetPlaceholders);
|
||||
setLayout(layout);
|
||||
|
||||
_entryData = entryData;
|
||||
@@ -445,15 +517,12 @@ MacroConditionMediaEdit::MacroConditionMediaEdit(
|
||||
|
||||
void MacroConditionMediaEdit::SourceTypeChanged(int idx)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_sourceType = static_cast<MacroConditionMedia::Type>(
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_sourceType = static_cast<MacroConditionMedia::SourceType>(
|
||||
_sourceTypes->itemData(idx).toInt());
|
||||
|
||||
if (_entryData->_sourceType == MacroConditionMedia::Type::SOURCE) {
|
||||
if (_entryData->_sourceType ==
|
||||
MacroConditionMedia::SourceType::SOURCE) {
|
||||
_entryData->_sourceGroup.clear();
|
||||
}
|
||||
|
||||
@@ -464,16 +533,19 @@ void MacroConditionMediaEdit::SourceTypeChanged(int idx)
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionMediaEdit::CheckTypeChanged(int idx)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_checkType = static_cast<MacroConditionMedia::CheckType>(
|
||||
_checkTypes->itemData(idx).toInt());
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionMediaEdit::SourceChanged(const SourceSelection &source)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_sourceGroup.clear();
|
||||
_entryData->_sourceType = MacroConditionMedia::Type::SOURCE;
|
||||
_entryData->ClearSignalHandler();
|
||||
_entryData->_sourceType = MacroConditionMedia::SourceType::SOURCE;
|
||||
_entryData->_source = source;
|
||||
_entryData->ResetSignalHandler();
|
||||
emit HeaderInfoChanged(
|
||||
@@ -483,40 +555,20 @@ void MacroConditionMediaEdit::SourceChanged(const SourceSelection &source)
|
||||
|
||||
void MacroConditionMediaEdit::SceneChanged(const SceneSelection &s)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_scene = s;
|
||||
_entryData->UpdateMediaSourcesOfSceneList();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
MacroConditionMedia::State getMediaStateFromIdx(int idx)
|
||||
{
|
||||
if (idx < static_cast<int>(
|
||||
MacroConditionMedia::State::LAST_OBS_MEDIA_STATE)) {
|
||||
return static_cast<MacroConditionMedia::State>(idx);
|
||||
} else {
|
||||
return static_cast<MacroConditionMedia::State>(
|
||||
idx -
|
||||
static_cast<int>(
|
||||
MacroConditionMedia::State::LAST_OBS_MEDIA_STATE) +
|
||||
custom_media_states_offset);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionMediaEdit::StateChanged(int index)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_state = getMediaStateFromIdx(index);
|
||||
if (_entryData->_sourceType != MacroConditionMedia::Type::SOURCE) {
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_state = static_cast<MacroConditionMedia::State>(
|
||||
_states->itemData(index).toInt());
|
||||
if (_entryData->_sourceType !=
|
||||
MacroConditionMedia::SourceType::SOURCE) {
|
||||
_entryData->UpdateMediaSourcesOfSceneList();
|
||||
}
|
||||
}
|
||||
@@ -527,7 +579,9 @@ void MacroConditionMediaEdit::TimeRestrictionChanged(int index)
|
||||
return;
|
||||
}
|
||||
|
||||
if (static_cast<MacroConditionMedia::Time>(index) ==
|
||||
const auto timeRestriction = static_cast<MacroConditionMedia::Time>(
|
||||
_timeRestrictions->itemData(index).toInt());
|
||||
if (timeRestriction ==
|
||||
MacroConditionMedia::Time::TIME_RESTRICTION_NONE) {
|
||||
_time->setDisabled(true);
|
||||
} else {
|
||||
@@ -535,9 +589,9 @@ void MacroConditionMediaEdit::TimeRestrictionChanged(int index)
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_restriction =
|
||||
static_cast<MacroConditionMedia::Time>(index);
|
||||
if (_entryData->_sourceType != MacroConditionMedia::Type::SOURCE) {
|
||||
_entryData->_timeRestriction = timeRestriction;
|
||||
if (_entryData->_sourceType !=
|
||||
MacroConditionMedia::SourceType::SOURCE) {
|
||||
_entryData->UpdateMediaSourcesOfSceneList();
|
||||
}
|
||||
}
|
||||
@@ -550,7 +604,8 @@ void MacroConditionMediaEdit::TimeChanged(const Duration &dur)
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_time = dur;
|
||||
if (_entryData->_sourceType != MacroConditionMedia::Type::SOURCE) {
|
||||
if (_entryData->_sourceType !=
|
||||
MacroConditionMedia::SourceType::SOURCE) {
|
||||
_entryData->UpdateMediaSourcesOfSceneList();
|
||||
}
|
||||
}
|
||||
@@ -558,20 +613,25 @@ void MacroConditionMediaEdit::TimeChanged(const Duration &dur)
|
||||
void MacroConditionMediaEdit::SetWidgetVisibility()
|
||||
{
|
||||
_sources->setVisible(_entryData->_sourceType ==
|
||||
MacroConditionMedia::Type::SOURCE);
|
||||
MacroConditionMedia::SourceType::SOURCE);
|
||||
_scenes->setVisible(_entryData->_sourceType !=
|
||||
MacroConditionMedia::Type::SOURCE);
|
||||
}
|
||||
MacroConditionMedia::SourceType::SOURCE);
|
||||
|
||||
static int getIdxFromMediaState(MacroConditionMedia::State state)
|
||||
{
|
||||
if (state < MacroConditionMedia::State::LAST_OBS_MEDIA_STATE) {
|
||||
return static_cast<int>(state);
|
||||
} else {
|
||||
return static_cast<int>(state) - custom_media_states_offset +
|
||||
static_cast<int>(
|
||||
MacroConditionMedia::State::LAST_OBS_MEDIA_STATE);
|
||||
if (_entryData->_checkType == MacroConditionMedia::CheckType::LEGACY) {
|
||||
_checkTypes->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
_states->setVisible(_entryData->_checkType ==
|
||||
MacroConditionMedia::CheckType::STATE);
|
||||
|
||||
_timeRestrictions->setVisible(_entryData->_checkType ==
|
||||
MacroConditionMedia::CheckType::TIME);
|
||||
_time->setVisible(_entryData->_checkType ==
|
||||
MacroConditionMedia::CheckType::TIME);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionMediaEdit::UpdateEntryData()
|
||||
@@ -580,15 +640,18 @@ void MacroConditionMediaEdit::UpdateEntryData()
|
||||
return;
|
||||
}
|
||||
|
||||
_checkTypes->setCurrentIndex(_checkTypes->findData(
|
||||
static_cast<int>(_entryData->_checkType)));
|
||||
_sourceTypes->setCurrentIndex(_sourceTypes->findData(
|
||||
static_cast<int>(_entryData->_sourceType)));
|
||||
_sources->SetSource(_entryData->_source);
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
_states->setCurrentIndex(getIdxFromMediaState(_entryData->_state));
|
||||
_timeRestrictions->setCurrentIndex(
|
||||
static_cast<int>(_entryData->_restriction));
|
||||
_states->setCurrentIndex(
|
||||
_states->findData(static_cast<int>(_entryData->_state)));
|
||||
_timeRestrictions->setCurrentIndex(_timeRestrictions->findData(
|
||||
static_cast<int>(_entryData->_timeRestriction)));
|
||||
_time->SetDuration(_entryData->_time);
|
||||
if (_entryData->_restriction ==
|
||||
if (_entryData->_timeRestriction ==
|
||||
MacroConditionMedia::Time::TIME_RESTRICTION_NONE) {
|
||||
_time->setDisabled(true);
|
||||
}
|
||||
|
||||
@@ -5,18 +5,18 @@
|
||||
#include "source-selection.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <obs.hpp>
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
|
||||
namespace advss {
|
||||
|
||||
constexpr auto custom_media_states_offset = 100;
|
||||
|
||||
class MacroConditionMedia : public MacroCondition {
|
||||
public:
|
||||
MacroConditionMedia(Macro *m) : MacroCondition(m) {}
|
||||
~MacroConditionMedia();
|
||||
MacroConditionMedia(const MacroConditionMedia &);
|
||||
MacroConditionMedia &operator=(const MacroConditionMedia &);
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj) const;
|
||||
bool Load(obs_data_t *obj);
|
||||
@@ -26,19 +26,17 @@ public:
|
||||
{
|
||||
return std::make_shared<MacroConditionMedia>(m);
|
||||
}
|
||||
void ClearSignalHandler();
|
||||
void ResetSignalHandler();
|
||||
void UpdateMediaSourcesOfSceneList();
|
||||
static void MediaStopped(void *data, calldata_t *);
|
||||
static void MediaEnded(void *data, calldata_t *);
|
||||
static void MediaNext(void *data, calldata_t *);
|
||||
|
||||
enum class Type {
|
||||
SOURCE,
|
||||
ANY,
|
||||
ALL,
|
||||
};
|
||||
Type _sourceType = Type::SOURCE;
|
||||
enum class SourceType { SOURCE, ANY, ALL };
|
||||
SourceType _sourceType = SourceType::SOURCE;
|
||||
|
||||
enum class CheckType { STATE, TIME, LEGACY = 1000 };
|
||||
CheckType _checkType = CheckType::STATE;
|
||||
|
||||
enum class State {
|
||||
// OBS's internal states
|
||||
@@ -53,19 +51,19 @@ public:
|
||||
// Just a marker
|
||||
LAST_OBS_MEDIA_STATE,
|
||||
// states added for use in the plugin
|
||||
PLAYLIST_ENDED = custom_media_states_offset,
|
||||
ANY,
|
||||
PLAYLIST_ENDED = 100,
|
||||
ANY
|
||||
};
|
||||
State _state = State::OBS_MEDIA_STATE_NONE;
|
||||
State _state = State::OBS_MEDIA_STATE_PLAYING;
|
||||
|
||||
enum class Time {
|
||||
TIME_RESTRICTION_NONE,
|
||||
TIME_RESTRICTION_SHORTER,
|
||||
TIME_RESTRICTION_LONGER,
|
||||
TIME_RESTRICTION_REMAINING_SHORTER,
|
||||
TIME_RESTRICTION_REMAINING_LONGER,
|
||||
TIME_RESTRICTION_REMAINING_LONGER
|
||||
};
|
||||
Time _restriction = Time::TIME_RESTRICTION_NONE;
|
||||
Time _timeRestriction = Time::TIME_RESTRICTION_REMAINING_SHORTER;
|
||||
|
||||
SceneSelection _scene;
|
||||
SourceSelection _source;
|
||||
@@ -74,12 +72,15 @@ public:
|
||||
Duration _time;
|
||||
|
||||
private:
|
||||
bool IsUsingLegacyCheck() const;
|
||||
bool CheckTime();
|
||||
bool CheckState();
|
||||
bool CheckPlaylistEnd(const obs_media_state);
|
||||
bool CheckMediaMatch();
|
||||
void HandleSceneChange();
|
||||
|
||||
std::vector<OBSSignal> _signals;
|
||||
|
||||
bool _stopped = false;
|
||||
bool _ended = false;
|
||||
bool _next = false;
|
||||
@@ -110,6 +111,7 @@ public:
|
||||
}
|
||||
|
||||
private slots:
|
||||
void CheckTypeChanged(int);
|
||||
void SourceTypeChanged(int);
|
||||
void SourceChanged(const SourceSelection &);
|
||||
void SceneChanged(const SceneSelection &);
|
||||
@@ -121,6 +123,7 @@ signals:
|
||||
|
||||
protected:
|
||||
QComboBox *_sourceTypes;
|
||||
QComboBox *_checkTypes;
|
||||
SceneSelectionWidget *_scenes;
|
||||
SourceSelectionWidget *_sources;
|
||||
QComboBox *_states;
|
||||
|
||||
Reference in New Issue
Block a user