commit 230439917489e68eb4131d90a9664d61889ae2d4
parent 361246ba698171a30bb4b3f471985f9d295193a9
Author: cfillion <cfillion@users.noreply.github.com>
Date: Sat, 28 Nov 2015 15:29:48 -0500
implement script installation
Diffstat:
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) {