reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

commit 230439917489e68eb4131d90a9664d61889ae2d4
parent 361246ba698171a30bb4b3f471985f9d295193a9
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Sat, 28 Nov 2015 15:29:48 -0500

implement script installation

Diffstat:
Msrc/database.cpp | 8++++++++
Msrc/database.hpp | 4++++
Msrc/main.cpp | 8++------
Msrc/reapack.cpp | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/reapack.hpp | 22+++++++++++++++++++++-
Mtest/database.cpp | 3++-
6 files changed, 120 insertions(+), 12 deletions(-)

diff --git a/src/database.cpp b/src/database.cpp @@ -37,6 +37,9 @@ void Database::addCategory(CategoryPtr cat) return; m_categories.push_back(cat); + + m_packages.insert(m_packages.end(), + cat->packages().begin(), cat->packages().end()); } Category::Category(const std::string &name) @@ -93,3 +96,8 @@ VersionPtr Package::version(const int index) const return *it; } + +VersionPtr Package::lastVersion() const +{ + return *prev(m_versions.end()); +} diff --git a/src/database.hpp b/src/database.hpp @@ -26,10 +26,13 @@ public: const std::vector<CategoryPtr> &categories() const { return m_categories; } CategoryPtr category(const int i) const { return m_categories[i]; } + const std::vector<PackagePtr> &packages() const { return m_packages; } + private: static DatabasePtr loadV1(TiXmlElement *); std::vector<CategoryPtr> m_categories; + std::vector<PackagePtr> m_packages; }; class Category { @@ -68,6 +71,7 @@ public: void addVersion(VersionPtr ver); const VersionSet &versions() const { return m_versions; } VersionPtr version(const int i) const; + VersionPtr lastVersion() const; private: Category *m_category; diff --git a/src/main.cpp b/src/main.cpp @@ -1,7 +1,5 @@ #include "reapack.hpp" -#include <cstdlib> - #define REAPERAPI_IMPLEMENT #include <reaper_plugin_functions.h> @@ -21,12 +19,10 @@ extern "C" REAPER_PLUGIN_DLL_EXPORT int REAPER_PLUGIN_ENTRYPOINT( if(REAPERAPI_LoadAPI(rec->GetFunc) > 0) return 0; - printf("%s\n", GetResourcePath()); - reapack.init(instance, rec); - reapack.setupAction("REAPACKMGR", "ReaPack: Package Manager", - &reapack.action, std::bind(&ReaPack::toggleBrowser, reapack)); + reapack.setupAction("REAPACKSYNC", "ReaPack: Synchronize Packages", + &reapack.action, std::bind(&ReaPack::synchronize, reapack)); rec->Register("hookcommand", (void *)commandHook); diff --git a/src/reapack.cpp b/src/reapack.cpp @@ -1,15 +1,31 @@ #include "reapack.hpp" #include "errors.hpp" -#include "database.hpp" +#include "resource.hpp" + +#include <fstream> #include "reaper_plugin_functions.h" +using namespace std; + void ReaPack::init(REAPER_PLUGIN_HINSTANCE instance, reaper_plugin_info_t *rec) { m_instance = instance; m_rec = rec; m_mainHandle = GetMainHwnd(); + m_resourcePath = GetResourcePath(); +} + +ReaPack::~ReaPack() +{ + while(!m_downloadQueue.empty()) { + Download *download = m_downloadQueue.front(); + download->stop(); + // delete in the stop callback + + m_downloadQueue.pop(); + } } void ReaPack::setupAction(const char *name, const char *desc, @@ -32,13 +48,76 @@ bool ReaPack::execActions(const int id, const int) return true; } -void ReaPack::toggleBrowser() +void ReaPack::synchronize() { try { - Database::load("/Users/cfillion/Programs/reapack/reapack.xml"); - ShowMessageBox("Hello World!", "Test", 0); + m_database = Database::load("/Users/cfillion/Programs/reapack/reapack.xml"); + + for(PackagePtr pkg : m_database->packages()) { + installPackage(pkg); + } } catch(const reapack_error &e) { ShowMessageBox(e.what(), "Database Error", 0); } } + +void ReaPack::installPackage(PackagePtr pkg) +{ + const char *url = pkg->lastVersion()->source(0)->url().c_str(); + + queuedDownload(url, [=](const int status, const string &contents) { + if(status != 200) { + ShowMessageBox(contents.c_str(), "Download failure (debug)", 0); + return; + } + + + const Location loc = scriptLocation(pkg); + switch(pkg->type()) { + case Package::ScriptType: + break; + default: + return; + }; + + RecursiveCreateDirectory(loc.directory.c_str(), 0); + + ofstream file(loc.path()); + if(file.bad()) { + ShowMessageBox(strerror(errno), pkg->name().c_str(), 0); + return; + } + + file << contents; + file.close(); + }); +} + +Location ReaPack::scriptLocation(PackagePtr pkg) +{ + string path = string(m_resourcePath) + .append("/Scripts/ReaScripts") + .append("/" + pkg->category()->name()) + ; + + return {path, pkg->name()}; +} + +void ReaPack::queuedDownload(const char *url, DownloadCallback cb) +{ + Download *download = new Download(url); + download->addCallback(cb); + download->addCallback([=](const int, const string &) { + m_downloadQueue.pop(); + delete download; + + if(!m_downloadQueue.empty()) + m_downloadQueue.front()->start(); + }); + + m_downloadQueue.push(download); + + if(m_downloadQueue.size() == 1) + download->start(); +} diff --git a/src/reapack.hpp b/src/reapack.hpp @@ -3,13 +3,26 @@ #include <functional> #include <map> +#include <queue> + +#include "database.hpp" +#include "download.hpp" #include "reaper_plugin.h" +struct Location { + std::string path() const { return directory + "/" + filename; } + + std::string directory; + std::string filename; +}; + typedef std::function<void()> ActionCallback; class ReaPack { public: + ~ReaPack(); + gaccel_register_t action; void init(REAPER_PLUGIN_HINSTANCE, reaper_plugin_info_t *); @@ -18,14 +31,21 @@ public: gaccel_register_t *action, ActionCallback callback); bool execActions(const int id, const int); - void toggleBrowser(); + void synchronize(); + void installPackage(PackagePtr pkg); + void queuedDownload(const char *url, DownloadCallback cb); private: + Location scriptLocation(PackagePtr pkg); + std::map<int, ActionCallback> m_actions; + DatabasePtr m_database; + std::queue<Download *> m_downloadQueue; REAPER_PLUGIN_HINSTANCE m_instance; reaper_plugin_info_t *m_rec; HWND m_mainHandle; + const char *m_resourcePath; }; #endif diff --git a/test/database.cpp b/test/database.cpp @@ -60,7 +60,6 @@ TEST_CASE("future version", M) { REQUIRE(string(e.what()) == "unsupported version"); } } - TEST_CASE("add category", M) { VersionPtr ver = make_shared<Version>("1"); ver->addSource(make_shared<Source>(Source::GenericPlatform, "google.com")); @@ -77,6 +76,7 @@ TEST_CASE("add category", M) { db.addCategory(cat); REQUIRE(db.categories().size() == 1); + REQUIRE(db.packages() == cat->packages()); } TEST_CASE("drop empty category", M) { @@ -177,6 +177,7 @@ TEST_CASE("package versions are sorted", M) { REQUIRE(pack.version(0) == alpha); REQUIRE(pack.version(1) == final); + REQUIRE(pack.lastVersion() == final); } TEST_CASE("drop empty version", M) {