diff --git a/buildspec.json b/buildspec.json index 5c37151..ce7be28 100644 --- a/buildspec.json +++ b/buildspec.json @@ -39,8 +39,8 @@ "name": "elgato-marketplace-connect", "displayName": "Elgato Marketplace Connect", "versionMajor": 1, - "versionMinor": 0, - "versionPatch": 2, + "versionMinor": 1, + "versionPatch": 0, "buildNumber": 0, "releaseType": "release", "author": "Elgato", diff --git a/src/export-wizard.cpp b/src/export-wizard.cpp index b80b953..724418a 100644 --- a/src/export-wizard.cpp +++ b/src/export-wizard.cpp @@ -18,9 +18,12 @@ with this program. If not, see #include +#include + #include "export-wizard.hpp" #include "elgato-styles.hpp" #include "plugins.hpp" +#include "plugin-support.h" #include #include #include @@ -52,9 +55,7 @@ const std::vector ExcludedModules{ "obs-outputs.dll", "obs-nvenc.dll", "obs-filters.dll", "obs-ffmpeg.dll", "obs-browser.dll", "nv-filters.dll", "image-source.dll", "frontend-tools.dll", "decklink-output-ui.dll", "decklink-captions.dll", - "coreaudio-encoder.dll", - // This plugin - "elgato-marketplace.dll"}; + "coreaudio-encoder.dll", "elgato-marketplace.dll"}; FileCollectionCheck::FileCollectionCheck(QWidget *parent, std::vector files) @@ -80,8 +81,30 @@ FileCollectionCheck::FileCollectionCheck(QWidget *parent, layout->addWidget(subTitle); auto fileList = new QListWidget(this); + std::vector browserSourceDirs; + for (auto fileName : _files) { - fileList->addItem(fileName.c_str()); + bool hasExtension = fileName.rfind(".") != std::string::npos; + std::string extension = + hasExtension ? os_get_path_extension(fileName.c_str()) + : ""; + if (extension == ".html" || extension == ".htm") { + if (fileName.rfind("/") == std::string::npos) { + obs_log(LOG_INFO, "Error exporting file- could not determine parent directory of file."); + continue; + } + std::string parentDir = fileName.substr(0, fileName.rfind("/")); + if (std::find(browserSourceDirs.begin(), browserSourceDirs.end(), parentDir) == browserSourceDirs.end()) { + browserSourceDirs.push_back(parentDir); + std::vector parentDirFiles; + _SubFiles(parentDirFiles, parentDir); + for (auto parentFileName : parentDirFiles) { + fileList->addItem(parentFileName.c_str()); + } + } + } else { + fileList->addItem(fileName.c_str()); + } } fileList->setStyleSheet(EListStyle); @@ -106,6 +129,40 @@ FileCollectionCheck::FileCollectionCheck(QWidget *parent, layout->addLayout(buttons); } +bool FileCollectionCheck::_SubFiles(std::vector& files, std::string curDir) +{ + os_dir_t* dir = os_opendir(curDir.c_str()); + if (dir) { + struct os_dirent* ent; + for (;;) { + ent = os_readdir(dir); + if (!ent) + break; + if (ent->directory) { + std::string dName = ent->d_name; + if (dName == "." || dName == "..") { + continue; + } + std::string dPath = curDir + "/" + dName; + if (!_SubFiles(files, dPath)) { + os_closedir(dir); + return false; + } + } else { + std::string filename = ent->d_name; + std::string filePath = curDir + "/" + filename; + files.push_back(filePath); + } + } + } else { + obs_log(LOG_ERROR, "Fatal: Could not open directory: %s", + curDir.c_str()); + return false; + } + os_closedir(dir); + return true; +} + VideoSourceLabels::VideoSourceLabels(QWidget *parent, std::map devices) : QWidget(parent) diff --git a/src/export-wizard.hpp b/src/export-wizard.hpp index db6fcd6..b446e5b 100644 --- a/src/export-wizard.hpp +++ b/src/export-wizard.hpp @@ -51,6 +51,7 @@ class FileCollectionCheck : public QWidget { private: std::vector _files; + bool _SubFiles(std::vector& files, std::string curDir); }; class VideoSourceLabels : public QWidget { diff --git a/src/scene-bundle.cpp b/src/scene-bundle.cpp index e7776dc..b8908a5 100644 --- a/src/scene-bundle.cpp +++ b/src/scene-bundle.cpp @@ -28,6 +28,7 @@ with this program. If not, see #include #include #include +#include #include #include #include @@ -46,7 +47,10 @@ const std::map extensionMap{ {".mkv", "/video/"}, {".mp3", "/audio/"}, {".wav", "/aduio/"}, {".effect", "/shaders/"}, {".shader", "/shaders/"}, {".hlsl", "/shaders/"}, - {".lua", "/scripts/"}, {".py", "/scripts/"}}; + {".lua", "/scripts/"}, {".py", "/scripts/"}, + {".html", "/browser-sources/"}, + {".htm", "/browser-sources/"} +}; // Filter IDs of incompatible filter types, e.g. filters // that require external libraries or executables. @@ -305,11 +309,26 @@ SceneBundleStatus SceneBundle::ToElgatoCloudFile( std::string collection_json = _collection.dump(2); std::string bundleInfo_json = bundleInfo.dump(2); + std::vector browserSourceDirs; + ecFile.writestr("collection.json", collection_json); ecFile.writestr("bundle_info.json", bundleInfo_json); // Write all assets to zip archive. for (const auto &file : _fileMap) { std::string oFilename = file.first; + + std::string filename = oFilename.substr(oFilename.rfind("/") + 1); + std::string parentDir = oFilename.substr(0, oFilename.rfind("/")); + std::string zipParent = file.second.substr(0, file.second.rfind("/")); + bool hasExtension = filename.rfind(".") != std::string::npos; + std::string extension = + hasExtension ? os_get_path_extension(oFilename.c_str()) + : ""; + bool isBrowserSource = extension == ".html" || extension == ".htm"; + bool addBrowser = isBrowserSource && std::find(browserSourceDirs.begin(), browserSourceDirs.end(), parentDir) == browserSourceDirs.end(); + if (addBrowser) { + browserSourceDirs.push_back(parentDir); + } struct stat st; os_stat(oFilename.c_str(), &st); if ((st.st_mode & S_IFMT) == S_IFDIR) { @@ -322,13 +341,24 @@ SceneBundleStatus SceneBundle::ToElgatoCloudFile( } return SceneBundleStatus::Error; } - } else if (!_AddFileToZip(file.first, file.second, ecFile)) { - bool wasInterrupted = _interrupt; - _interrupt = false; - if (wasInterrupted) { - return _interruptReason; + } else if (addBrowser) { + if (!_AddBrowserSourceContentsToZip(parentDir, zipParent, ecFile)) { + bool wasInterrupted = _interrupt; + _interrupt = false; + if (wasInterrupted) { + return _interruptReason; + } + return SceneBundleStatus::Error; + } + } else if(!isBrowserSource) { + if (!_AddFileToZip(file.first, file.second, ecFile)) { + bool wasInterrupted = _interrupt; + _interrupt = false; + if (wasInterrupted) { + return _interruptReason; + } + return SceneBundleStatus::Error; } - return SceneBundleStatus::Error; } } @@ -505,6 +535,13 @@ void SceneBundle::_CreateFileMap(nlohmann::json &item) } else { directory = "/misc/"; } + bool isBrowserSource = extension == ".htm" || extension == ".html"; + if (isBrowserSource) { + std::filesystem::path pathObj(value); + auto parentPath = pathObj.parent_path(); + std::string parent = parentPath.filename().string(); + directory += parent + "/"; + } std::string newFileName = "Assets" + directory + filename; auto result = std::find_if(std::begin(_fileMap), std::end(_fileMap), @@ -538,6 +575,51 @@ bool SceneBundle::_AddFileToZip(std::string filePath, std::string zipPath, return true; } +bool SceneBundle::_AddBrowserSourceContentsToZip(std::string dirPath, std::string zipDir, + miniz_cpp::zip_file& ecFile) +{ + // Iterate the files in the directory and add them to the zip. + // Ignore sub-directories + os_dir_t* dir = os_opendir(dirPath.c_str()); + if (dir) { + struct os_dirent* ent; + for (;;) { + ent = os_readdir(dir); + if (!ent) + break; + if (ent->directory) { + std::string dName = ent->d_name; + if (dName == "." || dName == "..") { + continue; + } + std::string dPath = dirPath + "/" + dName; + std::string zipDPath = zipDir + "/" + dName; + if (!_AddBrowserSourceContentsToZip(dPath, zipDPath, ecFile)) { + os_closedir(dir); + return false; + } + } else { + std::string filename = ent->d_name; + std::string filePath = dirPath + "/" + filename; + std::string zipFilePath = zipDir + "/" + filename; + if (!_AddFileToZip(filePath, zipFilePath, ecFile)) { + os_closedir(dir); + return false; + } + } + } + } + else { + obs_log(LOG_ERROR, "Fatal: Could not open directory: %s", + dirPath.c_str()); + return false; + } + + os_closedir(dir); + + return true; +} + bool SceneBundle::_AddDirContentsToZip(std::string dirPath, std::string zipDir, miniz_cpp::zip_file &ecFile) { diff --git a/src/scene-bundle.hpp b/src/scene-bundle.hpp index 1b6c772..45a29f7 100644 --- a/src/scene-bundle.hpp +++ b/src/scene-bundle.hpp @@ -93,6 +93,8 @@ class SceneBundle { miniz_cpp::zip_file &ecFile); bool _AddDirContentsToZip(std::string dirPath, std::string zipDir, miniz_cpp::zip_file &ecFile); + bool _AddBrowserSourceContentsToZip(std::string dirPath, std::string zipDir, + miniz_cpp::zip_file& ecFile); void _reset(); };