@@ -5,7 +5,7 @@ | |||
#include "app/SVGPanel.hpp" | |||
#include "app/Port.hpp" | |||
#include "app/ParamWidget.hpp" | |||
#include "plugin.hpp" | |||
#include "plugin/Model.hpp" | |||
#include "engine/Module.hpp" | |||
@@ -1,6 +1,6 @@ | |||
#pragma once | |||
#include "common.hpp" | |||
#include "plugin.hpp" | |||
#include "plugin/Plugin.hpp" | |||
namespace rack { | |||
@@ -1,4 +1,4 @@ | |||
#include "plugin.hpp" | |||
#include "plugin/Model.hpp" | |||
#include "event.hpp" | |||
#include "ui/MenuLabel.hpp" | |||
#include "ui/MenuItem.hpp" | |||
@@ -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); |
@@ -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 |
@@ -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 |
@@ -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); |
@@ -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); |
@@ -8,7 +8,6 @@ | |||
#include "random.hpp" | |||
#include "network.hpp" | |||
#include "asset.hpp" | |||
#include "plugin.hpp" | |||
#include "window.hpp" | |||
#include "helpers.hpp" | |||
@@ -77,3 +76,7 @@ | |||
#include "engine/Output.hpp" | |||
#include "engine/Param.hpp" | |||
#include "engine/Wire.hpp" | |||
#include "plugin/Plugin.hpp" | |||
#include "plugin/Model.hpp" | |||
#include "plugin/callbacks.hpp" |
@@ -1,6 +1,5 @@ | |||
#include <set> | |||
#include <algorithm> | |||
#include "plugin.hpp" | |||
#include "window.hpp" | |||
#include "helpers.hpp" | |||
#include "event.hpp" | |||
@@ -11,6 +10,7 @@ | |||
#include "app/Scene.hpp" | |||
#include "ui/List.hpp" | |||
#include "ui/TextField.hpp" | |||
#include "plugin/PluginManager.hpp" | |||
static const float itemMargin = 2.0; | |||
@@ -322,7 +322,7 @@ struct ModuleBrowser : OpaqueWidget { | |||
addChild(moduleScroll); | |||
// Collect authors | |||
for (Plugin *plugin : gPlugins) { | |||
for (Plugin *plugin : gPluginManager->plugins) { | |||
for (Model *model : plugin->models) { | |||
// Insert author | |||
if (!model->author.empty()) | |||
@@ -427,7 +427,7 @@ struct ModuleBrowser : OpaqueWidget { | |||
moduleList->addChild(item); | |||
} | |||
// Modules | |||
for (Plugin *plugin : gPlugins) { | |||
for (Plugin *plugin : gPluginManager->plugins) { | |||
for (Model *model : plugin->models) { | |||
if (isModelFiltered(model) && isModelMatch(model, search)) { | |||
ModelItem *item = new ModelItem; | |||
@@ -587,7 +587,7 @@ void moduleBrowserFromJson(json_t *rootJ) { | |||
continue; | |||
std::string pluginSlug = json_string_value(pluginJ); | |||
std::string modelSlug = json_string_value(modelJ); | |||
Model *model = pluginGetModel(pluginSlug, modelSlug); | |||
Model *model = gPluginManager->getModel(pluginSlug, modelSlug); | |||
if (!model) | |||
continue; | |||
sFavoriteModels.insert(model); | |||
@@ -7,7 +7,7 @@ | |||
#include "ui/TextField.hpp" | |||
#include "ui/PasswordField.hpp" | |||
#include "ui/Label.hpp" | |||
#include "plugin.hpp" | |||
#include "plugin/PluginManager.hpp" | |||
#include "window.hpp" | |||
#include "helpers.hpp" | |||
#include "osdialog.h" | |||
@@ -30,7 +30,9 @@ struct LogInButton : Button { | |||
TextField *emailField; | |||
TextField *passwordField; | |||
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(); | |||
passwordField->text = ""; | |||
} | |||
@@ -39,7 +41,7 @@ struct LogInButton : Button { | |||
struct StatusLabel : Label { | |||
void step() override { | |||
text = pluginGetLoginStatus(); | |||
text = gPluginManager->loginStatus; | |||
} | |||
}; | |||
@@ -65,7 +67,7 @@ struct SyncButton : Button { | |||
// Check for plugin update on first step() | |||
if (!checked) { | |||
std::thread t([this]() { | |||
if (pluginSync(true)) | |||
if (gPluginManager->sync(true)) | |||
available = true; | |||
}); | |||
t.detach(); | |||
@@ -94,7 +96,7 @@ struct SyncButton : Button { | |||
void onAction(event::Action &e) override { | |||
available = false; | |||
std::thread t([this]() { | |||
if (pluginSync(false)) | |||
if (gPluginManager->sync(false)) | |||
completed = true; | |||
}); | |||
t.detach(); | |||
@@ -104,14 +106,14 @@ struct SyncButton : Button { | |||
struct LogOutButton : Button { | |||
void onAction(event::Action &e) override { | |||
pluginLogOut(); | |||
gPluginManager->logOut(); | |||
} | |||
}; | |||
struct DownloadQuantity : Quantity { | |||
float getValue() override { | |||
return pluginGetDownloadProgress(); | |||
return gPluginManager->downloadProgress; | |||
} | |||
float getDisplayValue() override { | |||
@@ -121,7 +123,7 @@ struct DownloadQuantity : Quantity { | |||
int getDisplayPrecision() override {return 0;} | |||
std::string getLabel() override { | |||
return "Downloading " + pluginGetDownloadName(); | |||
return "Downloading " + gPluginManager->downloadName; | |||
} | |||
std::string getUnit() override {return "%";} | |||
@@ -137,7 +139,7 @@ struct DownloadProgressBar : ProgressBar { | |||
struct CancelButton : Button { | |||
void onAction(event::Action &e) override { | |||
pluginCancelDownload(); | |||
gPluginManager->cancelDownload(); | |||
} | |||
}; | |||
@@ -224,9 +226,9 @@ void PluginManagerWidget::step() { | |||
manageWidget->visible = false; | |||
downloadWidget->visible = false; | |||
if (pluginIsDownloading()) | |||
if (gPluginManager->isDownloading) | |||
downloadWidget->visible = true; | |||
else if (pluginIsLoggedIn()) | |||
else if (gPluginManager->isLoggedIn()) | |||
manageWidget->visible = true; | |||
else | |||
loginWidget->visible = true; | |||
@@ -9,6 +9,7 @@ | |||
#include "asset.hpp" | |||
#include "system.hpp" | |||
#include "logger.hpp" | |||
#include "plugin/PluginManager.hpp" | |||
namespace rack { | |||
@@ -377,7 +378,7 @@ ModuleWidget *RackWidget::moduleFromJson(json_t *moduleJ) { | |||
std::string modelSlug = json_string_value(modelSlugJ); | |||
// Get Model | |||
Model *model = pluginGetModel(pluginSlug, modelSlug); | |||
Model *model = gPluginManager->getModel(pluginSlug, modelSlug); | |||
if (!model) | |||
return NULL; | |||
@@ -10,6 +10,8 @@ | |||
#include "settings.hpp" | |||
#include "engine/Engine.hpp" | |||
#include "app/Scene.hpp" | |||
#include "tags.hpp" | |||
#include "plugin/PluginManager.hpp" | |||
#ifdef ARCH_WIN | |||
#include <Windows.h> | |||
@@ -67,7 +69,8 @@ int main(int argc, char *argv[]) { | |||
INFO("Local directory: %s", asset::local("").c_str()); | |||
// Initialize app | |||
pluginInit(devMode); | |||
tagsInit(); | |||
gPluginManager = new PluginManager(devMode); | |||
gEngine = new Engine; | |||
rtmidiInit(); | |||
bridgeInit(); | |||
@@ -118,7 +121,8 @@ int main(int argc, char *argv[]) { | |||
delete gEngine; | |||
gEngine = NULL; | |||
midiDestroy(); | |||
pluginDestroy(); | |||
delete gPluginManager; | |||
gPluginManager = NULL; | |||
logger::destroy(); | |||
return 0; | |||
@@ -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 |
@@ -19,7 +19,7 @@ | |||
#endif | |||
#include <dirent.h> | |||
#include "plugin.hpp" | |||
#include "plugin/PluginManager.hpp" | |||
#include "system.hpp" | |||
#include "logger.hpp" | |||
#include "network.hpp" | |||
@@ -32,33 +32,11 @@ | |||
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 | |||
//////////////////// | |||
static bool loadPlugin(std::string path) { | |||
static bool PluginManager_loadPlugin(PluginManager *pluginManager, std::string path) { | |||
std::string libraryFilename; | |||
#if ARCH_LIN | |||
libraryFilename = path + "/" + "plugin.so"; | |||
@@ -112,7 +90,7 @@ static bool loadPlugin(std::string path) { | |||
initCallback(plugin); | |||
// Reject plugin if slug already exists | |||
Plugin *oldPlugin = pluginGetPlugin(plugin->slug); | |||
Plugin *oldPlugin = pluginManager->getPlugin(plugin->slug); | |||
if (oldPlugin) { | |||
WARN("Plugin \"%s\" is already loaded, not attempting to load it again", plugin->slug.c_str()); | |||
// TODO | |||
@@ -121,13 +99,13 @@ static bool loadPlugin(std::string path) { | |||
} | |||
// 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()); | |||
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" | |||
json_t *statusJ = json_object_get(manifestJ, "status"); | |||
if (!statusJ) { | |||
@@ -147,7 +125,7 @@ static bool syncPlugin(std::string slug, json_t *manifestJ, bool dryRun) { | |||
std::string latestVersion = json_string_value(latestVersionJ); | |||
// 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) { | |||
return false; | |||
} | |||
@@ -175,7 +153,7 @@ static bool syncPlugin(std::string slug, json_t *manifestJ, bool dryRun) { | |||
if (dryRun) { | |||
downloadUrl += "/available"; | |||
} | |||
downloadUrl += "?token=" + network::encodeUrl(gToken); | |||
downloadUrl += "?token=" + network::encodeUrl(pluginManager->token); | |||
downloadUrl += "&slug=" + network::encodeUrl(slug); | |||
downloadUrl += "&version=" + network::encodeUrl(latestVersion); | |||
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); | |||
} | |||
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()); | |||
// Download 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()); | |||
return false; | |||
} | |||
downloadName = ""; | |||
pluginManager->downloadName = ""; | |||
return true; | |||
} | |||
} | |||
static void loadPlugins(std::string path) { | |||
static void PluginManager_loadPlugins(PluginManager *pluginManager, std::string path) { | |||
std::string message; | |||
for (std::string pluginPath : system::listEntries(path)) { | |||
if (!system::isDirectory(pluginPath)) | |||
continue; | |||
if (!loadPlugin(pluginPath)) { | |||
if (!PluginManager_loadPlugin(pluginManager, pluginPath)) { | |||
message += string::f("Could not load plugin %s\n", pluginPath.c_str()); | |||
} | |||
} | |||
@@ -321,14 +299,12 @@ static void extractPackages(std::string path) { | |||
// public API | |||
//////////////////// | |||
void pluginInit(bool devMode) { | |||
tagsInit(); | |||
PluginManager::PluginManager(bool devMode) { | |||
// Load core | |||
// This function is defined in core.cpp | |||
Plugin *corePlugin = new Plugin; | |||
init(corePlugin); | |||
gPlugins.push_back(corePlugin); | |||
plugins.push_back(corePlugin); | |||
// Get local plugins directory | |||
std::string localPlugins = asset::local("plugins"); | |||
@@ -346,15 +322,15 @@ void pluginInit(bool devMode) { | |||
// Extract packages and load plugins | |||
extractPackages(localPlugins); | |||
loadPlugins(localPlugins); | |||
PluginManager_loadPlugins(this, localPlugins); | |||
} | |||
void pluginDestroy() { | |||
for (Plugin *plugin : gPlugins) { | |||
PluginManager::~PluginManager() { | |||
for (Plugin *plugin : plugins) { | |||
// Free library handle | |||
#if ARCH_WIN | |||
if (plugin->handle) | |||
FreeLibrary((HINSTANCE)plugin->handle); | |||
FreeLibrary((HINSTANCE) plugin->handle); | |||
#else | |||
if (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. | |||
// 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; | |||
bool available = false; | |||
@@ -384,7 +389,7 @@ bool pluginSync(bool dryRun) { | |||
// Get user's plugins list | |||
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_decref(pluginsReqJ); | |||
if (!pluginsResJ) { | |||
@@ -438,7 +443,7 @@ bool pluginSync(bool dryRun) { | |||
if (!manifestJ) | |||
continue; | |||
if (syncPlugin(slug, manifestJ, dryRun)) { | |||
if (PluginManager_syncPlugin(this, slug, manifestJ, dryRun)) { | |||
available = true; | |||
} | |||
} | |||
@@ -446,61 +451,16 @@ bool pluginSync(bool dryRun) { | |||
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 | |||
} | |||
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) { | |||
return plugin; | |||
} | |||
@@ -508,8 +468,8 @@ Plugin *pluginGetPlugin(std::string pluginSlug) { | |||
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) { | |||
for (Model *model : plugin->models) { | |||
if (model->slug == modelSlug) { | |||
@@ -521,4 +481,7 @@ Model *pluginGetModel(std::string pluginSlug, std::string modelSlug) { | |||
} | |||
PluginManager *gPluginManager = NULL; | |||
} // namespace rack |
@@ -1,7 +1,7 @@ | |||
#include "settings.hpp" | |||
#include "logger.hpp" | |||
#include "window.hpp" | |||
#include "plugin.hpp" | |||
#include "plugin/PluginManager.hpp" | |||
#include "app/Scene.hpp" | |||
#include "app/ModuleBrowser.hpp" | |||
#include "engine/Engine.hpp" | |||
@@ -20,7 +20,7 @@ static json_t *settingsToJson() { | |||
json_t *rootJ = json_object(); | |||
// 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); | |||
if (!windowIsMaximized()) { | |||
@@ -83,7 +83,7 @@ static void settingsFromJson(json_t *rootJ) { | |||
// token | |||
json_t *tokenJ = json_object_get(rootJ, "token"); | |||
if (tokenJ) | |||
gToken = json_string_value(tokenJ); | |||
gPluginManager->token = json_string_value(tokenJ); | |||
// windowSize | |||
json_t *windowSizeJ = json_object_get(rootJ, "windowSize"); | |||