diff --git a/CMakeLists.txt b/CMakeLists.txt index f6f95ffe..6477be90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ if(BUILD_OUT_OF_TREE) src/headers/advanced-scene-switcher.hpp src/headers/switcher-data-structs.hpp src/headers/utility.hpp + src/headers/curl-helper.hpp ) set(advanced-scene-switcher_SOURCES @@ -55,6 +56,7 @@ if(BUILD_OUT_OF_TREE) src/pause-switch.cpp src/random.cpp src/time-switch.cpp + src/curl-helper.cpp ) set(advanced-scene-switcher_UI @@ -105,8 +107,7 @@ if(BUILD_OUT_OF_TREE) ${LIBOBS_LIB} ${LIBOBS_FRONTEND_API_LIB} Qt5::Core - Qt5::Widgets - ${LIBCURL_LIBRARIES}) + Qt5::Widgets) # Additional commands to install the module in the correct place. # Find all the translation files so we can copy them to the correct @@ -167,6 +168,7 @@ else () src/headers/advanced-scene-switcher.hpp src/headers/switcher-data-structs.hpp src/headers/utility.hpp + src/headers/curl-helper.hpp ) set(advanced-scene-switcher_SOURCES @@ -187,6 +189,7 @@ else () src/pause-switch.cpp src/random.cpp src/time-switch.cpp + src/curl-helper.cpp ) set(advanced-scene-switcher_UI @@ -227,8 +230,7 @@ else () ${advanced-scene-switcher_PLATFORM_LIBS} obs-frontend-api Qt5::Widgets - libobs - ${LIBCURL_LIBRARIES}) + libobs) install_obs_plugin(advanced-scene-switcher data) endif() diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index 84328e3b..4512cfbd 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -2404,7 +2404,7 @@ File - + @@ -2537,6 +2537,22 @@ + + + + true + + + + 75 + true + + + + Failed to load libcurl! Accesssing remote files will not be possible! + + + diff --git a/src/advanced-scene-switcher.cpp b/src/advanced-scene-switcher.cpp index 205814c0..5c334d8e 100644 --- a/src/advanced-scene-switcher.cpp +++ b/src/advanced-scene-switcher.cpp @@ -16,6 +16,7 @@ #include "headers/switcher-data-structs.hpp" #include "headers/advanced-scene-switcher.hpp" #include "headers/utility.hpp" +#include "headers/curl-helper.hpp" SwitcherData *switcher = nullptr; @@ -342,6 +343,13 @@ void SwitcherData::Stop() ********************************************************************************/ extern "C" void FreeSceneSwitcher() { + if (loaded_curl_lib) { + if (switcher->curl && f_curl_cleanup) + f_curl_cleanup(switcher->curl); + delete loaded_curl_lib; + loaded_curl_lib = nullptr; + } + delete switcher; switcher = nullptr; } @@ -406,6 +414,10 @@ extern "C" void InitSceneSwitcher() switcher = new SwitcherData; + if (loadCurl() && f_curl_init) { + switcher->curl = f_curl_init(); + } + auto cb = []() { QMainWindow *window = (QMainWindow *)obs_frontend_get_main_window(); diff --git a/src/curl-helper.cpp b/src/curl-helper.cpp new file mode 100644 index 00000000..b6cfd527 --- /dev/null +++ b/src/curl-helper.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include + +#include "headers/curl-helper.hpp" + +initFunction f_curl_init = nullptr; +setOptFunction f_curl_setopt = nullptr; +performFunction f_curl_perform = nullptr; +cleanupFunction f_curl_cleanup = nullptr; + +QLibrary *loaded_curl_lib = nullptr; + +bool resolveCurl() +{ + f_curl_init = (initFunction)loaded_curl_lib->resolve("curl_easy_init"); + f_curl_setopt = (setOptFunction)loaded_curl_lib->resolve("curl_easy_setopt"); + f_curl_perform = + (performFunction)loaded_curl_lib->resolve("curl_easy_perform"); + f_curl_cleanup = + (cleanupFunction)loaded_curl_lib->resolve("curl_easy_cleanup"); + + if (f_curl_init && f_curl_setopt && f_curl_perform && f_curl_cleanup) { + blog(LOG_INFO, "curl loaded successfully"); + return true; + } + + blog(LOG_INFO, "curl symbols not resolved"); + return false; +} + +bool loadCurl() +{ + QStringList locations; + locations << QDir::currentPath(); +#if defined(__linux__) || defined(__APPLE__) + locations << "/usr/lib"; + locations << "/usr/local/lib"; + locations << "/usr/lib/x86_64-linux-gnu"; + locations << "/usr/local/opt/curl/lib"; +#endif + + for (QString path : locations) { + blog(LOG_INFO, "trying '%s'", path.toUtf8().constData()); + QFileInfo libPath(QDir(path).absoluteFilePath(CURL_LIBRARY_NAME)); + + if (libPath.exists() && libPath.isFile()) { + QString libFilePath = libPath.absoluteFilePath(); + blog(LOG_INFO, "found curl library at '%s'", + libFilePath.toUtf8().constData()); + + loaded_curl_lib = new QLibrary(libFilePath, nullptr); + if (resolveCurl()) + return true; + else { + delete loaded_curl_lib; + loaded_curl_lib = nullptr; + } + } + } + + blog(LOG_ERROR, "can't find the curl library"); + return false; +} diff --git a/src/file-switch.cpp b/src/file-switch.cpp index b5213cbf..1bf9345f 100644 --- a/src/file-switch.cpp +++ b/src/file-switch.cpp @@ -5,6 +5,7 @@ #include #include "headers/advanced-scene-switcher.hpp" +#include "headers/curl-helper.hpp" #define LOCAL_FILE_IDX 0 #define REMOTE_FILE_IDX 1 @@ -124,17 +125,13 @@ static size_t WriteCallback(void *contents, size_t size, size_t nmemb, std::string getRemoteData(std::string &url) { - CURL *curl; - CURLcode res; std::string readBuffer; - curl = curl_easy_init(); - if (curl) { - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); - res = curl_easy_perform(curl); - curl_easy_cleanup(curl); + if (switcher->curl && f_curl_setopt && f_curl_perform) { + f_curl_setopt(switcher->curl, CURLOPT_URL, url.c_str()); + f_curl_setopt(switcher->curl, CURLOPT_WRITEFUNCTION, WriteCallback); + f_curl_setopt(switcher->curl, CURLOPT_WRITEDATA, &readBuffer); + f_curl_perform(switcher->curl); } return readBuffer; } @@ -447,6 +444,9 @@ void SceneSwitcher::setupFileTab() "Note that the scene switcher will try to access the remote location every " + QString::number(switcher->interval) + "ms"); + if (switcher->curl) + ui->libcurlWarning->setVisible(false); + for (auto &s : switcher->fileSwitches) { std::string sceneName = GetWeakSourceName(s.scene); std::string transitionName = GetWeakSourceName(s.transition); diff --git a/src/headers/curl-helper.hpp b/src/headers/curl-helper.hpp new file mode 100644 index 00000000..80a447e1 --- /dev/null +++ b/src/headers/curl-helper.hpp @@ -0,0 +1,26 @@ +#pragma once +#include +#include + +#if defined(WIN32) +#define CURL_LIBRARY_NAME "libcurl.dll" +#elif __APPLE__ +#define CURL_LIBRARY_NAME "libcurl.4.dylib" +#else +#define CURL_LIBRARY_NAME "libcurl.so.4" +#endif + +typedef CURL *(*initFunction)(void); +typedef CURLcode (*setOptFunction)(CURL *, CURLoption, ...); +typedef CURLcode (*performFunction)(CURL *); +typedef void (*cleanupFunction)(CURL *); + +extern initFunction f_curl_init; +extern setOptFunction f_curl_setopt; +extern performFunction f_curl_perform; +extern cleanupFunction f_curl_cleanup; + +extern QLibrary *loaded_curl_lib; + +bool resolveCurl(); +bool loadCurl(); diff --git a/src/headers/switcher-data-structs.hpp b/src/headers/switcher-data-structs.hpp index 16a9efc8..7732d6f3 100644 --- a/src/headers/switcher-data-structs.hpp +++ b/src/headers/switcher-data-structs.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "utility.hpp" #define DEFAULT_INTERVAL 300 @@ -309,6 +310,7 @@ struct SwitcherData { FileIOData fileIO; IdleData idleData; std::vector fileSwitches; + CURL *curl = nullptr; std::vector executableSwitches;