mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-29 04:36:21 -05:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa87911b71 | ||
|
|
1b05019acc | ||
|
|
78a5a2629d | ||
|
|
634270a978 | ||
|
|
78ba22e1e4 | ||
|
|
aba5737a60 | ||
|
|
4315f7f621 | ||
|
|
53c535962f | ||
|
|
1e718b78c7 | ||
|
|
b1d2156228 |
@@ -33,6 +33,11 @@ add_library(${LIB_NAME} SHARED)
|
||||
include(cmake/common/get_git_revision_description.cmake)
|
||||
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
||||
git_describe(GIT_TAG)
|
||||
|
||||
if(${GIT_TAG} STREQUAL "GIT-NOTFOUND")
|
||||
set(GIT_TAG ${PROJECT_VERSION})
|
||||
endif()
|
||||
message(STATUS "${PROJECT_NAME} version: ${GIT_TAG}")
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/common/version.cpp.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/lib/version.cpp" @ONLY)
|
||||
|
||||
@@ -438,6 +443,9 @@ else()
|
||||
endif()
|
||||
target_include_directories(${LIB_NAME} PRIVATE "${PROC_INCLUDE_DIR}")
|
||||
target_sources(${LIB_NAME} PRIVATE lib/linux/advanced-scene-switcher-nix.cpp)
|
||||
|
||||
# Don't include irrelevant folders into sources archive
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "\\.deps/.*")
|
||||
endif()
|
||||
|
||||
if(NOT OS_WINDOWS)
|
||||
|
||||
@@ -526,7 +526,6 @@ AdvSceneSwitcher.action.screenshot.save.default="Standard"
|
||||
AdvSceneSwitcher.action.screenshot.save.custom="Benutzerdefiniert"
|
||||
AdvSceneSwitcher.action.screenshot.type.source="Quelle"
|
||||
AdvSceneSwitcher.action.screenshot.type.scene="Szene"
|
||||
AdvSceneSwitcher.action.screenshot.mainOutput="OBS's Haupt-Ausgabe"
|
||||
AdvSceneSwitcher.action.screenshot.blackscreenNote="Quellen oder Szenen, die nicht immer gerendert werden, können dazu führen, dass einige Teile der Screenshots leer bleiben."
|
||||
AdvSceneSwitcher.action.screenshot.entry="Screenshot{{targetType}}{{sources}}{{scenes}}und speichere in{{saveType}}{{variables}}Pfad"
|
||||
AdvSceneSwitcher.action.profile="Profil"
|
||||
|
||||
@@ -1022,7 +1022,6 @@ AdvSceneSwitcher.action.screenshot.save.custom="Custom file path"
|
||||
AdvSceneSwitcher.action.screenshot.save.variable="Variable (base64 encoded PNG)"
|
||||
AdvSceneSwitcher.action.screenshot.type.source="Source"
|
||||
AdvSceneSwitcher.action.screenshot.type.scene="Scene"
|
||||
AdvSceneSwitcher.action.screenshot.mainOutput="OBS's main output"
|
||||
AdvSceneSwitcher.action.screenshot.blackscreenNote="Sources or scenes, which are not always rendered, may result in some parts of screenshots to remain blank."
|
||||
AdvSceneSwitcher.action.screenshot.entry="Screenshot{{targetType}}{{sources}}{{scenes}}and save to{{saveType}}{{variables}}"
|
||||
AdvSceneSwitcher.action.profile="Profile"
|
||||
@@ -1051,11 +1050,25 @@ AdvSceneSwitcher.action.websocket.entry.sceneSwitcher.request="Send{{api}}of typ
|
||||
AdvSceneSwitcher.action.websocket.entry.sceneSwitcher.event="Send{{api}}of type{{type}}to connected clients"
|
||||
AdvSceneSwitcher.action.websocket.entry.generic="Send{{api}}via{{connection}}"
|
||||
AdvSceneSwitcher.action.http="HTTP"
|
||||
AdvSceneSwitcher.action.http.legacy="HTTP (legacy)"
|
||||
AdvSceneSwitcher.action.http.setHeaders="Set headers"
|
||||
AdvSceneSwitcher.action.http.headers="Headers:"
|
||||
AdvSceneSwitcher.action.http.addHeader="Add header"
|
||||
AdvSceneSwitcher.action.http.addHeader.name="Header name"
|
||||
AdvSceneSwitcher.action.http.addHeader.value="Header value"
|
||||
AdvSceneSwitcher.action.http.setParams="Set parameters"
|
||||
AdvSceneSwitcher.action.http.params="Parameters:"
|
||||
AdvSceneSwitcher.action.http.addParam.name="Parameter name"
|
||||
AdvSceneSwitcher.action.http.addParam.value="Parameter value"
|
||||
AdvSceneSwitcher.action.http.body="Message body:"
|
||||
AdvSceneSwitcher.action.http.type.get="GET"
|
||||
AdvSceneSwitcher.action.http.type.post="POST"
|
||||
AdvSceneSwitcher.action.http.type.put="PUT"
|
||||
AdvSceneSwitcher.action.http.type.patch="PATCH"
|
||||
AdvSceneSwitcher.action.http.type.delete="DELETE"
|
||||
AdvSceneSwitcher.action.http.layout.method="Send{{method}}to URL{{url}}at path{{path}}"
|
||||
AdvSceneSwitcher.action.http.layout.contentType="Content type:{{contentType}}"
|
||||
AdvSceneSwitcher.action.http.layout.timeout="Timeout:{{timeout}}seconds"
|
||||
AdvSceneSwitcher.action.http.entry.line1="Send{{method}}to{{url}}"
|
||||
AdvSceneSwitcher.action.http.entry.line2="Timeout:{{timeout}}seconds"
|
||||
AdvSceneSwitcher.action.variable="Variable"
|
||||
@@ -2041,6 +2054,11 @@ AdvSceneSwitcher.tempVar.gameCapture.class.description="Window class of the appl
|
||||
AdvSceneSwitcher.tempVar.gameCapture.executable="Executable"
|
||||
AdvSceneSwitcher.tempVar.gameCapture.executable.description="Executable name of the application captured by the source."
|
||||
|
||||
AdvSceneSwitcher.tempVar.http.status="Status code"
|
||||
AdvSceneSwitcher.tempVar.http.body="Message body"
|
||||
AdvSceneSwitcher.tempVar.http.error="Error"
|
||||
AdvSceneSwitcher.tempVar.http.error.description="Empty when no error occurred.\nOther possible values:\n\n * Could not establish connection\n * Failed to bind IP address\n * Failed to read connection\n * Failed to write connection\n * Maximum redirect count exceeded\n * Connection handling canceled\n * SSL connection failed\n * SSL certificate loading failed\n * SSL server verification failed\n * Unsupported HTTP multipart boundary characters\n * Compression failed\n * Connection timed out\n * Proxy connection failed\n * Unknown"
|
||||
|
||||
AdvSceneSwitcher.selectScene="--select scene--"
|
||||
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
||||
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
||||
@@ -2079,7 +2097,6 @@ AdvSceneSwitcher.settings.suffix.type.list=" (List)"
|
||||
AdvSceneSwitcher.settings.suffix.type.color=" (Color)"
|
||||
AdvSceneSwitcher.settings.suffix.type.button=" (Button)"
|
||||
AdvSceneSwitcher.settings.suffix.type.font=" (Font)"
|
||||
AdvSceneSwitcher.settings.suffix.type.font=" (Font)"
|
||||
AdvSceneSwitcher.settings.suffix.type.editableList=" (Editable list)"
|
||||
AdvSceneSwitcher.settings.suffix.type.frameRate=" (Frame rate)"
|
||||
AdvSceneSwitcher.settings.suffix.type.group=" (Group)"
|
||||
|
||||
@@ -438,7 +438,6 @@ AdvSceneSwitcher.action.random="Aleatorio"
|
||||
AdvSceneSwitcher.action.random.entry="Ejecute aleatoriamente cualquiera de las siguientes macros (las macros en pausa se ignoran)"
|
||||
AdvSceneSwitcher.action.systray="Notificación de la bandeja del sistema"
|
||||
AdvSceneSwitcher.action.screenshot="Captura de pantalla"
|
||||
AdvSceneSwitcher.action.screenshot.mainOutput="Salida principal de OBS"
|
||||
AdvSceneSwitcher.action.profile="Perfil"
|
||||
AdvSceneSwitcher.action.profile.entry="Cambiar perfil activo a {{profiles}}"
|
||||
AdvSceneSwitcher.action.sceneCollection="Colección de escenas"
|
||||
|
||||
@@ -647,7 +647,6 @@ AdvSceneSwitcher.action.screenshot.save.default="Par défaut"
|
||||
AdvSceneSwitcher.action.screenshot.save.custom="Personnalisé"
|
||||
AdvSceneSwitcher.action.screenshot.type.source="Source"
|
||||
AdvSceneSwitcher.action.screenshot.type.scene="Scène"
|
||||
AdvSceneSwitcher.action.screenshot.mainOutput="Sortie principale d'OBS"
|
||||
AdvSceneSwitcher.action.screenshot.blackscreenNote="Les sources ou les scènes qui ne sont pas toujours rendues peuvent entraîner des parties de captures d'écran vides."
|
||||
AdvSceneSwitcher.action.screenshot.entry="Capturer{{targetType}}{{sources}}{{scenes}}et enregistrer à l'emplacement{{saveType}}{{variables}}"
|
||||
AdvSceneSwitcher.action.profile="Profil"
|
||||
|
||||
@@ -979,7 +979,6 @@ AdvSceneSwitcher.action.screenshot.save.default="デフォルト"
|
||||
AdvSceneSwitcher.action.screenshot.save.custom="カスタム"
|
||||
; AdvSceneSwitcher.action.screenshot.type.source="Source"
|
||||
AdvSceneSwitcher.action.screenshot.type.scene="シーン"
|
||||
AdvSceneSwitcher.action.screenshot.mainOutput="OBSの主な出力"
|
||||
AdvSceneSwitcher.action.screenshot.blackscreenNote="常にレンダリングされるわけではないソースやシーンにより、スクリーンショットの一部が空白のままになる場合があります。"
|
||||
AdvSceneSwitcher.action.screenshot.entry="スクリーンショット{{targetType}}{{sources}}{{scenes}}を作成し、{{saveType}}{{variables}}の場所に保存します"
|
||||
AdvSceneSwitcher.action.profile="プロファイル"
|
||||
|
||||
@@ -960,7 +960,6 @@ AdvSceneSwitcher.action.screenshot.save.default="Padrão"
|
||||
AdvSceneSwitcher.action.screenshot.save.custom="Personalizado"
|
||||
AdvSceneSwitcher.action.screenshot.type.source="Fonte"
|
||||
AdvSceneSwitcher.action.screenshot.type.scene="Cena"
|
||||
AdvSceneSwitcher.action.screenshot.mainOutput="Saída principal do OBS"
|
||||
AdvSceneSwitcher.action.screenshot.blackscreenNote="Fontes ou cenas, que nem sempre são renderizadas, podem resultar em algumas partes das capturas de tela permanecendo em branco."
|
||||
AdvSceneSwitcher.action.screenshot.entry="Captura de tela{{targetType}}{{sources}}{{scenes}}e salvar em{{saveType}}{{variables}}localização"
|
||||
AdvSceneSwitcher.action.profile="Perfil"
|
||||
|
||||
@@ -356,7 +356,6 @@ AdvSceneSwitcher.action.random="Rastgele"
|
||||
AdvSceneSwitcher.action.random.entry="Aşağıdaki makrolardan herhangi birini rastgele çalıştırın (duraklatılmış makrolar yoksayılır)"
|
||||
AdvSceneSwitcher.action.systray="Sistem tepsisi bildirimi"
|
||||
AdvSceneSwitcher.action.screenshot="Ekran görüntüsü"
|
||||
AdvSceneSwitcher.action.screenshot.mainOutput="OBS'nin ana çıkışı"
|
||||
AdvSceneSwitcher.action.profile="Profil"
|
||||
AdvSceneSwitcher.action.profile.entry="Aktif profili şununla değiştir: {{profiles}}"
|
||||
AdvSceneSwitcher.action.sceneCollection="Sahne koleksiyonu"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
2
deps/libremidi
vendored
2
deps/libremidi
vendored
Submodule deps/libremidi updated: d6d6557b5b...73e6ea40de
@@ -1,6 +1,5 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "backup.hpp"
|
||||
#include "curl-helper.hpp"
|
||||
#include "log-helper.hpp"
|
||||
#include "macro-helpers.hpp"
|
||||
#include "obs-module-helper.hpp"
|
||||
@@ -19,10 +18,15 @@
|
||||
#include <obs-frontend-api.h>
|
||||
#include <QAction>
|
||||
#include <QDirIterator>
|
||||
#include <QLibrary>
|
||||
#include <QMainWindow>
|
||||
#include <QTextStream>
|
||||
#include <regex>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
namespace advss {
|
||||
|
||||
AdvSceneSwitcher *AdvSceneSwitcher::window = nullptr;
|
||||
|
||||
@@ -17,6 +17,9 @@ static inline void populateActionSelection(QComboBox *list)
|
||||
QString entry(obs_module_text(action._name.c_str()));
|
||||
if (list->findText(entry) == -1) {
|
||||
list->addItem(entry);
|
||||
qobject_cast<QListView *>(list->view())
|
||||
->setRowHidden(list->count() - 1,
|
||||
action._hidden);
|
||||
} else {
|
||||
blog(LOG_WARNING,
|
||||
"did not insert duplicate action entry with name \"%s\"",
|
||||
|
||||
@@ -12,6 +12,7 @@ struct MacroActionInfo {
|
||||
std::function<std::shared_ptr<MacroAction>(Macro *m)> _create = nullptr;
|
||||
CreateActionWidget _createWidget = nullptr;
|
||||
std::string _name;
|
||||
bool _hidden = false;
|
||||
};
|
||||
|
||||
class MacroActionFactory {
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <QPushButton>
|
||||
#include <QHBoxLayout>
|
||||
#include <QTimer>
|
||||
#include <QListWidget>
|
||||
|
||||
namespace advss {
|
||||
|
||||
|
||||
@@ -32,7 +32,9 @@ void PreventMouseWheelAdjustWithoutFocus(QWidget *w)
|
||||
QString(w->metaObject()->className()) ==
|
||||
"advss::OSCMessageElementEdit" ||
|
||||
QString(w->metaObject()->className()) ==
|
||||
"advss::ChatMessagePropertyEdit") {
|
||||
"advss::ChatMessagePropertyEdit" ||
|
||||
QString(w->metaObject()->className()) ==
|
||||
"advss::KeyValueListContainerWidget") {
|
||||
return;
|
||||
}
|
||||
w->setFocusPolicy(Qt::StrongFocus);
|
||||
|
||||
@@ -67,6 +67,8 @@ NonModalMessageDialog::NonModalMessageDialog(const QString &message, Type type,
|
||||
}
|
||||
case Type::INPUT: {
|
||||
_inputEdit = new ResizingPlainTextEdit(this);
|
||||
_inputEdit->setTabChangesFocus(true);
|
||||
_inputEdit->setFocus();
|
||||
connect(_inputEdit, &ResizingPlainTextEdit::textChanged, this,
|
||||
&NonModalMessageDialog::InputChanged);
|
||||
layout->addWidget(_inputEdit);
|
||||
|
||||
@@ -28,6 +28,7 @@ install_advss_plugin_dependency(...)
|
||||
... to install the plugin and its dependencies.
|
||||
#]]
|
||||
|
||||
add_plugin(http)
|
||||
add_plugin(midi)
|
||||
add_plugin(openvr)
|
||||
add_plugin(stream-deck)
|
||||
|
||||
@@ -15,8 +15,8 @@ target_sources(
|
||||
macro-action-filter.hpp
|
||||
macro-action-hotkey.cpp
|
||||
macro-action-hotkey.hpp
|
||||
macro-action-http.cpp
|
||||
macro-action-http.hpp
|
||||
macro-action-http-legacy.cpp
|
||||
macro-action-http-legacy.hpp
|
||||
macro-action-log.cpp
|
||||
macro-action-log.hpp
|
||||
macro-action-media.cpp
|
||||
|
||||
@@ -449,8 +449,11 @@ void MacroActionFilterEdit::SetWidgetVisibility()
|
||||
_entryData->_action == MacroActionFilter::Action::SETTINGS &&
|
||||
_entryData->_settingsInputMethod ==
|
||||
MacroActionFilter::SettingsInputMethod::JSON_STRING);
|
||||
_getSettings->setVisible(_entryData->_action ==
|
||||
MacroActionFilter::Action::SETTINGS);
|
||||
_getSettings->setVisible(
|
||||
_entryData->_action == MacroActionFilter::Action::SETTINGS &&
|
||||
_entryData->_settingsInputMethod !=
|
||||
MacroActionFilter::SettingsInputMethod::
|
||||
INDIVIDUAL_TEMPVAR);
|
||||
_tempVars->setVisible(_entryData->_action ==
|
||||
MacroActionFilter::Action::SETTINGS &&
|
||||
_entryData->_settingsInputMethod ==
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "macro-action-http.hpp"
|
||||
#include "macro-action-http-legacy.hpp"
|
||||
#include "curl-helper.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
|
||||
@@ -9,7 +9,7 @@ const std::string MacroActionHttp::id = "http";
|
||||
bool MacroActionHttp::_registered = MacroActionFactory::Register(
|
||||
MacroActionHttp::id,
|
||||
{MacroActionHttp::Create, MacroActionHttpEdit::Create,
|
||||
"AdvSceneSwitcher.action.http"});
|
||||
"AdvSceneSwitcher.action.http.legacy", true});
|
||||
|
||||
const static std::map<MacroActionHttp::Method, std::string> methods = {
|
||||
{MacroActionHttp::Method::GET, "AdvSceneSwitcher.action.http.type.get"},
|
||||
@@ -34,11 +34,11 @@ const static std::map<PluginStateAction, std::string> actionTypes = {
|
||||
|
||||
const static std::map<NoMatchBehavior, std::string> noMatchValues = {
|
||||
{NoMatchBehavior::NO_SWITCH,
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch"},
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.dontSwitch"},
|
||||
{NoMatchBehavior::SWITCH,
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo"},
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchTo"},
|
||||
{NoMatchBehavior::RANDOM_SWITCH,
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom"},
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMatch.switchToRandom"},
|
||||
};
|
||||
|
||||
static void stopPlugin()
|
||||
|
||||
@@ -42,7 +42,7 @@ const static std::map<obs_deinterlace_mode, std::string> deinterlaceModes = {
|
||||
{OBS_DEINTERLACE_MODE_DISABLE,
|
||||
"AdvSceneSwitcher.action.source.deinterlaceMode.disable"},
|
||||
{OBS_DEINTERLACE_MODE_DISCARD,
|
||||
"AdvSceneSwitcher.action.source.deinterlaceMode.disable"},
|
||||
"AdvSceneSwitcher.action.source.deinterlaceMode.discard"},
|
||||
{OBS_DEINTERLACE_MODE_RETRO,
|
||||
"AdvSceneSwitcher.action.source.deinterlaceMode.retro"},
|
||||
{OBS_DEINTERLACE_MODE_BLEND,
|
||||
@@ -526,8 +526,11 @@ void MacroActionSourceEdit::SetWidgetVisibility()
|
||||
_entryData->_action == MacroActionSource::Action::SETTINGS &&
|
||||
_entryData->_settingsInputMethod ==
|
||||
MacroActionSource::SettingsInputMethod::JSON_STRING);
|
||||
_getSettings->setVisible(_entryData->_action ==
|
||||
MacroActionSource::Action::SETTINGS);
|
||||
_getSettings->setVisible(
|
||||
_entryData->_action == MacroActionSource::Action::SETTINGS &&
|
||||
_entryData->_settingsInputMethod !=
|
||||
MacroActionSource::SettingsInputMethod::
|
||||
INDIVIDUAL_TEMPVAR);
|
||||
_tempVars->setVisible(_entryData->_action ==
|
||||
MacroActionSource::Action::SETTINGS &&
|
||||
_entryData->_settingsInputMethod ==
|
||||
|
||||
@@ -442,6 +442,13 @@ void MacroConditionFileEdit::SetWidgetVisibility()
|
||||
_entryData->_onlyMatchIfChanged &&
|
||||
_entryData->GetCondition() ==
|
||||
MacroConditionFile::Condition::MATCH);
|
||||
|
||||
// TODO: Remove remote file support in future version in favor of HTTP
|
||||
// action.
|
||||
// Hide the option for now, if it is not used already.
|
||||
_fileTypes->setVisible(_entryData->_fileType ==
|
||||
MacroConditionFile::FileType::REMOTE);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
@@ -41,12 +41,12 @@ public:
|
||||
|
||||
StringVariable _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||
StringVariable _text = obs_module_text("AdvSceneSwitcher.enterText");
|
||||
FileType _fileType = FileType::LOCAL;
|
||||
RegexConfig _regex;
|
||||
|
||||
// TODO: Remove in future version
|
||||
bool _useTime = false;
|
||||
bool _onlyMatchIfChanged = false;
|
||||
FileType _fileType = FileType::LOCAL;
|
||||
|
||||
private:
|
||||
bool MatchFileContent(QString &filedata);
|
||||
|
||||
77
plugins/http/CMakeLists.txt
Normal file
77
plugins/http/CMakeLists.txt
Normal file
@@ -0,0 +1,77 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(advanced-scene-switcher-http)
|
||||
|
||||
# --- Check requirements ---
|
||||
|
||||
get_target_property(ADVSS_SOURCE_DIR advanced-scene-switcher-lib SOURCE_DIR)
|
||||
set(CPP_HTTPLIB_DIR "${ADVSS_SOURCE_DIR}/deps/cpp-httplib")
|
||||
if(NOT EXISTS "${CPP_HTTPLIB_DIR}/CMakeLists.txt")
|
||||
message(WARNING "cpp-httplib directory \"${CPP_HTTPLIB_DIR}\" not found!\n"
|
||||
"HTTP support will be disabled!")
|
||||
return()
|
||||
endif()
|
||||
if(NOT TARGET httplib)
|
||||
add_subdirectory("${CPP_HTTPLIB_DIR}" "${CPP_HTTPLIB_DIR}/build"
|
||||
EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
if(NOT OPENSSL_INCLUDE_DIR OR NOT OPENSSL_LIBRARIES)
|
||||
find_package(OpenSSL)
|
||||
if(NOT OPENSSL_FOUND)
|
||||
message(WARNING "OpenSSL not found!\n" "HTTP support will be disabled!\n\n")
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(ZLIB)
|
||||
if(NOT ZLIB_FOUND)
|
||||
message(WARNING "zlib not found!\n" "HTTP support will be disabled!\n\n")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# --- End of section ---
|
||||
|
||||
add_library(${PROJECT_NAME} MODULE)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT=1)
|
||||
if(OS_MACOS)
|
||||
target_compile_definitions(
|
||||
${PROJECT_NAME} PRIVATE CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN=1)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE "-framework CoreFoundation")
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE "-framework Security")
|
||||
endif()
|
||||
|
||||
target_sources(
|
||||
${PROJECT_NAME} PRIVATE macro-action-http.cpp macro-action-http.hpp
|
||||
key-value-list.cpp key-value-list.hpp)
|
||||
|
||||
setup_advss_plugin(${PROJECT_NAME})
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE "${CPP_HTTPLIB_DIR}/"
|
||||
"${OPENSSL_INCLUDE_DIR}")
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${OPENSSL_LIBRARIES} ZLIB::ZLIB)
|
||||
install_advss_plugin(${PROJECT_NAME})
|
||||
if(OS_WINDOWS)
|
||||
# Couldn't really find a better way to install runtime dependencies for
|
||||
# Windows TODO: Clean this up at some point
|
||||
function(FIND_FILES_WITH_PATTERN result pattern dir)
|
||||
execute_process(
|
||||
COMMAND
|
||||
powershell -Command
|
||||
"Get-ChildItem -Path '${dir}' -Recurse -Include ${pattern} |"
|
||||
"Select-Object -First 1 |"
|
||||
"ForEach-Object { $_.FullName -replace '\\\\', '\\\\' }"
|
||||
OUTPUT_VARIABLE files
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(${result}
|
||||
${files}
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
set(OPENSSL_DLL_SEARCH_DIR "${OPENSSL_INCLUDE_DIR}/..")
|
||||
find_files_with_pattern(CRYPTO_DLL_FILES "libcrypto*.dll"
|
||||
"${OPENSSL_DLL_SEARCH_DIR}")
|
||||
find_files_with_pattern(SSL_DLL_FILES "libssl*.dll"
|
||||
"${OPENSSL_DLL_SEARCH_DIR}")
|
||||
install_advss_plugin_dependency(TARGET ${PROJECT_NAME} DEPENDENCIES
|
||||
"${CRYPTO_DLL_FILES}" "${SSL_DLL_FILES}")
|
||||
endif()
|
||||
213
plugins/http/key-value-list.cpp
Normal file
213
plugins/http/key-value-list.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
#include "key-value-list.hpp"
|
||||
#include "name-dialog.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
|
||||
#include <QLayout>
|
||||
#include <QTimer>
|
||||
|
||||
namespace advss {
|
||||
|
||||
KeyValueListEdit::KeyValueListEdit(QWidget *parent, const QString &addKeyString,
|
||||
const QString &addKeyStringDescription,
|
||||
const QString &addValueString,
|
||||
const QString &addValueStringDescription)
|
||||
: ListEditor(parent),
|
||||
_addKeyString(addKeyString),
|
||||
_addKeyStringDescription(addKeyStringDescription),
|
||||
_addValueString(addValueString),
|
||||
_addValueStringDescription(addValueStringDescription)
|
||||
{
|
||||
_list->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
_list->setAutoScroll(false);
|
||||
}
|
||||
|
||||
void KeyValueListEdit::SetStringList(const StringList &list)
|
||||
{
|
||||
_stringList = list;
|
||||
_list->clear();
|
||||
|
||||
for (int i = 0; i < list.size(); i += 2) {
|
||||
AppendListEntryWidget(
|
||||
list.at(i), i + 1 >= list.size() ? "" : list.at(i + 1));
|
||||
}
|
||||
UpdateListSize();
|
||||
}
|
||||
|
||||
void KeyValueListEdit::Add()
|
||||
{
|
||||
StringVariable key;
|
||||
StringVariable value;
|
||||
bool accepted = AskForKeyValue(key, value);
|
||||
if (!accepted) {
|
||||
return;
|
||||
}
|
||||
|
||||
AppendListEntryWidget(key, value);
|
||||
_stringList << key << value;
|
||||
|
||||
// Delay resizing to make sure the list viewport was already updated
|
||||
QTimer::singleShot(0, this, [this]() { UpdateListSize(); });
|
||||
|
||||
StringListChanged(_stringList);
|
||||
}
|
||||
|
||||
void KeyValueListEdit::Remove()
|
||||
{
|
||||
int idx = _list->currentRow();
|
||||
if (idx == -1) {
|
||||
return;
|
||||
}
|
||||
_stringList.removeAt(idx);
|
||||
|
||||
QListWidgetItem *item = _list->currentItem();
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
delete item;
|
||||
|
||||
// Delay resizing to make sure the list viewport was already updated
|
||||
QTimer::singleShot(0, this, [this]() { UpdateListSize(); });
|
||||
|
||||
StringListChanged(_stringList);
|
||||
}
|
||||
|
||||
void KeyValueListEdit::Up()
|
||||
{
|
||||
int idx = _list->currentRow();
|
||||
if (idx <= 0 || idx >= _list->count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MoveStringListIdxUp(idx);
|
||||
|
||||
auto row = _list->itemWidget(_list->currentItem());
|
||||
auto newItem = _list->currentItem()->clone();
|
||||
|
||||
_list->insertItem(idx - 1, newItem);
|
||||
_list->setItemWidget(newItem, row);
|
||||
|
||||
_list->takeItem(idx + 1);
|
||||
_list->setCurrentRow(idx - 1);
|
||||
|
||||
UpdateListSize();
|
||||
|
||||
StringListChanged(_stringList);
|
||||
}
|
||||
|
||||
void KeyValueListEdit::Down()
|
||||
{
|
||||
int idx = _list->currentRow();
|
||||
if (idx == -1 || idx == _list->count() - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
MoveStringListIdxUp(idx + 1);
|
||||
|
||||
auto row = _list->itemWidget(_list->currentItem());
|
||||
auto newItem = _list->currentItem()->clone();
|
||||
|
||||
_list->insertItem(idx + 2, newItem);
|
||||
_list->setItemWidget(newItem, row);
|
||||
|
||||
_list->takeItem(idx);
|
||||
_list->setCurrentRow(idx + 1);
|
||||
|
||||
UpdateListSize();
|
||||
|
||||
StringListChanged(_stringList);
|
||||
}
|
||||
|
||||
void KeyValueListEdit::Clicked(QListWidgetItem *item)
|
||||
{
|
||||
int idx = _list->currentRow();
|
||||
|
||||
StringVariable key = _stringList[idx * 2];
|
||||
StringVariable value = _stringList[idx * 2 + 1];
|
||||
bool accepted = AskForKeyValue(key, value);
|
||||
if (!accepted) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto container = static_cast<KeyValueListContainerWidget *>(
|
||||
_list->itemWidget(item));
|
||||
container->_key->setText(QString::fromStdString(key.UnresolvedValue()));
|
||||
container->_value->setText(
|
||||
QString::fromStdString(value.UnresolvedValue()));
|
||||
container->adjustSize();
|
||||
container->updateGeometry();
|
||||
|
||||
_stringList[idx * 2] = key;
|
||||
_stringList[idx * 2 + 1] = value;
|
||||
|
||||
// Delay resizing to make sure the list viewport was already updated
|
||||
QTimer::singleShot(0, this, [this]() { UpdateListSize(); });
|
||||
StringListChanged(_stringList);
|
||||
}
|
||||
|
||||
void KeyValueListEdit::MoveStringListIdxUp(int idx)
|
||||
{
|
||||
if (idx <= 0 || idx >= _list->count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_stringList.move(idx * 2, idx * 2 - 2);
|
||||
_stringList.move(idx * 2 + 1, idx * 2 - 1);
|
||||
}
|
||||
|
||||
bool KeyValueListEdit::AskForKeyValue(StringVariable &keyVariable,
|
||||
StringVariable &valueVariable)
|
||||
{
|
||||
std::string key;
|
||||
bool accepted = NameDialog::AskForName(
|
||||
this, _addKeyString, _addKeyStringDescription, key,
|
||||
QString::fromStdString(keyVariable.UnresolvedValue()), 4096,
|
||||
false);
|
||||
if (!accepted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string value;
|
||||
accepted = NameDialog::AskForName(
|
||||
this, _addValueString, _addValueStringDescription, value,
|
||||
QString::fromStdString(valueVariable.UnresolvedValue()), 4096,
|
||||
false);
|
||||
if (!accepted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
keyVariable = key;
|
||||
valueVariable = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KeyValueListEdit::AppendListEntryWidget(const StringVariable &key,
|
||||
const StringVariable &value)
|
||||
{
|
||||
QListWidgetItem *item = new QListWidgetItem(_list);
|
||||
auto container = new KeyValueListContainerWidget(this, _list->count());
|
||||
container->_key->setText(QString::fromStdString(key.UnresolvedValue()));
|
||||
container->_value->setText(
|
||||
QString::fromStdString(value.UnresolvedValue()));
|
||||
container->adjustSize();
|
||||
container->updateGeometry();
|
||||
_list->addItem(item);
|
||||
_list->setItemWidget(item, container);
|
||||
UpdateListSize();
|
||||
}
|
||||
|
||||
KeyValueListContainerWidget::KeyValueListContainerWidget(QWidget *parent,
|
||||
int index)
|
||||
: QWidget(parent),
|
||||
_key(new QLabel("Key", this)),
|
||||
_value(new QLabel("Value", this)),
|
||||
_index(index)
|
||||
{
|
||||
auto layout = new QHBoxLayout();
|
||||
layout->addWidget(_key);
|
||||
layout->addWidget(_value);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
53
plugins/http/key-value-list.hpp
Normal file
53
plugins/http/key-value-list.hpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
#include "string-list.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
class KeyValueListEdit final : public ListEditor {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
KeyValueListEdit(QWidget *parent, const QString &addKeyString,
|
||||
const QString &addKeyStringDescription,
|
||||
const QString &addValueString,
|
||||
const QString &addValueStringDescription);
|
||||
void SetStringList(const StringList &);
|
||||
|
||||
private slots:
|
||||
void Add();
|
||||
void Remove();
|
||||
void Up();
|
||||
void Down();
|
||||
void Clicked(QListWidgetItem *);
|
||||
signals:
|
||||
void StringListChanged(const StringList &);
|
||||
|
||||
private:
|
||||
void MoveStringListIdxUp(int);
|
||||
bool AskForKeyValue(StringVariable &key, StringVariable &value);
|
||||
void AppendListEntryWidget(const StringVariable &key,
|
||||
const StringVariable &value);
|
||||
|
||||
StringList _stringList;
|
||||
QString _addKeyString;
|
||||
QString _addKeyStringDescription;
|
||||
QString _addValueString;
|
||||
QString _addValueStringDescription;
|
||||
};
|
||||
|
||||
class KeyValueListContainerWidget final : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
KeyValueListContainerWidget(QWidget *parent, int index);
|
||||
|
||||
private:
|
||||
QLabel *_key;
|
||||
QLabel *_value;
|
||||
|
||||
int _index = -1;
|
||||
friend class KeyValueListEdit;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
463
plugins/http/macro-action-http.cpp
Normal file
463
plugins/http/macro-action-http.cpp
Normal file
@@ -0,0 +1,463 @@
|
||||
#include "macro-action-http.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
|
||||
#include <httplib.h>
|
||||
|
||||
#undef DELETE
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionHttp::id = "http_v2";
|
||||
|
||||
bool MacroActionHttp::_registered = MacroActionFactory::Register(
|
||||
MacroActionHttp::id,
|
||||
{MacroActionHttp::Create, MacroActionHttpEdit::Create,
|
||||
"AdvSceneSwitcher.action.http"});
|
||||
|
||||
static httplib::Headers getHeaders(const StringList &strings)
|
||||
{
|
||||
httplib::Headers headers;
|
||||
for (int i = 0; i < strings.size(); i = i + 2) {
|
||||
const auto pair =
|
||||
i + 1 >= strings.size()
|
||||
? std::make_pair(std::string(strings.at(i)), "")
|
||||
: std::make_pair(
|
||||
std::string(strings.at(i)),
|
||||
std::string(strings.at(i + 1)));
|
||||
headers.emplace(pair);
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
static httplib::Params getParams(const StringList &strings)
|
||||
{
|
||||
httplib::Params params;
|
||||
for (int i = 0; i < strings.size(); i = i + 2) {
|
||||
const auto pair =
|
||||
i + 1 >= strings.size()
|
||||
? std::make_pair(std::string(strings.at(i)), "")
|
||||
: std::make_pair(
|
||||
std::string(strings.at(i)),
|
||||
std::string(strings.at(i + 1)));
|
||||
params.emplace(pair);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
static void setTimeout(httplib::Client &client, const Duration &timeout)
|
||||
{
|
||||
const time_t seconds = timeout.Seconds();
|
||||
const time_t usecs = timeout.Milliseconds() * 1000;
|
||||
client.set_read_timeout(seconds, usecs);
|
||||
client.set_write_timeout(seconds, usecs);
|
||||
}
|
||||
|
||||
void MacroActionHttp::SetupTempVars()
|
||||
{
|
||||
MacroAction::SetupTempVars();
|
||||
AddTempvar("status",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.http.status"));
|
||||
AddTempvar("body",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.http.body"));
|
||||
AddTempvar("error",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.http.error"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.http.error.description"));
|
||||
}
|
||||
|
||||
bool MacroActionHttp::PerformAction()
|
||||
{
|
||||
httplib::Client cli(_url);
|
||||
setTimeout(cli, _timeout);
|
||||
const auto params = _setParams ? getParams(_params) : httplib::Params();
|
||||
const auto headers = _setHeaders ? getHeaders(_headers)
|
||||
: httplib::Headers();
|
||||
|
||||
httplib::Result response;
|
||||
switch (_method) {
|
||||
case MacroActionHttp::Method::GET:
|
||||
response = cli.Get(_path, params, headers);
|
||||
break;
|
||||
case MacroActionHttp::Method::POST: {
|
||||
const auto path = httplib::append_query_params(_path, params);
|
||||
response = cli.Post(path, headers, _body, _contentType);
|
||||
break;
|
||||
}
|
||||
case MacroActionHttp::Method::PUT: {
|
||||
const auto path = httplib::append_query_params(_path, params);
|
||||
response = cli.Put(path, headers, _body, _contentType);
|
||||
break;
|
||||
}
|
||||
case MacroActionHttp::Method::PATCH: {
|
||||
const auto path = httplib::append_query_params(_path, params);
|
||||
response = cli.Patch(path, headers, _body, _contentType);
|
||||
break;
|
||||
}
|
||||
case MacroActionHttp::Method::DELETE: {
|
||||
const auto path = httplib::append_query_params(_path, params);
|
||||
response = cli.Delete(path, headers, _body, _contentType);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SetTempVarValue("status",
|
||||
response ? std::to_string(response->status) : "");
|
||||
SetTempVarValue("body", response ? response->body : "");
|
||||
SetTempVarValue("error",
|
||||
response ? "" : httplib::to_string(response.error()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static constexpr std::string_view methodToString(MacroActionHttp::Method method)
|
||||
{
|
||||
switch (method) {
|
||||
case MacroActionHttp::Method::GET:
|
||||
return "GET";
|
||||
case MacroActionHttp::Method::POST:
|
||||
return "POST";
|
||||
case MacroActionHttp::Method::PUT:
|
||||
return "PUT";
|
||||
case MacroActionHttp::Method::PATCH:
|
||||
return "PATCH";
|
||||
case MacroActionHttp::Method::DELETE:
|
||||
return "DELETE";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static std::string stringListToString(const StringList &list)
|
||||
{
|
||||
if (list.empty()) {
|
||||
return "[]";
|
||||
}
|
||||
std::string result = "[";
|
||||
for (const auto &string : list) {
|
||||
result += std::string(string) + ", ";
|
||||
}
|
||||
result.pop_back();
|
||||
return result + "]";
|
||||
}
|
||||
|
||||
void MacroActionHttp::LogAction() const
|
||||
{
|
||||
ablog(LOG_INFO,
|
||||
"sent HTTP request (%s) "
|
||||
"to URL \"%s\" "
|
||||
"to path \"%s\" "
|
||||
"with content type \"%s\" "
|
||||
"with body \"%s\" "
|
||||
"with headers \"%s\" "
|
||||
"with parameters \"%s\" "
|
||||
"with timeout \"%s\"",
|
||||
methodToString(_method).data(), _url.c_str(), _path.c_str(),
|
||||
_contentType.c_str(), _body.c_str(),
|
||||
_setHeaders ? stringListToString(_headers).c_str() : "-",
|
||||
_setParams ? stringListToString(_params).c_str() : "-",
|
||||
_timeout.ToString().c_str());
|
||||
}
|
||||
|
||||
bool MacroActionHttp::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
_url.Save(obj, "url");
|
||||
_path.Save(obj, "path");
|
||||
_contentType.Save(obj, "contentType");
|
||||
_body.Save(obj, "body");
|
||||
obs_data_set_bool(obj, "setHeaders", _setHeaders);
|
||||
_headers.Save(obj, "headers", "header");
|
||||
obs_data_set_bool(obj, "setParams", _setParams);
|
||||
_params.Save(obj, "params", "param");
|
||||
obs_data_set_int(obj, "method", static_cast<int>(_method));
|
||||
_timeout.Save(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionHttp::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_url.Load(obj, "url");
|
||||
_path.Load(obj, "path");
|
||||
_contentType.Load(obj, "contentType");
|
||||
_body.Load(obj, "body");
|
||||
_setHeaders = obs_data_get_bool(obj, "setHeaders");
|
||||
_headers.Load(obj, "headers", "header");
|
||||
_setParams = obs_data_get_bool(obj, "setParams");
|
||||
_params.Load(obj, "params", "param");
|
||||
_method = static_cast<Method>(obs_data_get_int(obj, "method"));
|
||||
_timeout.Load(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionHttp::GetShortDesc() const
|
||||
{
|
||||
return _url.UnresolvedValue();
|
||||
}
|
||||
|
||||
std::shared_ptr<MacroAction> MacroActionHttp::Create(Macro *m)
|
||||
{
|
||||
return std::make_shared<MacroActionHttp>(m);
|
||||
}
|
||||
|
||||
std::shared_ptr<MacroAction> MacroActionHttp::Copy() const
|
||||
{
|
||||
return std::make_shared<MacroActionHttp>(*this);
|
||||
}
|
||||
|
||||
void MacroActionHttp::ResolveVariablesToFixedValues()
|
||||
{
|
||||
_url.ResolveVariables();
|
||||
_path.ResolveVariables();
|
||||
_contentType.ResolveVariables();
|
||||
_body.ResolveVariables();
|
||||
_headers.ResolveVariables();
|
||||
_params.ResolveVariables();
|
||||
_timeout.ResolveVariables();
|
||||
}
|
||||
|
||||
static inline void populateMethodSelection(QComboBox *list)
|
||||
{
|
||||
const static std::map<MacroActionHttp::Method, std::string> methods = {
|
||||
{MacroActionHttp::Method::GET,
|
||||
"AdvSceneSwitcher.action.http.type.get"},
|
||||
{MacroActionHttp::Method::POST,
|
||||
"AdvSceneSwitcher.action.http.type.post"},
|
||||
{MacroActionHttp::Method::PUT,
|
||||
"AdvSceneSwitcher.action.http.type.put"},
|
||||
{MacroActionHttp::Method::PATCH,
|
||||
"AdvSceneSwitcher.action.http.type.patch"},
|
||||
{MacroActionHttp::Method::DELETE,
|
||||
"AdvSceneSwitcher.action.http.type.delete"},
|
||||
};
|
||||
|
||||
for (const auto &[value, name] : methods) {
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(value));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionHttpEdit::MacroActionHttpEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionHttp> entryData)
|
||||
: QWidget(parent),
|
||||
_url(new VariableLineEdit(this)),
|
||||
_path(new VariableLineEdit(this)),
|
||||
_contentType(new VariableLineEdit(this)),
|
||||
_contentTypeLayout(new QHBoxLayout()),
|
||||
_methods(new QComboBox()),
|
||||
_body(new VariableTextEdit(this)),
|
||||
_bodyLayout(new QVBoxLayout()),
|
||||
_setHeaders(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.http.setHeaders"))),
|
||||
_headerList(new KeyValueListEdit(
|
||||
this, obs_module_text("AdvSceneSwitcher.action.http.headers"),
|
||||
obs_module_text("AdvSceneSwitcher.action.http.addHeader.name"),
|
||||
obs_module_text("AdvSceneSwitcher.action.http.headers"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.http.addHeader.value"))),
|
||||
_headerListLayout(new QVBoxLayout()),
|
||||
_setParams(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.http.setParams"))),
|
||||
_paramList(new KeyValueListEdit(
|
||||
this, obs_module_text("AdvSceneSwitcher.action.http.params"),
|
||||
obs_module_text("AdvSceneSwitcher.action.http.addParam.name"),
|
||||
obs_module_text("AdvSceneSwitcher.action.http.params"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.http.addParam.value"))),
|
||||
_paramListLayout(new QVBoxLayout()),
|
||||
_timeout(new DurationSelection(this, false))
|
||||
{
|
||||
populateMethodSelection(_methods);
|
||||
|
||||
SetWidgetSignalConnections();
|
||||
SetWidgetLayout();
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_url->setText(_entryData->_url);
|
||||
_path->setText(_entryData->_path);
|
||||
_contentType->setText(_entryData->_contentType);
|
||||
_body->setPlainText(_entryData->_body);
|
||||
_setHeaders->setChecked(_entryData->_setHeaders);
|
||||
_headerList->SetStringList(_entryData->_headers);
|
||||
_setParams->setChecked(_entryData->_setParams);
|
||||
_paramList->SetStringList(_entryData->_params);
|
||||
_methods->setCurrentIndex(
|
||||
_methods->findData(static_cast<int>(_entryData->_method)));
|
||||
_timeout->SetDuration(_entryData->_timeout);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::URLChanged()
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_url = _url->text().toStdString();
|
||||
emit(HeaderInfoChanged(_url->text()));
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::PathChanged()
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_path = _path->text().toStdString();
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::ContentTypeChanged()
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_contentType = _contentType->text().toStdString();
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::BodyChanged()
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_body = _body->toPlainText().toUtf8().constData();
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::MethodChanged(int idx)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_method = static_cast<MacroActionHttp::Method>(
|
||||
_methods->itemData(idx).toInt());
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::TimeoutChanged(const Duration &dur)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_timeout = dur;
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::SetHeadersChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_setHeaders = value;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::HeadersChanged(const StringList &headers)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_headers = headers;
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::SetParamsChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_setParams = value;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::ParamsChanged(const StringList ¶ms)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_params = params;
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::SetWidgetSignalConnections()
|
||||
{
|
||||
QWidget::connect(_url, SIGNAL(editingFinished()), this,
|
||||
SLOT(URLChanged()));
|
||||
QWidget::connect(_path, SIGNAL(editingFinished()), this,
|
||||
SLOT(PathChanged()));
|
||||
QWidget::connect(_contentType, SIGNAL(editingFinished()), this,
|
||||
SLOT(ContentTypeChanged()));
|
||||
QWidget::connect(_body, SIGNAL(textChanged()), this,
|
||||
SLOT(BodyChanged()));
|
||||
QWidget::connect(_methods, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(MethodChanged(int)));
|
||||
QWidget::connect(_setHeaders, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(SetHeadersChanged(int)));
|
||||
QWidget::connect(_headerList,
|
||||
SIGNAL(StringListChanged(const StringList &)), this,
|
||||
SLOT(HeadersChanged(const StringList &)));
|
||||
QWidget::connect(_setParams, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(SetParamsChanged(int)));
|
||||
QWidget::connect(_paramList,
|
||||
SIGNAL(StringListChanged(const StringList &)), this,
|
||||
SLOT(ParamsChanged(const StringList &)));
|
||||
QWidget::connect(_timeout, SIGNAL(DurationChanged(const Duration &)),
|
||||
this, SLOT(TimeoutChanged(const Duration &)));
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::SetWidgetLayout()
|
||||
{
|
||||
const std::unordered_map<std::string, QWidget *> widgets = {
|
||||
{"{{url}}", _url},
|
||||
{"{{path}}", _path},
|
||||
{"{{contentType}}", _contentType},
|
||||
{"{{method}}", _methods},
|
||||
{"{{body}}", _body},
|
||||
{"{{timeout}}", _timeout},
|
||||
};
|
||||
|
||||
auto actionLayout = new QHBoxLayout;
|
||||
PlaceWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.http.layout.method"),
|
||||
actionLayout, widgets);
|
||||
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.action.http.layout.contentType"),
|
||||
_contentTypeLayout, widgets);
|
||||
|
||||
_bodyLayout->addWidget(new QLabel(
|
||||
obs_module_text("AdvSceneSwitcher.action.http.body")));
|
||||
_bodyLayout->addWidget(_body);
|
||||
|
||||
auto timeoutLayout = new QHBoxLayout;
|
||||
PlaceWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.http.layout.timeout"),
|
||||
timeoutLayout, widgets);
|
||||
|
||||
_headerListLayout->addWidget(new QLabel(
|
||||
obs_module_text("AdvSceneSwitcher.action.http.headers")));
|
||||
_headerListLayout->addWidget(_headerList);
|
||||
|
||||
_paramListLayout->addWidget(new QLabel(
|
||||
obs_module_text("AdvSceneSwitcher.action.http.params")));
|
||||
_paramListLayout->addWidget(_paramList);
|
||||
|
||||
auto layout = new QVBoxLayout;
|
||||
layout->addLayout(actionLayout);
|
||||
layout->addWidget(_setHeaders);
|
||||
layout->addLayout(_headerListLayout);
|
||||
layout->addWidget(_setParams);
|
||||
layout->addLayout(_paramListLayout);
|
||||
layout->addLayout(_contentTypeLayout);
|
||||
layout->addLayout(_bodyLayout);
|
||||
layout->addLayout(timeoutLayout);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void MacroActionHttpEdit::SetWidgetVisibility()
|
||||
{
|
||||
SetLayoutVisible(_headerListLayout, _entryData->_setHeaders);
|
||||
SetLayoutVisible(_paramListLayout, _entryData->_setParams);
|
||||
SetLayoutVisible(_contentTypeLayout,
|
||||
_entryData->_method != MacroActionHttp::Method::GET);
|
||||
SetLayoutVisible(_bodyLayout,
|
||||
_entryData->_method != MacroActionHttp::Method::GET);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
107
plugins/http/macro-action-http.hpp
Normal file
107
plugins/http/macro-action-http.hpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "key-value-list.hpp"
|
||||
#include "variable-text-edit.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroActionHttp final : public MacroAction {
|
||||
public:
|
||||
MacroActionHttp(Macro *m) : MacroAction(m, true) {}
|
||||
bool PerformAction();
|
||||
void LogAction() const;
|
||||
bool Save(obs_data_t *obj) const;
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc() const;
|
||||
std::string GetId() const { return id; };
|
||||
static std::shared_ptr<MacroAction> Create(Macro *m);
|
||||
std::shared_ptr<MacroAction> Copy() const;
|
||||
void ResolveVariablesToFixedValues();
|
||||
|
||||
enum class Method {
|
||||
GET = 0,
|
||||
POST,
|
||||
PUT,
|
||||
PATCH,
|
||||
DELETE,
|
||||
};
|
||||
|
||||
StringVariable _url = "127.0.0.1:8080";
|
||||
StringVariable _path = "/";
|
||||
StringVariable _body = obs_module_text("AdvSceneSwitcher.enterText");
|
||||
StringVariable _contentType = "application/json";
|
||||
bool _setHeaders = false;
|
||||
StringList _headers;
|
||||
bool _setParams = false;
|
||||
StringList _params;
|
||||
Method _method = Method::GET;
|
||||
Duration _timeout = Duration(1.0);
|
||||
|
||||
private:
|
||||
void SetupTempVars();
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionHttpEdit final : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionHttpEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionHttp> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionHttpEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionHttp>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void URLChanged();
|
||||
void PathChanged();
|
||||
void BodyChanged();
|
||||
void ContentTypeChanged();
|
||||
void MethodChanged(int);
|
||||
void TimeoutChanged(const Duration &seconds);
|
||||
void SetHeadersChanged(int);
|
||||
void HeadersChanged(const StringList &);
|
||||
void SetParamsChanged(int);
|
||||
void ParamsChanged(const StringList &);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
private:
|
||||
void SetWidgetSignalConnections();
|
||||
void SetWidgetLayout();
|
||||
void SetWidgetVisibility();
|
||||
|
||||
VariableLineEdit *_url;
|
||||
VariableLineEdit *_path;
|
||||
VariableLineEdit *_contentType;
|
||||
QHBoxLayout *_contentTypeLayout;
|
||||
QComboBox *_methods;
|
||||
VariableTextEdit *_body;
|
||||
QVBoxLayout *_bodyLayout;
|
||||
QCheckBox *_setHeaders;
|
||||
KeyValueListEdit *_headerList;
|
||||
QVBoxLayout *_headerListLayout;
|
||||
QCheckBox *_setParams;
|
||||
KeyValueListEdit *_paramList;
|
||||
QVBoxLayout *_paramListLayout;
|
||||
DurationSelection *_timeout;
|
||||
|
||||
std::shared_ptr<MacroActionHttp> _entryData;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
@@ -19,9 +19,22 @@ add_library(${PROJECT_NAME} MODULE)
|
||||
|
||||
if(OS_WINDOWS)
|
||||
if(MSVC)
|
||||
target_compile_options(libremidi PRIVATE /wd4251 /wd4267 /wd4275 /wd4101
|
||||
/wd4244 /wd4018)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /wd4101 /wd4244 /wd4018)
|
||||
target_compile_options(
|
||||
libremidi
|
||||
PRIVATE /wd4018
|
||||
/wd4068
|
||||
/wd4100
|
||||
/wd4101
|
||||
/wd4189
|
||||
/wd4244
|
||||
/wd4251
|
||||
/wd4267
|
||||
/wd4275
|
||||
/wd4389
|
||||
/wd4505
|
||||
/wd4702)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /wd4017 /wd4068 /wd4100
|
||||
/wd4101 /wd4244)
|
||||
endif()
|
||||
else()
|
||||
target_compile_options(
|
||||
|
||||
@@ -10,8 +10,10 @@ if(NOT EXISTS "${CPP_HTTPLIB_DIR}/CMakeLists.txt")
|
||||
"Twitch support will be disabled!")
|
||||
return()
|
||||
endif()
|
||||
add_subdirectory("${CPP_HTTPLIB_DIR}" "${CPP_HTTPLIB_DIR}/build"
|
||||
EXCLUDE_FROM_ALL)
|
||||
if(NOT TARGET httplib)
|
||||
add_subdirectory("${CPP_HTTPLIB_DIR}" "${CPP_HTTPLIB_DIR}/build"
|
||||
EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
if(NOT OPENSSL_INCLUDE_DIR OR NOT OPENSSL_LIBRARIES)
|
||||
find_package(OpenSSL)
|
||||
|
||||
Reference in New Issue
Block a user