From 5ad820d6cdcd0152a65de172e92be0c0a1fef389 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Mon, 12 Oct 2020 21:46:16 +0200 Subject: [PATCH] add new UI for media tab --- forms/advanced-scene-switcher.ui | 94 ------ src/headers/advanced-scene-switcher.hpp | 2 - src/headers/switch-media.hpp | 62 ++-- src/headers/switcher-data-structs.hpp | 7 +- src/switch-media.cpp | 378 +++++++++++++----------- 5 files changed, 246 insertions(+), 297 deletions(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index c0d11a2c..dfb9033e 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -2001,100 +2001,6 @@ Media - - - - - - When - - - - - - - - - - state is - - - - - - - - - - and - - - - - - - - - - ms - - - 0 - - - 1000000 - - - - - - - switch to - - - - - - - - 100 - 0 - - - - - - - - using the - - - - - - - - - - transition - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index 2c4bd60e..a56e7781 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -181,12 +181,10 @@ public slots: void on_fileUp_clicked(); void on_fileDown_clicked(); - void on_mediaSwitches_currentRowChanged(int idx); void on_mediaAdd_clicked(); void on_mediaRemove_clicked(); void on_mediaUp_clicked(); void on_mediaDown_clicked(); - void on_mediaTimeRestrictions_currentIndexChanged(int idx); void on_timeSwitches_currentRowChanged(int idx); void on_timeAdd_clicked(); diff --git a/src/headers/switch-media.hpp b/src/headers/switch-media.hpp index 8b9f1a2f..be15f755 100644 --- a/src/headers/switch-media.hpp +++ b/src/headers/switch-media.hpp @@ -1,5 +1,4 @@ #pragma once -#include #include "utility.hpp" #include "switch-generic.hpp" @@ -15,36 +14,57 @@ typedef enum { } time_restriction; struct MediaSwitch : SceneSwitcherEntry { - OBSWeakSource source; - obs_media_state state; - time_restriction restriction; - int64_t time; - bool matched; - std::string mediaSwitchStr; + OBSWeakSource source = nullptr; + obs_media_state state = OBS_MEDIA_STATE_NONE; + time_restriction restriction = TIME_RESTRICTION_NONE; + int64_t time = 0; - const char *getType() { return "meida"; } - - bool valid() - { - return (usePreviousScene || WeakSourceValid(scene)) && - WeakSourceValid(source) && WeakSourceValid(transition); - } + const char *getType() { return "media"; } + bool initialized(); + bool valid(); + inline MediaSwitch(){}; inline MediaSwitch(OBSWeakSource scene_, OBSWeakSource source_, OBSWeakSource transition_, obs_media_state state_, time_restriction restriction_, uint64_t time_, - bool usePreviousScene_, std::string mediaSwitchStr_) + bool usePreviousScene_) : SceneSwitcherEntry(scene_, transition_, usePreviousScene_), source(source_), state(state_), restriction(restriction_), - time(time_), - mediaSwitchStr(mediaSwitchStr_) + time(time_) { } }; -static inline QString -MakeMediaSwitchName(const QString &source, const QString &scene, - const QString &transition, obs_media_state state, - time_restriction restriction, uint64_t time); +class MediaSwitchWidget : public SwitchWidget { + Q_OBJECT + +public: + MediaSwitchWidget(MediaSwitch *s); + MediaSwitch *getSwitchData(); + void setSwitchData(MediaSwitch *s); + + static void swapSwitchData(MediaSwitchWidget *s1, + MediaSwitchWidget *s2); + +private slots: + void SourceChanged(const QString &text); + void StateChanged(int index); + void TimeRestrictionChanged(int index); + void TimeChanged(int time); + +private: + QComboBox *meidaSources; + QComboBox *states; + QComboBox *timeRestrictions; + QSpinBox *time; + + QLabel *whenLabel; + QLabel *stateLabel; + QLabel *andLabel; + QLabel *switchLabel; + QLabel *usingLabel; + + MediaSwitch *switchData; +}; diff --git a/src/headers/switcher-data-structs.hpp b/src/headers/switcher-data-structs.hpp index 53688c6e..11b7be23 100644 --- a/src/headers/switcher-data-structs.hpp +++ b/src/headers/switcher-data-structs.hpp @@ -20,7 +20,6 @@ #include "switch-window.hpp" #include "swtich-sequence.hpp" - constexpr auto default_interval = 300; constexpr auto previous_scene_name = "Previous Scene"; @@ -94,7 +93,7 @@ struct SwitcherData { std::vector sceneTransitions; std::vector defaultSceneTransitions; - std::vector mediaSwitches; + std::deque mediaSwitches; std::vector timeSwitches; QDateTime liveTime; @@ -147,8 +146,8 @@ struct SwitcherData { void autoStartStreamRecording(); bool checkPause(); void checkSceneSequence(bool &match, OBSWeakSource &scene, - OBSWeakSource &transition, - std::unique_lock &lock); + OBSWeakSource &transition, + std::unique_lock &lock); void checkIdleSwitch(bool &match, OBSWeakSource &scene, OBSWeakSource &transition); void checkWindowTitleSwitch(bool &match, OBSWeakSource &scene, diff --git a/src/switch-media.cpp b/src/switch-media.cpp index b5e7e552..7afbb332 100644 --- a/src/switch-media.cpp +++ b/src/switch-media.cpp @@ -1,69 +1,17 @@ #include "headers/advanced-scene-switcher.hpp" -void SceneSwitcher::on_mediaSwitches_currentRowChanged(int idx) -{ - if (loading) - return; - if (idx == -1) - return; - - QListWidgetItem *item = ui->mediaSwitches->item(idx); - - QString mediaSceneStr = item->data(Qt::UserRole).toString(); - - std::lock_guard lock(switcher->m); - for (auto &s : switcher->mediaSwitches) { - if (mediaSceneStr.compare(s.mediaSwitchStr.c_str()) == 0) { - QString sceneName = GetWeakSourceName(s.scene).c_str(); - QString sourceName = - GetWeakSourceName(s.source).c_str(); - QString transitionName = - GetWeakSourceName(s.transition).c_str(); - ui->mediaScenes->setCurrentText(sceneName); - ui->mediaSources->setCurrentText(sourceName); - ui->mediaTransitions->setCurrentText(transitionName); - ui->mediaStates->setCurrentIndex(s.state); - ui->mediaTimeRestrictions->setCurrentIndex( - s.restriction); - ui->mediaTime->setValue(s.time); - break; - } - } -} - void SceneSwitcher::on_mediaAdd_clicked() { - QString sourceName = ui->mediaSources->currentText(); - QString sceneName = ui->mediaScenes->currentText(); - QString transitionName = ui->mediaTransitions->currentText(); - obs_media_state state = - (obs_media_state)ui->mediaStates->currentIndex(); - time_restriction restriction = - (time_restriction)ui->mediaTimeRestrictions->currentIndex(); - uint64_t time = ui->mediaTime->value(); - - if (sceneName.isEmpty() || transitionName.isEmpty() || - sourceName.isEmpty()) - return; - - OBSWeakSource source = GetWeakSourceByQString(sourceName); - OBSWeakSource scene = GetWeakSourceByQString(sceneName); - OBSWeakSource transition = GetWeakTransitionByQString(transitionName); - - QString switchText = MakeMediaSwitchName(sourceName, sceneName, - transitionName, state, - restriction, time); - QVariant v = QVariant::fromValue(switchText); - - QListWidgetItem *item = - new QListWidgetItem(switchText, ui->mediaSwitches); - item->setData(Qt::UserRole, v); - std::lock_guard lock(switcher->m); - switcher->mediaSwitches.emplace_back( - scene, source, transition, state, restriction, time, - (sceneName == QString(previous_scene_name)), - switchText.toUtf8().constData()); + switcher->mediaSwitches.emplace_back(); + + QListWidgetItem *item; + item = new QListWidgetItem(ui->mediaSwitches); + ui->mediaSwitches->addItem(item); + MediaSwitchWidget *sw = + new MediaSwitchWidget(&switcher->mediaSwitches.back()); + item->setSizeHint(sw->minimumSizeHint()); + ui->mediaSwitches->setItemWidget(item, sw); } void SceneSwitcher::on_mediaRemove_clicked() @@ -72,20 +20,11 @@ void SceneSwitcher::on_mediaRemove_clicked() if (!item) return; - std::string mediaStr = - item->data(Qt::UserRole).toString().toUtf8().constData(); { std::lock_guard lock(switcher->m); + int idx = ui->mediaSwitches->currentRow(); auto &switches = switcher->mediaSwitches; - - for (auto it = switches.begin(); it != switches.end(); ++it) { - auto &s = *it; - - if (s.mediaSwitchStr == mediaStr) { - switches.erase(it); - break; - } - } + switches.erase(switches.begin() + idx); } delete item; @@ -94,50 +33,50 @@ void SceneSwitcher::on_mediaRemove_clicked() void SceneSwitcher::on_mediaUp_clicked() { int index = ui->mediaSwitches->currentRow(); - if (index != -1 && index != 0) { - ui->mediaSwitches->insertItem( - index - 1, ui->mediaSwitches->takeItem(index)); - ui->mediaSwitches->setCurrentRow(index - 1); + if (!listMoveUp(ui->mediaSwitches)) + return; - std::lock_guard lock(switcher->m); + MediaSwitchWidget *s1 = + (MediaSwitchWidget *)ui->mediaSwitches->itemWidget( + ui->mediaSwitches->item(index)); + MediaSwitchWidget *s2 = + (MediaSwitchWidget *)ui->mediaSwitches->itemWidget( + ui->mediaSwitches->item(index - 1)); + MediaSwitchWidget::swapSwitchData(s1, s2); - iter_swap(switcher->mediaSwitches.begin() + index, - switcher->mediaSwitches.begin() + index - 1); - } + std::lock_guard lock(switcher->m); + + std::swap(switcher->mediaSwitches[index], + switcher->mediaSwitches[index - 1]); } void SceneSwitcher::on_mediaDown_clicked() { int index = ui->mediaSwitches->currentRow(); - if (index != -1 && index != ui->mediaSwitches->count() - 1) { - ui->mediaSwitches->insertItem( - index + 1, ui->mediaSwitches->takeItem(index)); - ui->mediaSwitches->setCurrentRow(index + 1); - std::lock_guard lock(switcher->m); - - iter_swap(switcher->mediaSwitches.begin() + index, - switcher->mediaSwitches.begin() + index + 1); - } -} - -void SceneSwitcher::on_mediaTimeRestrictions_currentIndexChanged(int idx) -{ - if (idx == -1) + if (!listMoveDown(ui->mediaSwitches)) return; - if ((time_restriction)ui->mediaTimeRestrictions->currentIndex() == - TIME_RESTRICTION_NONE) { - ui->mediaTime->setDisabled(true); - } else { - ui->mediaTime->setDisabled(false); - } + MediaSwitchWidget *s1 = + (MediaSwitchWidget *)ui->mediaSwitches->itemWidget( + ui->mediaSwitches->item(index)); + MediaSwitchWidget *s2 = + (MediaSwitchWidget *)ui->mediaSwitches->itemWidget( + ui->mediaSwitches->item(index + 1)); + MediaSwitchWidget::swapSwitchData(s1, s2); + + std::lock_guard lock(switcher->m); + + std::swap(switcher->mediaSwitches[index], + switcher->mediaSwitches[index + 1]); } void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene, OBSWeakSource &transition) { for (MediaSwitch &mediaSwitch : mediaSwitches) { + if (!mediaSwitch.initialized()) + continue; obs_source_t *source = obs_weak_source_get_source(mediaSwitch.source); auto duration = obs_source_media_get_duration(source); @@ -158,7 +97,7 @@ void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene, TIME_RESTRICTION_REMAINING_LONGER && duration > time && duration - time > mediaSwitch.time)); - if (matched && !mediaSwitch.matched) { + if (matched) { match = true; scene = (mediaSwitch.usePreviousScene) ? previousScene @@ -167,8 +106,8 @@ void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene, if (verbose) mediaSwitch.logMatch(); + break; } - mediaSwitch.matched = matched; obs_source_release(source); } } @@ -233,17 +172,10 @@ void SwitcherData::loadMediaSwitches(obs_data_t *obj) "restriction"); uint64_t time = obs_data_get_int(array_obj, "time"); - std::string mediaStr = MakeMediaSwitchName(source, scene, - transition, state, - restriction, time) - .toUtf8() - .constData(); - switcher->mediaSwitches.emplace_back( GetWeakSourceByName(scene), GetWeakSourceByName(source), GetWeakTransitionByName(transition), state, restriction, - time, (strcmp(scene, previous_scene_name) == 0), - mediaStr); + time, (strcmp(scene, previous_scene_name) == 0)); obs_data_release(array_obj); } @@ -252,81 +184,175 @@ void SwitcherData::loadMediaSwitches(obs_data_t *obj) void SceneSwitcher::setupMediaTab() { - populateSceneSelection(ui->mediaScenes, true); - populateTransitionSelection(ui->mediaTransitions); - populateMediaSelection(ui->mediaSources); - - ui->mediaStates->addItem("None"); - ui->mediaStates->addItem("Playing"); - ui->mediaStates->addItem("Opening"); - ui->mediaStates->addItem("Buffering"); - ui->mediaStates->addItem("Paused"); - ui->mediaStates->addItem("Stopped"); - ui->mediaStates->addItem("Ended"); - ui->mediaStates->addItem("Error"); - - ui->mediaTimeRestrictions->addItem("None"); - ui->mediaTimeRestrictions->addItem("Time shorter"); - ui->mediaTimeRestrictions->addItem("Time longer"); - ui->mediaTimeRestrictions->addItem("Time remaining shorter"); - ui->mediaTimeRestrictions->addItem("Time remaining longer"); - for (auto &s : switcher->mediaSwitches) { std::string sourceName = GetWeakSourceName(s.source); std::string sceneName = (s.usePreviousScene) ? previous_scene_name : GetWeakSourceName(s.scene); std::string transitionName = GetWeakSourceName(s.transition); - QString listText = MakeMediaSwitchName( - sourceName.c_str(), sceneName.c_str(), - transitionName.c_str(), s.state, s.restriction, s.time); - QListWidgetItem *item = - new QListWidgetItem(listText, ui->mediaSwitches); - item->setData(Qt::UserRole, listText); + QListWidgetItem *item; + item = new QListWidgetItem(ui->mediaSwitches); + ui->mediaSwitches->addItem(item); + MediaSwitchWidget *sw = new MediaSwitchWidget(&s); + item->setSizeHint(sw->minimumSizeHint()); + ui->mediaSwitches->setItemWidget(item, sw); } } -static inline QString -MakeMediaSwitchName(const QString &source, const QString &scene, - const QString &transition, obs_media_state state, - time_restriction restriction, uint64_t time) +bool MediaSwitch::initialized() { - QString switchName = QStringLiteral("Switch to ") + scene + - QStringLiteral(" using ") + transition + - QStringLiteral(" if ") + source + - QStringLiteral(" state is "); - if (state == OBS_MEDIA_STATE_NONE) { - switchName += QStringLiteral("none"); - } else if (state == OBS_MEDIA_STATE_PLAYING) { - switchName += QStringLiteral("playing"); - } else if (state == OBS_MEDIA_STATE_OPENING) { - switchName += QStringLiteral("opening"); - } else if (state == OBS_MEDIA_STATE_BUFFERING) { - switchName += QStringLiteral("buffering"); - } else if (state == OBS_MEDIA_STATE_PAUSED) { - switchName += QStringLiteral("paused"); - } else if (state == OBS_MEDIA_STATE_STOPPED) { - switchName += QStringLiteral("stopped"); - } else if (state == OBS_MEDIA_STATE_ENDED) { - switchName += QStringLiteral("ended"); - } else if (state == OBS_MEDIA_STATE_ERROR) { - switchName += QStringLiteral("error"); - } - if (restriction == TIME_RESTRICTION_SHORTER) { - switchName += QStringLiteral(" and time shorter than "); - } else if (restriction == TIME_RESTRICTION_LONGER) { - switchName += QStringLiteral(" and time longer than "); - } else if (restriction == TIME_RESTRICTION_REMAINING_SHORTER) { - switchName += - QStringLiteral(" and time remaining shorter than "); - } else if (restriction == TIME_RESTRICTION_REMAINING_LONGER) { - switchName += - QStringLiteral(" and time remaining longer than "); - } - if (restriction != TIME_RESTRICTION_NONE) { - switchName += std::to_string(time).c_str(); - switchName += QStringLiteral(" ms"); - } - return switchName; + return SceneSwitcherEntry::initialized() && source; +} + +bool MediaSwitch::valid() +{ + return !initialized() || + (SceneSwitcherEntry::valid() && WeakSourceValid(source)); +} + +void populateMediaStates(QComboBox *list) +{ + list->addItem("None"); + list->addItem("Playing"); + list->addItem("Opening"); + list->addItem("Buffering"); + list->addItem("Paused"); + list->addItem("Stopped"); + list->addItem("Ended"); + list->addItem("Error"); +} + +void populateTimeRestrictions(QComboBox *list) +{ + list->addItem("None"); + list->addItem("Time shorter"); + list->addItem("Time longer"); + list->addItem("Time remaining shorter"); + list->addItem("Time remaining longer"); +} + +MediaSwitchWidget::MediaSwitchWidget(MediaSwitch *s) : SwitchWidget(s) +{ + meidaSources = new QComboBox(); + states = new QComboBox(); + timeRestrictions = new QComboBox(); + time = new QSpinBox(); + + whenLabel = new QLabel("When"); + stateLabel = new QLabel("state is"); + andLabel = new QLabel("and"); + switchLabel = new QLabel("switch to"); + usingLabel = new QLabel("using"); + + time->setSuffix("ms"); + time->setMaximum(99999999); + time->setMinimum(0); + + QWidget::connect(meidaSources, + SIGNAL(currentTextChanged(const QString &)), this, + SLOT(SourceChanged(const QString &))); + QWidget::connect(states, SIGNAL(currentIndexChanged(int)), this, + SLOT(StateChanged(int))); + QWidget::connect(timeRestrictions, SIGNAL(currentIndexChanged(int)), + this, SLOT(TimeRestrictionChanged(int))); + QWidget::connect(states, SIGNAL(currentIndexChanged(int)), this, + SLOT(StateChanged(const QString &))); + QWidget::connect(time, SIGNAL(valueChanged(int)), this, + SLOT(TimeChanged(int))); + + SceneSwitcher::populateMediaSelection(meidaSources); + populateMediaStates(states); + populateTimeRestrictions(timeRestrictions); + + if (s) { + meidaSources->setCurrentText( + GetWeakSourceName(s->source).c_str()); + states->setCurrentIndex(s->state); + timeRestrictions->setCurrentIndex(s->restriction); + time->setValue(s->time); + if (s->restriction == TIME_RESTRICTION_NONE) + time->setDisabled(true); + } + + setStyleSheet("* { background-color: transparent; }"); + + QHBoxLayout *mainLayout = new QHBoxLayout; + + mainLayout->addWidget(whenLabel); + mainLayout->addWidget(meidaSources); + mainLayout->addWidget(stateLabel); + mainLayout->addWidget(states); + mainLayout->addWidget(andLabel); + mainLayout->addWidget(timeRestrictions); + mainLayout->addWidget(time); + mainLayout->addWidget(switchLabel); + mainLayout->addWidget(scenes); + mainLayout->addWidget(usingLabel); + mainLayout->addWidget(transitions); + mainLayout->addStretch(); + + setLayout(mainLayout); + + switchData = s; + + loading = false; +} + +MediaSwitch *MediaSwitchWidget::getSwitchData() +{ + return switchData; +} + +void MediaSwitchWidget::setSwitchData(MediaSwitch *s) +{ + switchData = s; +} + +void MediaSwitchWidget::swapSwitchData(MediaSwitchWidget *s1, + MediaSwitchWidget *s2) +{ + SwitchWidget::swapSwitchData(s1, s2); + + MediaSwitch *t = s1->getSwitchData(); + s1->setSwitchData(s2->getSwitchData()); + s2->setSwitchData(t); +} + +void MediaSwitchWidget::SourceChanged(const QString &text) +{ + if (loading || !switchData) + return; + std::lock_guard lock(switcher->m); + switchData->source = GetWeakSourceByQString(text); +} + +void MediaSwitchWidget::StateChanged(int index) +{ + if (loading || !switchData) + return; + std::lock_guard lock(switcher->m); + switchData->state = (obs_media_state)index; +} + +void MediaSwitchWidget::TimeRestrictionChanged(int index) +{ + if (loading || !switchData) + return; + + if ((time_restriction)index == TIME_RESTRICTION_NONE) + time->setDisabled(true); + else + time->setDisabled(false); + + std::lock_guard lock(switcher->m); + switchData->restriction = (time_restriction)index; +} + +void MediaSwitchWidget::TimeChanged(int time) +{ + if (loading || !switchData) + return; + std::lock_guard lock(switcher->m); + switchData->time = time; }