Browse Source

Split plugin.hpp to folder of headers, wrap plugin state in new PluginManager class

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
c31b8f0ba2
16 changed files with 256 additions and 227 deletions
  1. +1
    -1
      include/app/ModuleWidget.hpp
  2. +1
    -1
      include/asset.hpp
  3. +1
    -1
      include/helpers.hpp
  4. +0
    -102
      include/plugin.hpp
  5. +41
    -0
      include/plugin/Model.hpp
  6. +41
    -0
      include/plugin/Plugin.hpp
  7. +46
    -0
      include/plugin/PluginManager.hpp
  8. +9
    -0
      include/plugin/callbacks.hpp
  9. +4
    -1
      include/rack.hpp
  10. +4
    -4
      src/app/ModuleBrowser.cpp
  11. +13
    -11
      src/app/PluginManagerWidget.cpp
  12. +2
    -1
      src/app/RackWidget.cpp
  13. +6
    -2
      src/main.cpp
  14. +21
    -0
      src/plugin/Plugin.cpp
  15. +63
    -100
      src/plugin/PluginManager.cpp
  16. +3
    -3
      src/settings.cpp

+ 1
- 1
include/app/ModuleWidget.hpp View File

@@ -5,7 +5,7 @@
#include "app/SVGPanel.hpp" #include "app/SVGPanel.hpp"
#include "app/Port.hpp" #include "app/Port.hpp"
#include "app/ParamWidget.hpp" #include "app/ParamWidget.hpp"
#include "plugin.hpp"
#include "plugin/Model.hpp"
#include "engine/Module.hpp" #include "engine/Module.hpp"






+ 1
- 1
include/asset.hpp View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "common.hpp" #include "common.hpp"
#include "plugin.hpp"
#include "plugin/Plugin.hpp"




namespace rack { namespace rack {


+ 1
- 1
include/helpers.hpp View File

@@ -1,4 +1,4 @@
#include "plugin.hpp"
#include "plugin/Model.hpp"
#include "event.hpp" #include "event.hpp"
#include "ui/MenuLabel.hpp" #include "ui/MenuLabel.hpp"
#include "ui/MenuItem.hpp" #include "ui/MenuItem.hpp"


+ 0
- 102
include/plugin.hpp View File

@@ -1,102 +0,0 @@
#pragma once
#include <string>
#include <list>
#include "common.hpp"
#include "tags.hpp"


namespace rack {


struct ModuleWidget;
struct Module;
struct Model;


// Subclass this and return a pointer to a new one when init() is called
struct Plugin {
/** A list of the models available by this plugin, add with addModel() */
std::list<Model*> models;
/** The file path of the plugin's directory */
std::string path;
/** OS-dependent library handle */
void *handle = NULL;

/** Must be unique. Used for patch files and the VCV store API.
To guarantee uniqueness, it is a good idea to prefix the slug by your "company name" if available, e.g. "MyCompany-MyPlugin"
*/
std::string slug;

/** The version of your plugin
Plugins should follow the versioning scheme described at https://github.com/VCVRack/Rack/issues/266
Do not include the "v" in "v1.0" for example.
*/
std::string version;

/** Deprecated, do not use. */
std::string website;
std::string manual;

virtual ~Plugin();
void addModel(Model *model);
};


struct Model {
Plugin *plugin = NULL;
/** An identifier for the model, e.g. "VCO". Used for saving patches.
The model slug must be unique in your plugin, but it doesn't need to be unique among different plugins.
*/
std::string slug;
/** Human readable name for your model, e.g. "Voltage Controlled Oscillator" */
std::string name;
/** The author name of the module.
This might be different than the plugin slug. For example, if you create multiple plugins but want them to be branded similarly, you may use the same author in multiple plugins.
You may even have multiple authors in one plugin, although this property will be moved to Plugin for Rack 1.0.
*/
std::string author;
/** List of tags representing the function(s) of the module (optional) */
std::list<ModelTag> tags;

virtual ~Model() {}
/** Creates a headless Module */
virtual Module *createModule() { return NULL; }
/** Creates a ModuleWidget with a Module attached */
virtual ModuleWidget *createModuleWidget() { return NULL; }
/** Creates a ModuleWidget with no Module, useful for previews */
virtual ModuleWidget *createModuleWidgetNull() { return NULL; }
};


void pluginInit(bool devMode);
void pluginDestroy();
void pluginLogIn(std::string email, std::string password);
void pluginLogOut();
/** Returns whether a new plugin is available, and downloads it unless doing a dry run */
bool pluginSync(bool dryRun);
void pluginCancelDownload();
bool pluginIsLoggedIn();
bool pluginIsDownloading();
float pluginGetDownloadProgress();
std::string pluginGetDownloadName();
std::string pluginGetLoginStatus();
Plugin *pluginGetPlugin(std::string pluginSlug);
Model *pluginGetModel(std::string pluginSlug, std::string modelSlug);


extern std::list<Plugin*> gPlugins;
extern std::string gToken;


} // namespace rack


////////////////////
// Implemented by plugin
////////////////////

/** Called once to initialize and return the Plugin instance.
You must implement this in your plugin
*/
extern "C"
void init(rack::Plugin *plugin);

+ 41
- 0
include/plugin/Model.hpp View File

@@ -0,0 +1,41 @@
#pragma once
#include "common.hpp"
#include "plugin/Plugin.hpp"
#include "tags.hpp"
#include <list>


namespace rack {


struct ModuleWidget;
struct Module;


struct Model {
Plugin *plugin = NULL;
/** An identifier for the model, e.g. "VCO". Used for saving patches.
The model slug must be unique in your plugin, but it doesn't need to be unique among different plugins.
*/
std::string slug;
/** Human readable name for your model, e.g. "Voltage Controlled Oscillator" */
std::string name;
/** The author name of the module.
This might be different than the plugin slug. For example, if you create multiple plugins but want them to be branded similarly, you may use the same author in multiple plugins.
You may even have multiple authors in one plugin, although this property will be moved to Plugin for Rack 1.0.
*/
std::string author;
/** List of tags representing the function(s) of the module (optional) */
std::list<ModelTag> tags;

virtual ~Model() {}
/** Creates a headless Module */
virtual Module *createModule() { return NULL; }
/** Creates a ModuleWidget with a Module attached */
virtual ModuleWidget *createModuleWidget() { return NULL; }
/** Creates a ModuleWidget with no Module, useful for previews */
virtual ModuleWidget *createModuleWidgetNull() { return NULL; }
};


} // namespace rack

+ 41
- 0
include/plugin/Plugin.hpp View File

@@ -0,0 +1,41 @@
#pragma once
#include "common.hpp"
#include <list>


namespace rack {


struct Model;


// Subclass this and return a pointer to a new one when init() is called
struct Plugin {
/** A list of the models available by this plugin, add with addModel() */
std::list<Model*> models;
/** The file path of the plugin's directory */
std::string path;
/** OS-dependent library handle */
void *handle = NULL;

/** Must be unique. Used for patch files and the VCV store API.
To guarantee uniqueness, it is a good idea to prefix the slug by your "company name" if available, e.g. "MyCompany-MyPlugin"
*/
std::string slug;

/** The version of your plugin
Plugins should follow the versioning scheme described at https://github.com/VCVRack/Rack/issues/266
Do not include the "v" in "v1.0" for example.
*/
std::string version;

/** Deprecated, do not use. */
std::string website;
std::string manual;

virtual ~Plugin();
void addModel(Model *model);
};


} // namespace rack

+ 46
- 0
include/plugin/PluginManager.hpp View File

@@ -0,0 +1,46 @@
#pragma once
#include "common.hpp"
#include "plugin/Plugin.hpp"
#include "plugin/Model.hpp"
#include <list>


namespace rack {


struct PluginManager {
std::list<Plugin*> plugins;
std::string token;

bool isDownloading = false;
float downloadProgress = 0.f;
std::string downloadName;
std::string loginStatus;

PluginManager(bool devMode);
~PluginManager();
void logIn(std::string email, std::string password);
void logOut();
/** Returns whether a new plugin is available, and downloads it unless doing a dry run */
bool sync(bool dryRun);
void cancelDownload();
bool isLoggedIn();
Plugin *getPlugin(std::string pluginSlug);
Model *getModel(std::string pluginSlug, std::string modelSlug);
};

extern PluginManager *gPluginManager;


} // namespace rack


////////////////////
// Implemented by plugin
////////////////////

/** Called once to initialize and return the Plugin instance.
You must implement this in your plugin
*/
extern "C"
void init(rack::Plugin *plugin);

+ 9
- 0
include/plugin/callbacks.hpp View File

@@ -0,0 +1,9 @@
#pragma once
#include "plugin/Plugin.hpp"


/** Called once to initialize and return the Plugin instance.
You must implement this in your plugin
*/
extern "C"
void init(rack::Plugin *plugin);

+ 4
- 1
include/rack.hpp View File

@@ -8,7 +8,6 @@
#include "random.hpp" #include "random.hpp"
#include "network.hpp" #include "network.hpp"
#include "asset.hpp" #include "asset.hpp"
#include "plugin.hpp"
#include "window.hpp" #include "window.hpp"
#include "helpers.hpp" #include "helpers.hpp"


@@ -77,3 +76,7 @@
#include "engine/Output.hpp" #include "engine/Output.hpp"
#include "engine/Param.hpp" #include "engine/Param.hpp"
#include "engine/Wire.hpp" #include "engine/Wire.hpp"

#include "plugin/Plugin.hpp"
#include "plugin/Model.hpp"
#include "plugin/callbacks.hpp"

+ 4
- 4
src/app/ModuleBrowser.cpp View File

@@ -1,6 +1,5 @@
#include <set> #include <set>
#include <algorithm> #include <algorithm>
#include "plugin.hpp"
#include "window.hpp" #include "window.hpp"
#include "helpers.hpp" #include "helpers.hpp"
#include "event.hpp" #include "event.hpp"
@@ -11,6 +10,7 @@
#include "app/Scene.hpp" #include "app/Scene.hpp"
#include "ui/List.hpp" #include "ui/List.hpp"
#include "ui/TextField.hpp" #include "ui/TextField.hpp"
#include "plugin/PluginManager.hpp"




static const float itemMargin = 2.0; static const float itemMargin = 2.0;
@@ -322,7 +322,7 @@ struct ModuleBrowser : OpaqueWidget {
addChild(moduleScroll); addChild(moduleScroll);


// Collect authors // Collect authors
for (Plugin *plugin : gPlugins) {
for (Plugin *plugin : gPluginManager->plugins) {
for (Model *model : plugin->models) { for (Model *model : plugin->models) {
// Insert author // Insert author
if (!model->author.empty()) if (!model->author.empty())
@@ -427,7 +427,7 @@ struct ModuleBrowser : OpaqueWidget {
moduleList->addChild(item); moduleList->addChild(item);
} }
// Modules // Modules
for (Plugin *plugin : gPlugins) {
for (Plugin *plugin : gPluginManager->plugins) {
for (Model *model : plugin->models) { for (Model *model : plugin->models) {
if (isModelFiltered(model) && isModelMatch(model, search)) { if (isModelFiltered(model) && isModelMatch(model, search)) {
ModelItem *item = new ModelItem; ModelItem *item = new ModelItem;
@@ -587,7 +587,7 @@ void moduleBrowserFromJson(json_t *rootJ) {
continue; continue;
std::string pluginSlug = json_string_value(pluginJ); std::string pluginSlug = json_string_value(pluginJ);
std::string modelSlug = json_string_value(modelJ); std::string modelSlug = json_string_value(modelJ);
Model *model = pluginGetModel(pluginSlug, modelSlug);
Model *model = gPluginManager->getModel(pluginSlug, modelSlug);
if (!model) if (!model)
continue; continue;
sFavoriteModels.insert(model); sFavoriteModels.insert(model);


+ 13
- 11
src/app/PluginManagerWidget.cpp View File

@@ -7,7 +7,7 @@
#include "ui/TextField.hpp" #include "ui/TextField.hpp"
#include "ui/PasswordField.hpp" #include "ui/PasswordField.hpp"
#include "ui/Label.hpp" #include "ui/Label.hpp"
#include "plugin.hpp"
#include "plugin/PluginManager.hpp"
#include "window.hpp" #include "window.hpp"
#include "helpers.hpp" #include "helpers.hpp"
#include "osdialog.h" #include "osdialog.h"
@@ -30,7 +30,9 @@ struct LogInButton : Button {
TextField *emailField; TextField *emailField;
TextField *passwordField; TextField *passwordField;
void onAction(event::Action &e) override { void onAction(event::Action &e) override {
std::thread t(pluginLogIn, emailField->text, passwordField->text);
std::thread t([&]() {
gPluginManager->logIn(emailField->text, passwordField->text);
});
t.detach(); t.detach();
passwordField->text = ""; passwordField->text = "";
} }
@@ -39,7 +41,7 @@ struct LogInButton : Button {


struct StatusLabel : Label { struct StatusLabel : Label {
void step() override { void step() override {
text = pluginGetLoginStatus();
text = gPluginManager->loginStatus;
} }
}; };


@@ -65,7 +67,7 @@ struct SyncButton : Button {
// Check for plugin update on first step() // Check for plugin update on first step()
if (!checked) { if (!checked) {
std::thread t([this]() { std::thread t([this]() {
if (pluginSync(true))
if (gPluginManager->sync(true))
available = true; available = true;
}); });
t.detach(); t.detach();
@@ -94,7 +96,7 @@ struct SyncButton : Button {
void onAction(event::Action &e) override { void onAction(event::Action &e) override {
available = false; available = false;
std::thread t([this]() { std::thread t([this]() {
if (pluginSync(false))
if (gPluginManager->sync(false))
completed = true; completed = true;
}); });
t.detach(); t.detach();
@@ -104,14 +106,14 @@ struct SyncButton : Button {


struct LogOutButton : Button { struct LogOutButton : Button {
void onAction(event::Action &e) override { void onAction(event::Action &e) override {
pluginLogOut();
gPluginManager->logOut();
} }
}; };




struct DownloadQuantity : Quantity { struct DownloadQuantity : Quantity {
float getValue() override { float getValue() override {
return pluginGetDownloadProgress();
return gPluginManager->downloadProgress;
} }


float getDisplayValue() override { float getDisplayValue() override {
@@ -121,7 +123,7 @@ struct DownloadQuantity : Quantity {
int getDisplayPrecision() override {return 0;} int getDisplayPrecision() override {return 0;}


std::string getLabel() override { std::string getLabel() override {
return "Downloading " + pluginGetDownloadName();
return "Downloading " + gPluginManager->downloadName;
} }


std::string getUnit() override {return "%";} std::string getUnit() override {return "%";}
@@ -137,7 +139,7 @@ struct DownloadProgressBar : ProgressBar {


struct CancelButton : Button { struct CancelButton : Button {
void onAction(event::Action &e) override { void onAction(event::Action &e) override {
pluginCancelDownload();
gPluginManager->cancelDownload();
} }
}; };


@@ -224,9 +226,9 @@ void PluginManagerWidget::step() {
manageWidget->visible = false; manageWidget->visible = false;
downloadWidget->visible = false; downloadWidget->visible = false;


if (pluginIsDownloading())
if (gPluginManager->isDownloading)
downloadWidget->visible = true; downloadWidget->visible = true;
else if (pluginIsLoggedIn())
else if (gPluginManager->isLoggedIn())
manageWidget->visible = true; manageWidget->visible = true;
else else
loginWidget->visible = true; loginWidget->visible = true;


+ 2
- 1
src/app/RackWidget.cpp View File

@@ -9,6 +9,7 @@
#include "asset.hpp" #include "asset.hpp"
#include "system.hpp" #include "system.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "plugin/PluginManager.hpp"




namespace rack { namespace rack {
@@ -377,7 +378,7 @@ ModuleWidget *RackWidget::moduleFromJson(json_t *moduleJ) {
std::string modelSlug = json_string_value(modelSlugJ); std::string modelSlug = json_string_value(modelSlugJ);


// Get Model // Get Model
Model *model = pluginGetModel(pluginSlug, modelSlug);
Model *model = gPluginManager->getModel(pluginSlug, modelSlug);
if (!model) if (!model)
return NULL; return NULL;




+ 6
- 2
src/main.cpp View File

@@ -10,6 +10,8 @@
#include "settings.hpp" #include "settings.hpp"
#include "engine/Engine.hpp" #include "engine/Engine.hpp"
#include "app/Scene.hpp" #include "app/Scene.hpp"
#include "tags.hpp"
#include "plugin/PluginManager.hpp"


#ifdef ARCH_WIN #ifdef ARCH_WIN
#include <Windows.h> #include <Windows.h>
@@ -67,7 +69,8 @@ int main(int argc, char *argv[]) {
INFO("Local directory: %s", asset::local("").c_str()); INFO("Local directory: %s", asset::local("").c_str());


// Initialize app // Initialize app
pluginInit(devMode);
tagsInit();
gPluginManager = new PluginManager(devMode);
gEngine = new Engine; gEngine = new Engine;
rtmidiInit(); rtmidiInit();
bridgeInit(); bridgeInit();
@@ -118,7 +121,8 @@ int main(int argc, char *argv[]) {
delete gEngine; delete gEngine;
gEngine = NULL; gEngine = NULL;
midiDestroy(); midiDestroy();
pluginDestroy();
delete gPluginManager;
gPluginManager = NULL;
logger::destroy(); logger::destroy();


return 0; return 0;


+ 21
- 0
src/plugin/Plugin.cpp View File

@@ -0,0 +1,21 @@
#include "plugin/Plugin.hpp"
#include "plugin/Model.hpp"


namespace rack {


Plugin::~Plugin() {
for (Model *model : models) {
delete model;
}
}

void Plugin::addModel(Model *model) {
assert(!model->plugin);
model->plugin = this;
models.push_back(model);
}


} // namespace rack

src/plugin.cpp → src/plugin/PluginManager.cpp View File

@@ -19,7 +19,7 @@
#endif #endif
#include <dirent.h> #include <dirent.h>


#include "plugin.hpp"
#include "plugin/PluginManager.hpp"
#include "system.hpp" #include "system.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "network.hpp" #include "network.hpp"
@@ -32,33 +32,11 @@
namespace rack { namespace rack {




std::list<Plugin*> gPlugins;
std::string gToken;


static bool isDownloading = false;
static float downloadProgress = 0.0;
static std::string downloadName;
static std::string loginStatus;


Plugin::~Plugin() {
for (Model *model : models) {
delete model;
}
}

void Plugin::addModel(Model *model) {
assert(!model->plugin);
model->plugin = this;
models.push_back(model);
}

//////////////////// ////////////////////
// private API // private API
//////////////////// ////////////////////


static bool loadPlugin(std::string path) {
static bool PluginManager_loadPlugin(PluginManager *pluginManager, std::string path) {
std::string libraryFilename; std::string libraryFilename;
#if ARCH_LIN #if ARCH_LIN
libraryFilename = path + "/" + "plugin.so"; libraryFilename = path + "/" + "plugin.so";
@@ -112,7 +90,7 @@ static bool loadPlugin(std::string path) {
initCallback(plugin); initCallback(plugin);


// Reject plugin if slug already exists // Reject plugin if slug already exists
Plugin *oldPlugin = pluginGetPlugin(plugin->slug);
Plugin *oldPlugin = pluginManager->getPlugin(plugin->slug);
if (oldPlugin) { if (oldPlugin) {
WARN("Plugin \"%s\" is already loaded, not attempting to load it again", plugin->slug.c_str()); WARN("Plugin \"%s\" is already loaded, not attempting to load it again", plugin->slug.c_str());
// TODO // TODO
@@ -121,13 +99,13 @@ static bool loadPlugin(std::string path) {
} }


// Add plugin to list // Add plugin to list
gPlugins.push_back(plugin);
pluginManager->plugins.push_back(plugin);
INFO("Loaded plugin %s %s from %s", plugin->slug.c_str(), plugin->version.c_str(), libraryFilename.c_str()); INFO("Loaded plugin %s %s from %s", plugin->slug.c_str(), plugin->version.c_str(), libraryFilename.c_str());


return true; return true;
} }


static bool syncPlugin(std::string slug, json_t *manifestJ, bool dryRun) {
static bool PluginManager_syncPlugin(PluginManager *pluginManager, std::string slug, json_t *manifestJ, bool dryRun) {
// Check that "status" is "available" // Check that "status" is "available"
json_t *statusJ = json_object_get(manifestJ, "status"); json_t *statusJ = json_object_get(manifestJ, "status");
if (!statusJ) { if (!statusJ) {
@@ -147,7 +125,7 @@ static bool syncPlugin(std::string slug, json_t *manifestJ, bool dryRun) {
std::string latestVersion = json_string_value(latestVersionJ); std::string latestVersion = json_string_value(latestVersionJ);


// Check whether we already have a plugin with the same slug and version // Check whether we already have a plugin with the same slug and version
Plugin *plugin = pluginGetPlugin(slug);
Plugin *plugin = pluginManager->getPlugin(slug);
if (plugin && plugin->version == latestVersion) { if (plugin && plugin->version == latestVersion) {
return false; return false;
} }
@@ -175,7 +153,7 @@ static bool syncPlugin(std::string slug, json_t *manifestJ, bool dryRun) {
if (dryRun) { if (dryRun) {
downloadUrl += "/available"; downloadUrl += "/available";
} }
downloadUrl += "?token=" + network::encodeUrl(gToken);
downloadUrl += "?token=" + network::encodeUrl(pluginManager->token);
downloadUrl += "&slug=" + network::encodeUrl(slug); downloadUrl += "&slug=" + network::encodeUrl(slug);
downloadUrl += "&version=" + network::encodeUrl(latestVersion); downloadUrl += "&version=" + network::encodeUrl(latestVersion);
downloadUrl += "&arch=" + network::encodeUrl(arch); downloadUrl += "&arch=" + network::encodeUrl(arch);
@@ -194,28 +172,28 @@ static bool syncPlugin(std::string slug, json_t *manifestJ, bool dryRun) {
return json_boolean_value(successJ); return json_boolean_value(successJ);
} }
else { else {
downloadName = name;
downloadProgress = 0.0;
pluginManager->downloadName = name;
pluginManager->downloadProgress = 0.0;
INFO("Downloading plugin %s %s %s", slug.c_str(), latestVersion.c_str(), arch.c_str()); INFO("Downloading plugin %s %s %s", slug.c_str(), latestVersion.c_str(), arch.c_str());


// Download zip // Download zip
std::string pluginDest = asset::local("plugins/" + slug + ".zip"); std::string pluginDest = asset::local("plugins/" + slug + ".zip");
if (!network::requestDownload(downloadUrl, pluginDest, &downloadProgress)) {
if (!network::requestDownload(downloadUrl, pluginDest, &pluginManager->downloadProgress)) {
WARN("Plugin %s download was unsuccessful", slug.c_str()); WARN("Plugin %s download was unsuccessful", slug.c_str());
return false; return false;
} }


downloadName = "";
pluginManager->downloadName = "";
return true; return true;
} }
} }


static void loadPlugins(std::string path) {
static void PluginManager_loadPlugins(PluginManager *pluginManager, std::string path) {
std::string message; std::string message;
for (std::string pluginPath : system::listEntries(path)) { for (std::string pluginPath : system::listEntries(path)) {
if (!system::isDirectory(pluginPath)) if (!system::isDirectory(pluginPath))
continue; continue;
if (!loadPlugin(pluginPath)) {
if (!PluginManager_loadPlugin(pluginManager, pluginPath)) {
message += string::f("Could not load plugin %s\n", pluginPath.c_str()); message += string::f("Could not load plugin %s\n", pluginPath.c_str());
} }
} }
@@ -321,14 +299,12 @@ static void extractPackages(std::string path) {
// public API // public API
//////////////////// ////////////////////


void pluginInit(bool devMode) {
tagsInit();

PluginManager::PluginManager(bool devMode) {
// Load core // Load core
// This function is defined in core.cpp // This function is defined in core.cpp
Plugin *corePlugin = new Plugin; Plugin *corePlugin = new Plugin;
init(corePlugin); init(corePlugin);
gPlugins.push_back(corePlugin);
plugins.push_back(corePlugin);


// Get local plugins directory // Get local plugins directory
std::string localPlugins = asset::local("plugins"); std::string localPlugins = asset::local("plugins");
@@ -346,15 +322,15 @@ void pluginInit(bool devMode) {


// Extract packages and load plugins // Extract packages and load plugins
extractPackages(localPlugins); extractPackages(localPlugins);
loadPlugins(localPlugins);
PluginManager_loadPlugins(this, localPlugins);
} }


void pluginDestroy() {
for (Plugin *plugin : gPlugins) {
PluginManager::~PluginManager() {
for (Plugin *plugin : plugins) {
// Free library handle // Free library handle
#if ARCH_WIN #if ARCH_WIN
if (plugin->handle) if (plugin->handle)
FreeLibrary((HINSTANCE)plugin->handle);
FreeLibrary((HINSTANCE) plugin->handle);
#else #else
if (plugin->handle) if (plugin->handle)
dlclose(plugin->handle); dlclose(plugin->handle);
@@ -364,11 +340,40 @@ void pluginDestroy() {
// It might be best to let them leak anyway, because "crash on exit" issues would occur with badly-written plugins. // It might be best to let them leak anyway, because "crash on exit" issues would occur with badly-written plugins.
// delete plugin; // delete plugin;
} }
gPlugins.clear();
plugins.clear();
}

void PluginManager::logIn(std::string email, std::string password) {
json_t *reqJ = json_object();
json_object_set(reqJ, "email", json_string(email.c_str()));
json_object_set(reqJ, "password", json_string(password.c_str()));
json_t *resJ = network::requestJson(network::METHOD_POST, API_HOST + "/token", reqJ);
json_decref(reqJ);

if (resJ) {
json_t *errorJ = json_object_get(resJ, "error");
if (errorJ) {
const char *errorStr = json_string_value(errorJ);
loginStatus = errorStr;
}
else {
json_t *tokenJ = json_object_get(resJ, "token");
if (tokenJ) {
const char *tokenStr = json_string_value(tokenJ);
token = tokenStr;
loginStatus = "";
}
}
json_decref(resJ);
}
}

void PluginManager::logOut() {
token = "";
} }


bool pluginSync(bool dryRun) {
if (gToken.empty())
bool PluginManager::sync(bool dryRun) {
if (token.empty())
return false; return false;


bool available = false; bool available = false;
@@ -384,7 +389,7 @@ bool pluginSync(bool dryRun) {


// Get user's plugins list // Get user's plugins list
json_t *pluginsReqJ = json_object(); json_t *pluginsReqJ = json_object();
json_object_set(pluginsReqJ, "token", json_string(gToken.c_str()));
json_object_set(pluginsReqJ, "token", json_string(token.c_str()));
json_t *pluginsResJ = network::requestJson(network::METHOD_GET, API_HOST + "/plugins", pluginsReqJ); json_t *pluginsResJ = network::requestJson(network::METHOD_GET, API_HOST + "/plugins", pluginsReqJ);
json_decref(pluginsReqJ); json_decref(pluginsReqJ);
if (!pluginsResJ) { if (!pluginsResJ) {
@@ -438,7 +443,7 @@ bool pluginSync(bool dryRun) {
if (!manifestJ) if (!manifestJ)
continue; continue;


if (syncPlugin(slug, manifestJ, dryRun)) {
if (PluginManager_syncPlugin(this, slug, manifestJ, dryRun)) {
available = true; available = true;
} }
} }
@@ -446,61 +451,16 @@ bool pluginSync(bool dryRun) {
return available; return available;
} }


void pluginLogIn(std::string email, std::string password) {
json_t *reqJ = json_object();
json_object_set(reqJ, "email", json_string(email.c_str()));
json_object_set(reqJ, "password", json_string(password.c_str()));
json_t *resJ = network::requestJson(network::METHOD_POST, API_HOST + "/token", reqJ);
json_decref(reqJ);

if (resJ) {
json_t *errorJ = json_object_get(resJ, "error");
if (errorJ) {
const char *errorStr = json_string_value(errorJ);
loginStatus = errorStr;
}
else {
json_t *tokenJ = json_object_get(resJ, "token");
if (tokenJ) {
const char *tokenStr = json_string_value(tokenJ);
gToken = tokenStr;
loginStatus = "";
}
}
json_decref(resJ);
}
}

void pluginLogOut() {
gToken = "";
}

void pluginCancelDownload() {
void PluginManager::cancelDownload() {
// TODO // TODO
} }


bool pluginIsLoggedIn() {
return gToken != "";
}

bool pluginIsDownloading() {
return isDownloading;
bool PluginManager::isLoggedIn() {
return token != "";
} }


float pluginGetDownloadProgress() {
return downloadProgress;
}

std::string pluginGetDownloadName() {
return downloadName;
}

std::string pluginGetLoginStatus() {
return loginStatus;
}

Plugin *pluginGetPlugin(std::string pluginSlug) {
for (Plugin *plugin : gPlugins) {
Plugin *PluginManager::getPlugin(std::string pluginSlug) {
for (Plugin *plugin : plugins) {
if (plugin->slug == pluginSlug) { if (plugin->slug == pluginSlug) {
return plugin; return plugin;
} }
@@ -508,8 +468,8 @@ Plugin *pluginGetPlugin(std::string pluginSlug) {
return NULL; return NULL;
} }


Model *pluginGetModel(std::string pluginSlug, std::string modelSlug) {
Plugin *plugin = pluginGetPlugin(pluginSlug);
Model *PluginManager::getModel(std::string pluginSlug, std::string modelSlug) {
Plugin *plugin = getPlugin(pluginSlug);
if (plugin) { if (plugin) {
for (Model *model : plugin->models) { for (Model *model : plugin->models) {
if (model->slug == modelSlug) { if (model->slug == modelSlug) {
@@ -521,4 +481,7 @@ Model *pluginGetModel(std::string pluginSlug, std::string modelSlug) {
} }




PluginManager *gPluginManager = NULL;


} // namespace rack } // namespace rack

+ 3
- 3
src/settings.cpp View File

@@ -1,7 +1,7 @@
#include "settings.hpp" #include "settings.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "window.hpp" #include "window.hpp"
#include "plugin.hpp"
#include "plugin/PluginManager.hpp"
#include "app/Scene.hpp" #include "app/Scene.hpp"
#include "app/ModuleBrowser.hpp" #include "app/ModuleBrowser.hpp"
#include "engine/Engine.hpp" #include "engine/Engine.hpp"
@@ -20,7 +20,7 @@ static json_t *settingsToJson() {
json_t *rootJ = json_object(); json_t *rootJ = json_object();


// token // token
json_t *tokenJ = json_string(gToken.c_str());
json_t *tokenJ = json_string(gPluginManager->token.c_str());
json_object_set_new(rootJ, "token", tokenJ); json_object_set_new(rootJ, "token", tokenJ);


if (!windowIsMaximized()) { if (!windowIsMaximized()) {
@@ -83,7 +83,7 @@ static void settingsFromJson(json_t *rootJ) {
// token // token
json_t *tokenJ = json_object_get(rootJ, "token"); json_t *tokenJ = json_object_get(rootJ, "token");
if (tokenJ) if (tokenJ)
gToken = json_string_value(tokenJ);
gPluginManager->token = json_string_value(tokenJ);


// windowSize // windowSize
json_t *windowSizeJ = json_object_get(rootJ, "windowSize"); json_t *windowSizeJ = json_object_get(rootJ, "windowSize");


Loading…
Cancel
Save