From 5496c256c0eaae2af02576828a72c7058d0ca210 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Mon, 24 May 2021 14:28:12 +0200 Subject: [PATCH] Move functions not required in advanced-scene-switcher.hpp Create header for platform specific functions. Move some UI helper functions to utility.hpp. --- CMakeLists.txt | 4 +- src/advanced-scene-switcher.cpp | 328 -------------- src/general.cpp | 7 +- src/headers/advanced-scene-switcher.hpp | 62 +-- src/headers/platform-funcs.hpp | 11 + src/headers/utility.hpp | 268 ++---------- src/macro-action-audio.cpp | 2 +- src/macro-action-media.cpp | 2 +- src/macro-action-scene-visibility.cpp | 2 +- src/macro-action-source.cpp | 18 +- src/macro-condition-audio.cpp | 2 +- src/macro-condition-media.cpp | 2 +- src/macro-condition-process.cpp | 2 +- src/macro-condition-scene.cpp | 2 +- src/macro-condition-video.cpp | 2 +- src/macro-condition-window.cpp | 2 +- src/macro-tab.cpp | 4 +- src/scene-group.cpp | 5 +- src/scene-trigger.cpp | 11 +- src/switch-audio.cpp | 6 +- src/switch-executable.cpp | 7 +- src/switch-file.cpp | 4 +- src/switch-generic.cpp | 7 +- src/switch-media.cpp | 6 +- src/switch-pause.cpp | 6 +- src/switch-random.cpp | 11 +- src/switch-screen-region.cpp | 9 +- src/switch-sequence.cpp | 7 +- src/switch-time.cpp | 4 +- src/switch-transitions.cpp | 2 +- src/switch-video.cpp | 9 +- src/switch-window.cpp | 7 +- src/utility.cpp | 555 ++++++++++++++++++++++++ 33 files changed, 700 insertions(+), 676 deletions(-) create mode 100644 src/headers/platform-funcs.hpp create mode 100644 src/utility.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 75b31bfa..c4665f57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,7 +62,6 @@ set(advanced-scene-switcher_HEADERS ${advanced-scene-switcher_HEADERS} src/headers/advanced-scene-switcher.hpp src/headers/switcher-data-structs.hpp - src/headers/utility.hpp src/headers/scene-group.hpp src/headers/scene-trigger.hpp src/headers/switch-audio.hpp @@ -113,6 +112,8 @@ set(advanced-scene-switcher_HEADERS src/headers/name-dialog.hpp src/headers/duration-control.hpp src/headers/section.hpp + src/headers/platform-funcs.hpp + src/headers/utility.hpp src/headers/volume-control.hpp src/headers/version.h ) @@ -176,6 +177,7 @@ set(advanced-scene-switcher_SOURCES src/name-dialog.cpp src/duration-control.cpp src/section.cpp + src/utility.cpp src/volume-control.cpp src/version.cpp ) diff --git a/src/advanced-scene-switcher.cpp b/src/advanced-scene-switcher.cpp index f416c638..d3105c54 100644 --- a/src/advanced-scene-switcher.cpp +++ b/src/advanced-scene-switcher.cpp @@ -1,13 +1,8 @@ #include #include -#include -#include -#include -#include #include #include -#include #include "headers/advanced-scene-switcher.hpp" #include "headers/curl-helper.hpp" @@ -72,329 +67,6 @@ void AdvSceneSwitcher::loadUI() loading = false; } -/****************************************************************************** - * UI helpers - ******************************************************************************/ -void AdvSceneSwitcher::addSelectionEntry(QComboBox *sel, - const char *description, - bool selectable, const char *tooltip) -{ - sel->addItem(description); - - if (strcmp(tooltip, "") != 0) { - sel->setItemData(0, tooltip, Qt::ToolTipRole); - } - - QStandardItemModel *model = - qobject_cast(sel->model()); - QModelIndex firstIndex = - model->index(0, sel->modelColumn(), sel->rootModelIndex()); - QStandardItem *firstItem = model->itemFromIndex(firstIndex); - if (!selectable) { - firstItem->setSelectable(false); - firstItem->setEnabled(false); - } -} - -void AdvSceneSwitcher::populateSceneSelection(QComboBox *sel, bool addPrevious, - bool addSceneGroup, - bool addSelect, - std::string selectText, - bool selectable) -{ - if (addSelect) { - if (selectText.empty()) { - addSelectionEntry( - sel, - obs_module_text("AdvSceneSwitcher.selectScene"), - selectable, - obs_module_text( - "AdvSceneSwitcher.invaildEntriesWillNotBeSaved")); - } else { - addSelectionEntry(sel, selectText.c_str(), selectable); - } - } - - BPtr scenes = obs_frontend_get_scene_names(); - char **temp = scenes; - while (*temp) { - const char *name = *temp; - sel->addItem(name); - temp++; - } - - if (addPrevious) { - sel->addItem(obs_module_text( - "AdvSceneSwitcher.selectPreviousScene")); - } - - if (addSceneGroup) { - for (auto &sg : switcher->sceneGroups) { - sel->addItem(QString::fromStdString(sg.name)); - } - } -} - -void AdvSceneSwitcher::populateTransitionSelection(QComboBox *sel, - bool addCurrent, - bool addSelect, - bool selectable) -{ - if (addSelect) { - addSelectionEntry( - sel, - obs_module_text("AdvSceneSwitcher.selectTransition"), - selectable); - } - - if (addCurrent) { - sel->addItem( - obs_module_text("AdvSceneSwitcher.currentTransition")); - } - - obs_frontend_source_list *transitions = new obs_frontend_source_list(); - obs_frontend_get_transitions(transitions); - - for (size_t i = 0; i < transitions->sources.num; i++) { - const char *name = - obs_source_get_name(transitions->sources.array[i]); - sel->addItem(name); - } - - obs_frontend_source_list_free(transitions); -} - -void AdvSceneSwitcher::populateWindowSelection(QComboBox *sel, bool addSelect) -{ - if (addSelect) { - addSelectionEntry( - sel, obs_module_text("AdvSceneSwitcher.selectWindow")); - } - - std::vector windows; - GetWindowList(windows); - sort(windows.begin(), windows.end()); - - for (std::string &window : windows) { - sel->addItem(window.c_str()); - } - -#ifdef WIN32 - sel->setItemData(0, obs_module_text("AdvSceneSwitcher.selectWindowTip"), - Qt::ToolTipRole); -#endif -} - -void AdvSceneSwitcher::populateAudioSelection(QComboBox *sel, bool addSelect) -{ - if (addSelect) { - addSelectionEntry( - sel, - obs_module_text("AdvSceneSwitcher.selectAudioSource"), - false, - obs_module_text( - "AdvSceneSwitcher.invaildEntriesWillNotBeSaved")); - } - - auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */ - { - std::vector *list = - reinterpret_cast *>(data); - uint32_t flags = obs_source_get_output_flags(source); - - if ((flags & OBS_SOURCE_AUDIO) != 0) { - list->push_back(obs_source_get_name(source)); - } - return true; - }; - - std::vector audioSources; - obs_enum_sources(sourceEnum, &audioSources); - sort(audioSources.begin(), audioSources.end()); - for (std::string &source : audioSources) { - sel->addItem(source.c_str()); - } -} - -void AdvSceneSwitcher::populateVideoSelection(QComboBox *sel, bool addScenes, - bool addSelect) -{ - if (addSelect) { - addSelectionEntry( - sel, - obs_module_text("AdvSceneSwitcher.selectVideoSource"), - false, - obs_module_text( - "AdvSceneSwitcher.invaildEntriesWillNotBeSaved")); - } - - auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */ - { - std::vector *list = - reinterpret_cast *>(data); - uint32_t flags = obs_source_get_output_flags(source); - std::string test = obs_source_get_name(source); - if ((flags & (OBS_SOURCE_VIDEO | OBS_SOURCE_ASYNC)) != 0) { - list->push_back(obs_source_get_name(source)); - } - return true; - }; - - std::vector videoSources; - obs_enum_sources(sourceEnum, &videoSources); - sort(videoSources.begin(), videoSources.end()); - for (std::string &source : videoSources) { - sel->addItem(source.c_str()); - } - - if (addScenes) { - populateSceneSelection(sel, false, false, false); - } -} - -void AdvSceneSwitcher::populateMediaSelection(QComboBox *sel, bool addSelect) -{ - if (addSelect) { - addSelectionEntry( - sel, - obs_module_text("AdvSceneSwitcher.selectMediaSource"), - false, - obs_module_text( - "AdvSceneSwitcher.invaildEntriesWillNotBeSaved")); - } - - auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */ - { - std::vector *list = - reinterpret_cast *>(data); - std::string sourceId = obs_source_get_id(source); - if (sourceId.compare("ffmpeg_source") == 0 || - sourceId.compare("vlc_source") == 0) { - list->push_back(obs_source_get_name(source)); - } - return true; - }; - - std::vector mediaSources; - obs_enum_sources(sourceEnum, &mediaSources); - sort(mediaSources.begin(), mediaSources.end()); - for (std::string &source : mediaSources) { - sel->addItem(source.c_str()); - } -} - -void AdvSceneSwitcher::populateProcessSelection(QComboBox *sel, bool addSelect) -{ - if (addSelect) { - addSelectionEntry( - sel, obs_module_text("AdvSceneSwitcher.selectProcess")); - } - - QStringList processes; - GetProcessList(processes); - processes.sort(); - for (QString &process : processes) - sel->addItem(process); -} - -void AdvSceneSwitcher::listAddClicked(QListWidget *list, - SwitchWidget *newWidget, - QPushButton *addButton, - QMetaObject::Connection *addHighlight) -{ - if (!list || !newWidget) { - blog(LOG_WARNING, - "listAddClicked called without valid list or widget"); - return; - } - - if (addButton && addHighlight) { - addButton->disconnect(*addHighlight); - } - - QListWidgetItem *item; - item = new QListWidgetItem(list); - list->addItem(item); - item->setSizeHint(newWidget->minimumSizeHint()); - list->setItemWidget(item, newWidget); - - list->scrollToItem(item); -} - -bool AdvSceneSwitcher::listMoveUp(QListWidget *list) -{ - int index = list->currentRow(); - if (index == -1 || index == 0) { - return false; - } - - QWidget *row = list->itemWidget(list->currentItem()); - QListWidgetItem *itemN = list->currentItem()->clone(); - - list->insertItem(index - 1, itemN); - list->setItemWidget(itemN, row); - - list->takeItem(index + 1); - list->setCurrentRow(index - 1); - return true; -} - -bool AdvSceneSwitcher::listMoveDown(QListWidget *list) -{ - int index = list->currentRow(); - if (index == -1 || index == list->count() - 1) { - return false; - } - - QWidget *row = list->itemWidget(list->currentItem()); - QListWidgetItem *itemN = list->currentItem()->clone(); - - list->insertItem(index + 2, itemN); - list->setItemWidget(itemN, row); - - list->takeItem(index); - list->setCurrentRow(index + 1); - return true; -} - -QMetaObject::Connection AdvSceneSwitcher::PulseWidget(QWidget *widget, - QColor endColor, - QColor startColor, - QString specifier) -{ - if (switcher->disableHints) { - return QMetaObject::Connection(); - } - - widget->setStyleSheet(specifier + "{ \ - border-style: outset; \ - border-width: 2px; \ - border-radius: 10px; \ - border-color: rgb(0,0,0,0) \ - }"); - - QGraphicsColorizeEffect *eEffect = new QGraphicsColorizeEffect(widget); - widget->setGraphicsEffect(eEffect); - QPropertyAnimation *paAnimation = - new QPropertyAnimation(eEffect, "color"); - paAnimation->setStartValue(startColor); - paAnimation->setEndValue(endColor); - paAnimation->setDuration(1000); - // Play backwards to return to original state on timer end - paAnimation->setDirection(QAbstractAnimation::Backward); - - auto con = QWidget::connect( - paAnimation, &QPropertyAnimation::finished, [paAnimation]() { - QTimer::singleShot(1000, [paAnimation] { - paAnimation->start(); - }); - }); - - paAnimation->start(); - - return con; -} - /****************************************************************************** * Saving and loading ******************************************************************************/ diff --git a/src/general.cpp b/src/general.cpp index 161c8519..4e903cb7 100644 --- a/src/general.cpp +++ b/src/general.cpp @@ -156,8 +156,11 @@ void AdvSceneSwitcher::SetStopped() obs_module_text("AdvSceneSwitcher.generalTab.status.start")); ui->pluginRunningText->setText( obs_module_text("AdvSceneSwitcher.status.inactive")); - inactivePluse = PulseWidget(ui->pluginRunningText, QColor(Qt::red), - QColor(0, 0, 0, 0), "QLabel "); + if (!switcher->disableHints) { + inactivePluse = PulseWidget(ui->pluginRunningText, + QColor(Qt::red), QColor(0, 0, 0, 0), + "QLabel "); + } currentStatusActive = false; } diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index c5c7fde4..519adc9b 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -5,6 +5,7 @@ #include "ui_advanced-scene-switcher.h" #endif #include "switcher-data-structs.hpp" +#include "platform-funcs.hpp" #define blog(level, msg, ...) blog(level, "[adv-ss] " msg, ##__VA_ARGS__) #define vblog(level, msg, ...) \ @@ -68,44 +69,8 @@ public: void setupMacroTab(); void setTabOrder(); void restoreWindowGeo(); - static void AskBackup(obs_data_t *obj); - static void addSelectionEntry(QComboBox *sel, const char *description, - bool selectable = false, - const char *tooltip = ""); - static void populateSceneSelection(QComboBox *sel, - bool addPrevious = false, - bool addSceneGroup = false, - bool addSelect = true, - std::string selectText = "", - bool selectable = false); - - static void populateTransitionSelection(QComboBox *sel, - bool addCurrent = true, - bool addSelect = true, - bool selectable = false); - static void populateWindowSelection(QComboBox *sel, - bool addSelect = true); - static void populateAudioSelection(QComboBox *sel, - bool addSelect = true); - static void populateVideoSelection(QComboBox *sel, - bool addScenes = true, - bool addSelect = true); - static void populateMediaSelection(QComboBox *sel, - bool addSelect = true); - static void populateProcessSelection(QComboBox *sel, - bool addSelect = true); - QMetaObject::Connection PulseWidget(QWidget *widget, QColor endColor, - QColor = QColor(0, 0, 0, 0), - QString specifier = "QLabel "); - - void listAddClicked(QListWidget *list, SwitchWidget *newWidget, - QPushButton *addButton = nullptr, - QMetaObject::Connection *addHighlight = nullptr); - bool listMoveUp(QListWidget *list); - bool listMoveDown(QListWidget *list); - signals: void MacroAdded(const QString &name); void MacroRemoved(const QString &name); @@ -280,31 +245,6 @@ public slots: private: }; -/****************************************************************************** - * Windowtitle helper - ******************************************************************************/ -void GetWindowList(std::vector &windows); -void GetWindowList(QStringList &windows); -void GetCurrentWindowTitle(std::string &title); -bool isFullscreen(const std::string &title); -bool isMaximized(const std::string &title); - -/****************************************************************************** - * Screenregion helper - ******************************************************************************/ -std::pair getCursorPos(); - -/****************************************************************************** - * Idle detection helper - ******************************************************************************/ -int secondsSinceLastInput(); - -/****************************************************************************** - * Executable helper - ******************************************************************************/ -void GetProcessList(QStringList &processes); -bool isInFocus(const QString &executable); - /****************************************************************************** * Sceneswitch helper ******************************************************************************/ diff --git a/src/headers/platform-funcs.hpp b/src/headers/platform-funcs.hpp new file mode 100644 index 00000000..d6164901 --- /dev/null +++ b/src/headers/platform-funcs.hpp @@ -0,0 +1,11 @@ +#pragma once + +void GetWindowList(std::vector &windows); +void GetWindowList(QStringList &windows); +void GetCurrentWindowTitle(std::string &title); +bool isFullscreen(const std::string &title); +bool isMaximized(const std::string &title); +std::pair getCursorPos(); +int secondsSinceLastInput(); +void GetProcessList(QStringList &processes); +bool isInFocus(const QString &executable); diff --git a/src/headers/utility.hpp b/src/headers/utility.hpp index f39835b8..b300629e 100644 --- a/src/headers/utility.hpp +++ b/src/headers/utility.hpp @@ -1,139 +1,26 @@ #pragma once - #include -#include #include -#include -#include -#include - +#include +#include +#include +#include +#include #include -#include #include +#include +#include +#include "scene-group.hpp" -static inline bool WeakSourceValid(obs_weak_source_t *ws) -{ - obs_source_t *source = obs_weak_source_get_source(ws); - if (source) { - obs_source_release(source); - } - return !!source; -} - -static inline std::string GetWeakSourceName(obs_weak_source_t *weak_source) -{ - std::string name; - - obs_source_t *source = obs_weak_source_get_source(weak_source); - if (source) { - name = obs_source_get_name(source); - obs_source_release(source); - } - - return name; -} - -static inline OBSWeakSource GetWeakSourceByName(const char *name) -{ - OBSWeakSource weak; - obs_source_t *source = obs_get_source_by_name(name); - if (source) { - weak = obs_source_get_weak_source(source); - obs_weak_source_release(weak); - obs_source_release(source); - } - - return weak; -} - -static inline OBSWeakSource GetWeakSourceByQString(const QString &name) -{ - return GetWeakSourceByName(name.toUtf8().constData()); -} - -static inline OBSWeakSource GetWeakTransitionByName(const char *transitionName) -{ - OBSWeakSource weak; - obs_source_t *source = nullptr; - - if (strcmp(transitionName, "Default") == 0) { - source = obs_frontend_get_current_transition(); - weak = obs_source_get_weak_source(source); - obs_source_release(source); - obs_weak_source_release(weak); - return weak; - } - - obs_frontend_source_list *transitions = new obs_frontend_source_list(); - obs_frontend_get_transitions(transitions); - bool match = false; - - for (size_t i = 0; i < transitions->sources.num; i++) { - const char *name = - obs_source_get_name(transitions->sources.array[i]); - if (strcmp(transitionName, name) == 0) { - match = true; - source = transitions->sources.array[i]; - break; - } - } - - if (match) { - weak = obs_source_get_weak_source(source); - obs_weak_source_release(weak); - } - obs_frontend_source_list_free(transitions); - - return weak; -} - -static inline OBSWeakSource GetWeakTransitionByQString(const QString &name) -{ - return GetWeakTransitionByName(name.toUtf8().constData()); -} - -static inline OBSWeakSource GetWeakFilterByName(OBSWeakSource source, - const char *name) -{ - OBSWeakSource weak; - auto s = obs_weak_source_get_source(source); - if (s) { - auto filterSource = obs_source_get_filter_by_name(s, name); - weak = obs_source_get_weak_source(filterSource); - obs_weak_source_release(weak); - obs_source_release(filterSource); - obs_source_release(s); - } - return weak; -} - -static inline OBSWeakSource GetWeakFilterByQString(OBSWeakSource source, - const QString &name) -{ - return GetWeakFilterByName(source, name.toUtf8().constData()); -} - -static inline std::string -getNextDelim(const std::string &text, - std::unordered_map placeholders) -{ - size_t pos = std::string::npos; - std::string res = ""; - - for (const auto &ph : placeholders) { - size_t newPos = text.find(ph.first); - if (newPos <= pos) { - pos = newPos; - res = ph.first; - } - } - - if (pos == std::string::npos) { - return ""; - } - - return res; -} +bool WeakSourceValid(obs_weak_source_t *ws); +std::string GetWeakSourceName(obs_weak_source_t *weak_source); +OBSWeakSource GetWeakSourceByName(const char *name); +OBSWeakSource GetWeakSourceByQString(const QString &name); +OBSWeakSource GetWeakTransitionByName(const char *transitionName); +OBSWeakSource GetWeakTransitionByQString(const QString &name); +OBSWeakSource GetWeakFilterByName(OBSWeakSource source, const char *name); +OBSWeakSource GetWeakFilterByQString(OBSWeakSource source, const QString &name); +bool compareIgnoringLineEnding(QString &s1, QString &s2); /** * Populate layout with labels and widgets based on provided text @@ -143,95 +30,32 @@ getNextDelim(const std::string &text, * @param placeholders Map containing a mapping of placeholder strings to widgets. * @param addStretch Add addStretch() to layout. */ -static inline void -placeWidgets(std::string text, QBoxLayout *layout, - std::unordered_map placeholders, - bool addStretch = true) -{ - std::vector> labelsWidgetsPairs; - - std::string delim = getNextDelim(text, placeholders); - while (delim != "") { - size_t pos = text.find(delim); - if (pos != std::string::npos) { - labelsWidgetsPairs.emplace_back(text.substr(0, pos), - placeholders[delim]); - text.erase(0, pos + delim.length()); - } - delim = getNextDelim(text, placeholders); - } - - if (text != "") { - labelsWidgetsPairs.emplace_back(text, nullptr); - } - - for (auto &lw : labelsWidgetsPairs) { - if (lw.first != "") { - layout->addWidget(new QLabel(lw.first.c_str())); - } - if (lw.second) { - layout->addWidget(lw.second); - } - } - if (addStretch) { - layout->addStretch(); - } -} - -static inline void clearLayout(QLayout *layout) -{ - QLayoutItem *item; - while ((item = layout->takeAt(0))) { - if (item->layout()) { - clearLayout(item->layout()); - delete item->layout(); - } - if (item->widget()) { - delete item->widget(); - } - delete item; - } -} - -static inline bool compareIgnoringLineEnding(QString &s1, QString &s2) -{ - // Let QT deal with different types of lineendings - QTextStream s1stream(&s1); - QTextStream s2stream(&s2); - - while (!s1stream.atEnd() || !s2stream.atEnd()) { - QString s1s = s1stream.readLine(); - QString s2s = s2stream.readLine(); - if (s1s != s2s) { - return false; - } - } - - if (!s1stream.atEnd() && !s2stream.atEnd()) { - return false; - } - - return true; -} - -static inline bool DisplayMessage(const QString &msg, bool question = false) -{ - if (question) { - QMessageBox::StandardButton reply; - reply = QMessageBox::question( - nullptr, "Advanced Scene Switcher", msg, - QMessageBox::Yes | QMessageBox::No); - if (reply == QMessageBox::Yes) { - return true; - } else { - return false; - } - } else { - QMessageBox Msgbox; - Msgbox.setWindowTitle("Advanced Scene Switcher"); - Msgbox.setText(msg); - Msgbox.exec(); - } - - return false; -} +void placeWidgets(std::string text, QBoxLayout *layout, + std::unordered_map placeholders, + bool addStretch = true); +void clearLayout(QLayout *layout); +QMetaObject::Connection PulseWidget(QWidget *widget, QColor endColor, + QColor = QColor(0, 0, 0, 0), + QString specifier = "QLabel "); +void listAddClicked(QListWidget *list, QWidget *newWidget, + QPushButton *addButton = nullptr, + QMetaObject::Connection *addHighlight = nullptr); +bool listMoveUp(QListWidget *list); +bool listMoveDown(QListWidget *list); +bool DisplayMessage(const QString &msg, bool question = false); +void addSelectionEntry(QComboBox *sel, const char *description, + bool selectable = false, const char *tooltip = ""); +void populateTransitionSelection(QComboBox *sel, bool addCurrent = true, + bool addSelect = true, + bool selectable = false); +void populateWindowSelection(QComboBox *sel, bool addSelect = true); +void populateAudioSelection(QComboBox *sel, bool addSelect = true); +void populateVideoSelection(QComboBox *sel, bool addSelect = true); +void populateMediaSelection(QComboBox *sel, bool addSelect = true); +void populateProcessSelection(QComboBox *sel, bool addSelect = true); +void populateSourceSelection(QComboBox *list, bool addSelect = true); +void populateSceneSelection(QComboBox *sel, bool addPrevious = false, + bool addSceneGroup = false, + std::deque *sceneGroups = nullptr, + bool addSelect = true, std::string selectText = "", + bool selectable = false); diff --git a/src/macro-action-audio.cpp b/src/macro-action-audio.cpp index 354c8b90..ca4bf929 100644 --- a/src/macro-action-audio.cpp +++ b/src/macro-action-audio.cpp @@ -94,7 +94,7 @@ MacroActionAudioEdit::MacroActionAudioEdit( _volumePercent->setSuffix("%"); populateActionSelection(_actions); - AdvSceneSwitcher::populateAudioSelection(_audioSources); + populateAudioSelection(_audioSources); QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, SLOT(ActionChanged(int))); diff --git a/src/macro-action-media.cpp b/src/macro-action-media.cpp index 827bc583..8e0e890d 100644 --- a/src/macro-action-media.cpp +++ b/src/macro-action-media.cpp @@ -99,7 +99,7 @@ MacroActionMediaEdit::MacroActionMediaEdit( _actions = new QComboBox(); populateActionSelection(_actions); - AdvSceneSwitcher::populateMediaSelection(_mediaSources); + populateMediaSelection(_mediaSources); QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, SLOT(ActionChanged(int))); diff --git a/src/macro-action-scene-visibility.cpp b/src/macro-action-scene-visibility.cpp index c1b480ae..3d2b1f03 100644 --- a/src/macro-action-scene-visibility.cpp +++ b/src/macro-action-scene-visibility.cpp @@ -124,7 +124,7 @@ MacroActionSceneVisibilityEdit::MacroActionSceneVisibilityEdit( _actions = new QComboBox(); populateActionSelection(_actions); - AdvSceneSwitcher::populateSceneSelection(_scenes); + populateSceneSelection(_scenes); QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, SLOT(ActionChanged(int))); diff --git a/src/macro-action-source.cpp b/src/macro-action-source.cpp index b58f2cfb..8da1d692 100644 --- a/src/macro-action-source.cpp +++ b/src/macro-action-source.cpp @@ -67,22 +67,6 @@ static inline void populateActionSelection(QComboBox *list) } } -static inline void populateSources(QComboBox *list) -{ - auto enumSourcesWithSources = [](void *param, obs_source_t *source) { - if (!source) { - return true; - } - QComboBox *list = reinterpret_cast(param); - list->addItem(obs_source_get_name(source)); - return true; - }; - - list->clear(); - list->addItem(obs_module_text("AdvSceneSwitcher.selectSource")); - obs_enum_sources(enumSourcesWithSources, list); -} - MacroActionSourceEdit::MacroActionSourceEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent) @@ -91,7 +75,7 @@ MacroActionSourceEdit::MacroActionSourceEdit( _actions = new QComboBox(); populateActionSelection(_actions); - populateSources(_sources); + populateSourceSelection(_sources); QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, SLOT(ActionChanged(int))); diff --git a/src/macro-condition-audio.cpp b/src/macro-condition-audio.cpp index b84d6795..dbb0c83b 100644 --- a/src/macro-condition-audio.cpp +++ b/src/macro-condition-audio.cpp @@ -139,7 +139,7 @@ MacroConditionAudioEdit::MacroConditionAudioEdit( SIGNAL(currentTextChanged(const QString &)), this, SLOT(SourceChanged(const QString &))); - AdvSceneSwitcher::populateAudioSelection(_audioSources); + populateAudioSelection(_audioSources); populateConditionSelection(_condition); QHBoxLayout *switchLayout = new QHBoxLayout; diff --git a/src/macro-condition-media.cpp b/src/macro-condition-media.cpp index d0e46bc2..d05ce8fd 100644 --- a/src/macro-condition-media.cpp +++ b/src/macro-condition-media.cpp @@ -256,7 +256,7 @@ MacroConditionMediaEdit::MacroConditionMediaEdit( QWidget::connect(_time, SIGNAL(UnitChanged(DurationUnit)), this, SLOT(TimeUnitChanged(DurationUnit))); - AdvSceneSwitcher::populateMediaSelection(_mediaSources); + populateMediaSelection(_mediaSources); populateMediaStates(_states); populateMediaTimeRestrictions(_timeRestrictions); diff --git a/src/macro-condition-process.cpp b/src/macro-condition-process.cpp index eb1ab373..a71341de 100644 --- a/src/macro-condition-process.cpp +++ b/src/macro-condition-process.cpp @@ -61,7 +61,7 @@ MacroConditionProcessEdit::MacroConditionProcessEdit( QWidget::connect(_focused, SIGNAL(stateChanged(int)), this, SLOT(FocusChanged(int))); - AdvSceneSwitcher::populateProcessSelection(_processSelection); + populateProcessSelection(_processSelection); std::unordered_map widgetPlaceholders = { {"{{processes}}", _processSelection}, diff --git a/src/macro-condition-scene.cpp b/src/macro-condition-scene.cpp index 8508b9cd..c0b99799 100644 --- a/src/macro-condition-scene.cpp +++ b/src/macro-condition-scene.cpp @@ -79,7 +79,7 @@ MacroConditionSceneEdit::MacroConditionSceneEdit( QWidget::connect(_duration, SIGNAL(UnitChanged(DurationUnit)), this, SLOT(DurationUnitChanged(DurationUnit))); - AdvSceneSwitcher::populateSceneSelection(_sceneSelection); + populateSceneSelection(_sceneSelection); populateTypeSelection(_sceneType); QHBoxLayout *mainLayout = new QHBoxLayout; diff --git a/src/macro-condition-video.cpp b/src/macro-condition-video.cpp index 85241501..66d55f74 100644 --- a/src/macro-condition-video.cpp +++ b/src/macro-condition-video.cpp @@ -160,7 +160,7 @@ MacroConditionVideoEdit::MacroConditionVideoEdit( QWidget::connect(_browseButton, SIGNAL(clicked()), this, SLOT(BrowseButtonClicked())); - AdvSceneSwitcher::populateVideoSelection(_videoSelection, false); + populateVideoSelection(_videoSelection); populateConditionSelection(_condition); QHBoxLayout *mainLayout = new QHBoxLayout; diff --git a/src/macro-condition-window.cpp b/src/macro-condition-window.cpp index 40751b95..3a4d2407 100644 --- a/src/macro-condition-window.cpp +++ b/src/macro-condition-window.cpp @@ -115,7 +115,7 @@ MacroConditionWindowEdit::MacroConditionWindowEdit( QWidget::connect(_focused, SIGNAL(stateChanged(int)), this, SLOT(FocusChanged(int))); - AdvSceneSwitcher::populateWindowSelection(_windowSelection); + populateWindowSelection(_windowSelection); std::unordered_map widgetPlaceholders = { {"{{windows}}", _windowSelection}, diff --git a/src/macro-tab.cpp b/src/macro-tab.cpp index 4dc2ce58..ef2d69e4 100644 --- a/src/macro-tab.cpp +++ b/src/macro-tab.cpp @@ -263,7 +263,9 @@ void AdvSceneSwitcher::setupMacroTab() } if (switcher->macros.size() == 0) { - addPulse = PulseWidget(ui->macroAdd, QColor(Qt::green)); + if (!switcher->disableHints) { + addPulse = PulseWidget(ui->macroAdd, QColor(Qt::green)); + } ui->macroHelp->setVisible(true); } else { ui->macroHelp->setVisible(false); diff --git a/src/scene-group.cpp b/src/scene-group.cpp index b1c3cb9b..fe18da9d 100644 --- a/src/scene-group.cpp +++ b/src/scene-group.cpp @@ -499,7 +499,10 @@ void AdvSceneSwitcher::setupSceneGroupTab() } if (switcher->sceneGroups.size() == 0) { - addPulse = PulseWidget(ui->sceneGroupAdd, QColor(Qt::green)); + if (!switcher->disableHints) { + addPulse = PulseWidget(ui->sceneGroupAdd, + QColor(Qt::green)); + } ui->sceneGroupHelp->setVisible(true); } else { ui->sceneGroupHelp->setVisible(false); diff --git a/src/scene-trigger.cpp b/src/scene-trigger.cpp index 055d373b..60a434de 100644 --- a/src/scene-trigger.cpp +++ b/src/scene-trigger.cpp @@ -347,7 +347,10 @@ void AdvSceneSwitcher::setupTriggerTab() } if (switcher->sceneTriggers.size() == 0) { - addPulse = PulseWidget(ui->triggerAdd, QColor(Qt::green)); + if (!switcher->disableHints) { + addPulse = + PulseWidget(ui->triggerAdd, QColor(Qt::green)); + } ui->triggerHelp->setVisible(true); } else { ui->triggerHelp->setVisible(false); @@ -381,7 +384,7 @@ void SceneTrigger::load(obs_data_t *obj) static inline void populateTriggers(QComboBox *list) { - AdvSceneSwitcher::addSelectionEntry( + addSelectionEntry( list, obs_module_text( "AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none")); @@ -396,7 +399,7 @@ static inline void populateTriggers(QComboBox *list) inline void populateActions(QComboBox *list) { - AdvSceneSwitcher::addSelectionEntry( + addSelectionEntry( list, obs_module_text( "AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none")); @@ -451,7 +454,7 @@ SceneTriggerWidget::SceneTriggerWidget(QWidget *parent, SceneTrigger *s) populateTriggers(triggers); populateActions(actions); - AdvSceneSwitcher::populateAudioSelection(audioSources); + populateAudioSelection(audioSources); if (s) { triggers->setCurrentIndex(static_cast(s->triggerType)); diff --git a/src/switch-audio.cpp b/src/switch-audio.cpp index 03ff4197..0473346d 100644 --- a/src/switch-audio.cpp +++ b/src/switch-audio.cpp @@ -224,7 +224,9 @@ void AdvSceneSwitcher::setupAudioTab() } if (switcher->audioSwitches.size() == 0) { - addPulse = PulseWidget(ui->audioAdd, QColor(Qt::green)); + if (!switcher->disableHints) { + addPulse = PulseWidget(ui->audioAdd, QColor(Qt::green)); + } ui->audioHelp->setVisible(true); } else { ui->audioHelp->setVisible(false); @@ -447,7 +449,7 @@ AudioSwitchWidget::AudioSwitchWidget(QWidget *parent, AudioSwitch *s) QWidget::connect(ignoreInactiveSource, SIGNAL(stateChanged(int)), this, SLOT(IgnoreInactiveChanged(int))); - AdvSceneSwitcher::populateAudioSelection(audioSources); + populateAudioSelection(audioSources); populateConditionSelection(condition); if (s) { diff --git a/src/switch-executable.cpp b/src/switch-executable.cpp index 04073ff7..42138f09 100644 --- a/src/switch-executable.cpp +++ b/src/switch-executable.cpp @@ -187,7 +187,10 @@ void AdvSceneSwitcher::setupExecutableTab() } if (switcher->executableSwitches.size() == 0) { - addPulse = PulseWidget(ui->executableAdd, QColor(Qt::green)); + if (!switcher->disableHints) { + addPulse = PulseWidget(ui->executableAdd, + QColor(Qt::green)); + } ui->exeHelp->setVisible(true); } else { ui->exeHelp->setVisible(false); @@ -223,7 +226,7 @@ ExecutableSwitchWidget::ExecutableSwitchWidget(QWidget *parent, QWidget::connect(requiresFocus, SIGNAL(stateChanged(int)), this, SLOT(FocusChanged(int))); - AdvSceneSwitcher::populateProcessSelection(processes); + populateProcessSelection(processes); processes->setEditable(true); processes->setMaxVisibleItems(20); diff --git a/src/switch-file.cpp b/src/switch-file.cpp index f144f3b7..f963e79d 100644 --- a/src/switch-file.cpp +++ b/src/switch-file.cpp @@ -415,7 +415,9 @@ void AdvSceneSwitcher::setupFileTab() } if (switcher->fileSwitches.size() == 0) { - addPulse = PulseWidget(ui->fileAdd, QColor(Qt::green)); + if (!switcher->disableHints) { + addPulse = PulseWidget(ui->fileAdd, QColor(Qt::green)); + } ui->fileHelp->setVisible(true); } else { ui->fileHelp->setVisible(false); diff --git a/src/switch-generic.cpp b/src/switch-generic.cpp index f8cb8c5e..ef4863b5 100644 --- a/src/switch-generic.cpp +++ b/src/switch-generic.cpp @@ -228,10 +228,9 @@ SwitchWidget::SwitchWidget(QWidget *parent, SceneSwitcherEntry *s, SIGNAL(SceneGroupRenamed(const QString &, const QString &)), this, SLOT(SceneGroupRename(const QString &, const QString &))); - AdvSceneSwitcher::populateSceneSelection(scenes, usePreviousScene, - addSceneGroup); - AdvSceneSwitcher::populateTransitionSelection(transitions, - addCurrentTransition); + populateSceneSelection(scenes, usePreviousScene, addSceneGroup, + &switcher->sceneGroups); + populateTransitionSelection(transitions, addCurrentTransition); switchData = s; showSwitchData(); diff --git a/src/switch-media.cpp b/src/switch-media.cpp index c83c1627..4849ec1b 100644 --- a/src/switch-media.cpp +++ b/src/switch-media.cpp @@ -244,7 +244,9 @@ void AdvSceneSwitcher::setupMediaTab() } if (switcher->mediaSwitches.size() == 0) { - addPulse = PulseWidget(ui->mediaAdd, QColor(Qt::green)); + if (!switcher->disableHints) { + addPulse = PulseWidget(ui->mediaAdd, QColor(Qt::green)); + } ui->mediaHelp->setVisible(true); } else { ui->mediaHelp->setVisible(false); @@ -458,7 +460,7 @@ MediaSwitchWidget::MediaSwitchWidget(QWidget *parent, MediaSwitch *s) QWidget::connect(time, SIGNAL(valueChanged(int)), this, SLOT(TimeChanged(int))); - AdvSceneSwitcher::populateMediaSelection(mediaSources); + populateMediaSelection(mediaSources); populateMediaStates(states); populateTimeRestrictions(timeRestrictions); diff --git a/src/switch-pause.cpp b/src/switch-pause.cpp index 0a7570cb..3a4511eb 100644 --- a/src/switch-pause.cpp +++ b/src/switch-pause.cpp @@ -264,7 +264,9 @@ void AdvSceneSwitcher::setupPauseTab() } if (switcher->pauseEntries.size() == 0) { - addPulse = PulseWidget(ui->pauseAdd, QColor(Qt::green)); + if (!switcher->disableHints) { + addPulse = PulseWidget(ui->pauseAdd, QColor(Qt::green)); + } ui->pauseHelp->setVisible(true); } else { ui->pauseHelp->setVisible(false); @@ -315,7 +317,7 @@ PauseEntryWidget::PauseEntryWidget(QWidget *parent, PauseEntry *s) populatePauseTypes(pauseTypes); populatePauseTargets(pauseTargets); - AdvSceneSwitcher::populateWindowSelection(windows); + populateWindowSelection(windows); windows->setEditable(true); windows->setMaxVisibleItems(20); diff --git a/src/switch-random.cpp b/src/switch-random.cpp index 920613c7..b45f1790 100644 --- a/src/switch-random.cpp +++ b/src/switch-random.cpp @@ -125,15 +125,20 @@ void AdvSceneSwitcher::setupRandomTab() } if (switcher->randomSwitches.size() == 0) { - addPulse = PulseWidget(ui->randomAdd, QColor(Qt::green)); + if (!switcher->disableHints) { + addPulse = + PulseWidget(ui->randomAdd, QColor(Qt::green)); + } ui->randomHelp->setVisible(true); } else { ui->randomHelp->setVisible(false); } if (switcher->switchIfNotMatching != RANDOM_SWITCH) { - PulseWidget(ui->randomDisabledWarning, QColor(Qt::red), - QColor(0, 0, 0, 0), "QLabel "); + if (!switcher->disableHints) { + PulseWidget(ui->randomDisabledWarning, QColor(Qt::red), + QColor(0, 0, 0, 0), "QLabel "); + } } else { ui->randomDisabledWarning->setVisible(false); } diff --git a/src/switch-screen-region.cpp b/src/switch-screen-region.cpp index 7d140f68..99d4874c 100644 --- a/src/switch-screen-region.cpp +++ b/src/switch-screen-region.cpp @@ -245,7 +245,10 @@ void AdvSceneSwitcher::setupRegionTab() } if (switcher->screenRegionSwitches.size() == 0) { - addPulse = PulseWidget(ui->screenRegionAdd, QColor(Qt::green)); + if (!switcher->disableHints) { + addPulse = PulseWidget(ui->screenRegionAdd, + QColor(Qt::green)); + } ui->regionHelp->setVisible(true); } else { ui->regionHelp->setVisible(false); @@ -320,8 +323,8 @@ ScreenRegionWidget::ScreenRegionWidget(QWidget *parent, ScreenRegionSwitch *s) QWidget::connect(maxY, SIGNAL(valueChanged(int)), this, SLOT(MaxYChanged(int))); - AdvSceneSwitcher::populateSceneSelection( - excludeScenes, false, false, true, + populateSceneSelection( + excludeScenes, false, false, nullptr, true, obs_module_text( "AdvSceneSwitcher.screenRegionTab.excludeScenes.None"), true); diff --git a/src/switch-sequence.cpp b/src/switch-sequence.cpp index fb5cfda4..a9889845 100644 --- a/src/switch-sequence.cpp +++ b/src/switch-sequence.cpp @@ -289,7 +289,10 @@ void AdvSceneSwitcher::setupSequenceTab() } if (switcher->sceneSequenceSwitches.size() == 0) { - addPulse = PulseWidget(ui->sceneSequenceAdd, QColor(Qt::green)); + if (!switcher->disableHints) { + addPulse = PulseWidget(ui->sceneSequenceAdd, + QColor(Qt::green)); + } ui->sequenceHelp->setVisible(true); } else { ui->sequenceHelp->setVisible(false); @@ -586,7 +589,7 @@ SequenceWidget::SequenceWidget(QWidget *parent, SceneSequenceSwitch *s, QWidget::connect(reduce, SIGNAL(clicked()), this, SLOT(ReduceClicked())); - AdvSceneSwitcher::populateSceneSelection(startScenes, false); + populateSceneSelection(startScenes); interruptible->setToolTip(obs_module_text( "AdvSceneSwitcher.sceneSequenceTab.interruptibleHint")); diff --git a/src/switch-time.cpp b/src/switch-time.cpp index 748aa951..1e643ff7 100644 --- a/src/switch-time.cpp +++ b/src/switch-time.cpp @@ -191,7 +191,9 @@ void AdvSceneSwitcher::setupTimeTab() } if (switcher->timeSwitches.size() == 0) { - addPulse = PulseWidget(ui->timeAdd, QColor(Qt::green)); + if (!switcher->disableHints) { + addPulse = PulseWidget(ui->timeAdd, QColor(Qt::green)); + } ui->timeHelp->setVisible(true); } else { ui->timeHelp->setVisible(false); diff --git a/src/switch-transitions.cpp b/src/switch-transitions.cpp index 221b8ca8..05aed606 100644 --- a/src/switch-transitions.cpp +++ b/src/switch-transitions.cpp @@ -495,7 +495,7 @@ TransitionSwitchWidget::TransitionSwitchWidget(QWidget *parent, QWidget::connect(duration, SIGNAL(valueChanged(double)), this, SLOT(DurationChanged(double))); - AdvSceneSwitcher::populateSceneSelection(scenes2, false); + populateSceneSelection(scenes2); if (s) { scenes2->setCurrentText(GetWeakSourceName(s->scene2).c_str()); diff --git a/src/switch-video.cpp b/src/switch-video.cpp index 95ef3041..8ec1cd15 100644 --- a/src/switch-video.cpp +++ b/src/switch-video.cpp @@ -194,7 +194,9 @@ void AdvSceneSwitcher::setupVideoTab() } if (switcher->videoSwitches.size() == 0) { - addPulse = PulseWidget(ui->videoAdd, QColor(Qt::green)); + if (!switcher->disableHints) { + addPulse = PulseWidget(ui->videoAdd, QColor(Qt::green)); + } ui->videoHelp->setVisible(true); } else { ui->videoHelp->setVisible(false); @@ -399,10 +401,7 @@ VideoSwitchWidget::VideoSwitchWidget(QWidget *parent, VideoSwitch *s) QWidget::connect(ignoreInactiveSource, SIGNAL(stateChanged(int)), this, SLOT(IgnoreInactiveChanged(int))); - // TODO: - // Figure out why scene do not work for "match exactly". - // Until then do not allow selecting scenes - AdvSceneSwitcher::populateVideoSelection(videoSources, false); + populateVideoSelection(videoSources); populateConditionSelection(condition); if (s) { diff --git a/src/switch-window.cpp b/src/switch-window.cpp index a9ee073c..f9455382 100644 --- a/src/switch-window.cpp +++ b/src/switch-window.cpp @@ -348,7 +348,10 @@ void AdvSceneSwitcher::setupTitleTab() } if (switcher->windowSwitches.size() == 0) { - addPulse = PulseWidget(ui->windowAdd, QColor(Qt::green)); + if (!switcher->disableHints) { + addPulse = + PulseWidget(ui->windowAdd, QColor(Qt::green)); + } ui->windowHelp->setVisible(true); } else { ui->windowHelp->setVisible(false); @@ -418,7 +421,7 @@ WindowSwitchWidget::WindowSwitchWidget(QWidget *parent, WindowSwitch *s) QWidget::connect(focused, SIGNAL(stateChanged(int)), this, SLOT(FocusChanged(int))); - AdvSceneSwitcher::populateWindowSelection(windows); + populateWindowSelection(windows); windows->setEditable(true); windows->setMaxVisibleItems(20); diff --git a/src/utility.cpp b/src/utility.cpp new file mode 100644 index 00000000..413571d0 --- /dev/null +++ b/src/utility.cpp @@ -0,0 +1,555 @@ +#pragma once +#include "headers/utility.hpp" +#include "headers/platform-funcs.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool WeakSourceValid(obs_weak_source_t *ws) +{ + obs_source_t *source = obs_weak_source_get_source(ws); + if (source) { + obs_source_release(source); + } + return !!source; +} + +std::string GetWeakSourceName(obs_weak_source_t *weak_source) +{ + std::string name; + + obs_source_t *source = obs_weak_source_get_source(weak_source); + if (source) { + name = obs_source_get_name(source); + obs_source_release(source); + } + + return name; +} + +OBSWeakSource GetWeakSourceByName(const char *name) +{ + OBSWeakSource weak; + obs_source_t *source = obs_get_source_by_name(name); + if (source) { + weak = obs_source_get_weak_source(source); + obs_weak_source_release(weak); + obs_source_release(source); + } + + return weak; +} + +OBSWeakSource GetWeakSourceByQString(const QString &name) +{ + return GetWeakSourceByName(name.toUtf8().constData()); +} + +OBSWeakSource GetWeakTransitionByName(const char *transitionName) +{ + OBSWeakSource weak; + obs_source_t *source = nullptr; + + if (strcmp(transitionName, "Default") == 0) { + source = obs_frontend_get_current_transition(); + weak = obs_source_get_weak_source(source); + obs_source_release(source); + obs_weak_source_release(weak); + return weak; + } + + obs_frontend_source_list *transitions = new obs_frontend_source_list(); + obs_frontend_get_transitions(transitions); + bool match = false; + + for (size_t i = 0; i < transitions->sources.num; i++) { + const char *name = + obs_source_get_name(transitions->sources.array[i]); + if (strcmp(transitionName, name) == 0) { + match = true; + source = transitions->sources.array[i]; + break; + } + } + + if (match) { + weak = obs_source_get_weak_source(source); + obs_weak_source_release(weak); + } + obs_frontend_source_list_free(transitions); + + return weak; +} + +OBSWeakSource GetWeakTransitionByQString(const QString &name) +{ + return GetWeakTransitionByName(name.toUtf8().constData()); +} + +OBSWeakSource GetWeakFilterByName(OBSWeakSource source, const char *name) +{ + OBSWeakSource weak; + auto s = obs_weak_source_get_source(source); + if (s) { + auto filterSource = obs_source_get_filter_by_name(s, name); + weak = obs_source_get_weak_source(filterSource); + obs_weak_source_release(weak); + obs_source_release(filterSource); + obs_source_release(s); + } + return weak; +} + +OBSWeakSource GetWeakFilterByQString(OBSWeakSource source, const QString &name) +{ + return GetWeakFilterByName(source, name.toUtf8().constData()); +} + +std::string +getNextDelim(const std::string &text, + std::unordered_map placeholders) +{ + size_t pos = std::string::npos; + std::string res = ""; + + for (const auto &ph : placeholders) { + size_t newPos = text.find(ph.first); + if (newPos <= pos) { + pos = newPos; + res = ph.first; + } + } + + if (pos == std::string::npos) { + return ""; + } + + return res; +} + +void placeWidgets(std::string text, QBoxLayout *layout, + std::unordered_map placeholders, + bool addStretch) +{ + std::vector> labelsWidgetsPairs; + + std::string delim = getNextDelim(text, placeholders); + while (delim != "") { + size_t pos = text.find(delim); + if (pos != std::string::npos) { + labelsWidgetsPairs.emplace_back(text.substr(0, pos), + placeholders[delim]); + text.erase(0, pos + delim.length()); + } + delim = getNextDelim(text, placeholders); + } + + if (text != "") { + labelsWidgetsPairs.emplace_back(text, nullptr); + } + + for (auto &lw : labelsWidgetsPairs) { + if (lw.first != "") { + layout->addWidget(new QLabel(lw.first.c_str())); + } + if (lw.second) { + layout->addWidget(lw.second); + } + } + if (addStretch) { + layout->addStretch(); + } +} + +void clearLayout(QLayout *layout) +{ + QLayoutItem *item; + while ((item = layout->takeAt(0))) { + if (item->layout()) { + clearLayout(item->layout()); + delete item->layout(); + } + if (item->widget()) { + delete item->widget(); + } + delete item; + } +} + +bool compareIgnoringLineEnding(QString &s1, QString &s2) +{ + // Let QT deal with different types of lineendings + QTextStream s1stream(&s1); + QTextStream s2stream(&s2); + + while (!s1stream.atEnd() || !s2stream.atEnd()) { + QString s1s = s1stream.readLine(); + QString s2s = s2stream.readLine(); + if (s1s != s2s) { + return false; + } + } + + if (!s1stream.atEnd() && !s2stream.atEnd()) { + return false; + } + + return true; +} + +bool DisplayMessage(const QString &msg, bool question) +{ + if (question) { + QMessageBox::StandardButton reply; + reply = QMessageBox::question( + nullptr, "Advanced Scene Switcher", msg, + QMessageBox::Yes | QMessageBox::No); + if (reply == QMessageBox::Yes) { + return true; + } else { + return false; + } + } else { + QMessageBox Msgbox; + Msgbox.setWindowTitle("Advanced Scene Switcher"); + Msgbox.setText(msg); + Msgbox.exec(); + } + + return false; +} + +void addSelectionEntry(QComboBox *sel, const char *description, bool selectable, + const char *tooltip) +{ + sel->addItem(description); + + if (strcmp(tooltip, "") != 0) { + sel->setItemData(0, tooltip, Qt::ToolTipRole); + } + + QStandardItemModel *model = + qobject_cast(sel->model()); + QModelIndex firstIndex = + model->index(0, sel->modelColumn(), sel->rootModelIndex()); + QStandardItem *firstItem = model->itemFromIndex(firstIndex); + if (!selectable) { + firstItem->setSelectable(false); + firstItem->setEnabled(false); + } +} + +void populateSourceSelection(QComboBox *list, bool addSelect) +{ + auto enumSourcesWithSources = [](void *param, obs_source_t *source) { + if (!source) { + return true; + } + QComboBox *list = reinterpret_cast(param); + list->addItem(obs_source_get_name(source)); + return true; + }; + + list->clear(); + if (addSelect) { + addSelectionEntry( + list, obs_module_text("AdvSceneSwitcher.selectSource"), + false); + } + + obs_enum_sources(enumSourcesWithSources, list); +} + +void populateTransitionSelection(QComboBox *sel, bool addCurrent, + bool addSelect, bool selectable) +{ + if (addSelect) { + addSelectionEntry( + sel, + obs_module_text("AdvSceneSwitcher.selectTransition"), + selectable); + } + + if (addCurrent) { + sel->addItem( + obs_module_text("AdvSceneSwitcher.currentTransition")); + } + + obs_frontend_source_list *transitions = new obs_frontend_source_list(); + obs_frontend_get_transitions(transitions); + + for (size_t i = 0; i < transitions->sources.num; i++) { + const char *name = + obs_source_get_name(transitions->sources.array[i]); + sel->addItem(name); + } + + obs_frontend_source_list_free(transitions); +} + +void populateWindowSelection(QComboBox *sel, bool addSelect) +{ + if (addSelect) { + addSelectionEntry( + sel, obs_module_text("AdvSceneSwitcher.selectWindow")); + } + + std::vector windows; + GetWindowList(windows); + sort(windows.begin(), windows.end()); + + for (std::string &window : windows) { + sel->addItem(window.c_str()); + } + +#ifdef WIN32 + sel->setItemData(0, obs_module_text("AdvSceneSwitcher.selectWindowTip"), + Qt::ToolTipRole); +#endif +} + +void populateAudioSelection(QComboBox *sel, bool addSelect) +{ + if (addSelect) { + addSelectionEntry( + sel, + obs_module_text("AdvSceneSwitcher.selectAudioSource"), + false, + obs_module_text( + "AdvSceneSwitcher.invaildEntriesWillNotBeSaved")); + } + + auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */ + { + std::vector *list = + reinterpret_cast *>(data); + uint32_t flags = obs_source_get_output_flags(source); + + if ((flags & OBS_SOURCE_AUDIO) != 0) { + list->push_back(obs_source_get_name(source)); + } + return true; + }; + + std::vector audioSources; + obs_enum_sources(sourceEnum, &audioSources); + sort(audioSources.begin(), audioSources.end()); + for (std::string &source : audioSources) { + sel->addItem(source.c_str()); + } +} + +void populateVideoSelection(QComboBox *sel, bool addSelect) +{ + if (addSelect) { + addSelectionEntry( + sel, + obs_module_text("AdvSceneSwitcher.selectVideoSource"), + false, + obs_module_text( + "AdvSceneSwitcher.invaildEntriesWillNotBeSaved")); + } + + auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */ + { + std::vector *list = + reinterpret_cast *>(data); + uint32_t flags = obs_source_get_output_flags(source); + std::string test = obs_source_get_name(source); + if ((flags & (OBS_SOURCE_VIDEO | OBS_SOURCE_ASYNC)) != 0) { + list->push_back(obs_source_get_name(source)); + } + return true; + }; + + std::vector videoSources; + obs_enum_sources(sourceEnum, &videoSources); + sort(videoSources.begin(), videoSources.end()); + for (std::string &source : videoSources) { + sel->addItem(source.c_str()); + } +} + +void populateMediaSelection(QComboBox *sel, bool addSelect) +{ + if (addSelect) { + addSelectionEntry( + sel, + obs_module_text("AdvSceneSwitcher.selectMediaSource"), + false, + obs_module_text( + "AdvSceneSwitcher.invaildEntriesWillNotBeSaved")); + } + + auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */ + { + std::vector *list = + reinterpret_cast *>(data); + std::string sourceId = obs_source_get_id(source); + if (sourceId.compare("ffmpeg_source") == 0 || + sourceId.compare("vlc_source") == 0) { + list->push_back(obs_source_get_name(source)); + } + return true; + }; + + std::vector mediaSources; + obs_enum_sources(sourceEnum, &mediaSources); + sort(mediaSources.begin(), mediaSources.end()); + for (std::string &source : mediaSources) { + sel->addItem(source.c_str()); + } +} + +void populateProcessSelection(QComboBox *sel, bool addSelect) +{ + if (addSelect) { + addSelectionEntry( + sel, obs_module_text("AdvSceneSwitcher.selectProcess")); + } + + QStringList processes; + GetProcessList(processes); + processes.sort(); + for (QString &process : processes) + sel->addItem(process); +} + +void populateSceneSelection(QComboBox *sel, bool addPrevious, + bool addSceneGroup, + std::deque *sceneGroups, bool addSelect, + std::string selectText, bool selectable) +{ + if (addSelect) { + if (selectText.empty()) { + addSelectionEntry( + sel, + obs_module_text("AdvSceneSwitcher.selectScene"), + selectable, + obs_module_text( + "AdvSceneSwitcher.invaildEntriesWillNotBeSaved")); + } else { + addSelectionEntry(sel, selectText.c_str(), selectable); + } + } + + BPtr scenes = obs_frontend_get_scene_names(); + char **temp = scenes; + while (*temp) { + const char *name = *temp; + sel->addItem(name); + temp++; + } + + if (addPrevious) { + sel->addItem(obs_module_text( + "AdvSceneSwitcher.selectPreviousScene")); + } + + if (addSceneGroup && sceneGroups) { + for (auto &sg : *sceneGroups) { + sel->addItem(QString::fromStdString(sg.name)); + } + } +} + +QMetaObject::Connection PulseWidget(QWidget *widget, QColor endColor, + QColor startColor, QString specifier) +{ + widget->setStyleSheet(specifier + "{ \ + border-style: outset; \ + border-width: 2px; \ + border-radius: 10px; \ + border-color: rgb(0,0,0,0) \ + }"); + + QGraphicsColorizeEffect *eEffect = new QGraphicsColorizeEffect(widget); + widget->setGraphicsEffect(eEffect); + QPropertyAnimation *paAnimation = + new QPropertyAnimation(eEffect, "color"); + paAnimation->setStartValue(startColor); + paAnimation->setEndValue(endColor); + paAnimation->setDuration(1000); + // Play backwards to return to original state on timer end + paAnimation->setDirection(QAbstractAnimation::Backward); + + auto con = QWidget::connect( + paAnimation, &QPropertyAnimation::finished, [paAnimation]() { + QTimer::singleShot(1000, [paAnimation] { + paAnimation->start(); + }); + }); + + paAnimation->start(); + + return con; +} + +void listAddClicked(QListWidget *list, QWidget *newWidget, + QPushButton *addButton, + QMetaObject::Connection *addHighlight) +{ + if (!list || !newWidget) { + blog(LOG_WARNING, + "listAddClicked called without valid list or widget"); + return; + } + + if (addButton && addHighlight) { + addButton->disconnect(*addHighlight); + } + + QListWidgetItem *item; + item = new QListWidgetItem(list); + list->addItem(item); + item->setSizeHint(newWidget->minimumSizeHint()); + list->setItemWidget(item, newWidget); + + list->scrollToItem(item); +} + +bool listMoveUp(QListWidget *list) +{ + int index = list->currentRow(); + if (index == -1 || index == 0) { + return false; + } + + QWidget *row = list->itemWidget(list->currentItem()); + QListWidgetItem *itemN = list->currentItem()->clone(); + + list->insertItem(index - 1, itemN); + list->setItemWidget(itemN, row); + + list->takeItem(index + 1); + list->setCurrentRow(index - 1); + return true; +} + +bool listMoveDown(QListWidget *list) +{ + int index = list->currentRow(); + if (index == -1 || index == list->count() - 1) { + return false; + } + + QWidget *row = list->itemWidget(list->currentItem()); + QListWidgetItem *itemN = list->currentItem()->clone(); + + list->insertItem(index + 2, itemN); + list->setItemWidget(itemN, row); + + list->takeItem(index); + list->setCurrentRow(index + 1); + return true; +}