Browse Source

Un-class-ify plugin

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
f1e4f08d0c
11 changed files with 118 additions and 121 deletions
  1. +2
    -2
      include/asset.hpp
  2. +0
    -2
      include/context.hpp
  3. +33
    -0
      include/plugin.hpp
  4. +0
    -44
      include/plugin/PluginManager.hpp
  5. +4
    -4
      src/app/ModuleBrowser.cpp
  6. +11
    -11
      src/app/PluginManagerWidget.cpp
  7. +2
    -2
      src/app/RackWidget.cpp
  8. +19
    -19
      src/asset.cpp
  9. +7
    -8
      src/main.cpp
  10. +37
    -26
      src/plugin.cpp
  11. +3
    -3
      src/settings.cpp

+ 2
- 2
include/asset.hpp View File

@@ -18,8 +18,8 @@ std::string user(std::string filename);
std::string plugin(Plugin *plugin, std::string filename);


extern std::string gSystemDir;
extern std::string gUserDir;
extern std::string systemDir;
extern std::string userDir;


} // namespace asset


+ 0
- 2
include/context.hpp View File

@@ -11,7 +11,6 @@ namespace event {

struct Scene;
struct Engine;
struct PluginManager;
struct Window;


@@ -19,7 +18,6 @@ struct Context {
event::Context *event = NULL;
Scene *scene = NULL;
Engine *engine = NULL;
PluginManager *plugin = NULL;
Window *window = NULL;
};



+ 33
- 0
include/plugin.hpp View File

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


namespace rack {
namespace plugin {


void init(bool devMode);
void destroy();
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 std::list<Plugin*> plugins;
extern std::string token;
extern bool isDownloading;
extern float downloadProgress;
extern std::string downloadName;
extern std::string loginStatus;


} // namespace plugin
} // namespace rack

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

@@ -1,44 +0,0 @@
#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);
};


} // 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);

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

@@ -10,7 +10,7 @@
#include "app/Scene.hpp"
#include "ui/List.hpp"
#include "ui/TextField.hpp"
#include "plugin/PluginManager.hpp"
#include "plugin.hpp"
#include "context.hpp"


@@ -323,7 +323,7 @@ struct ModuleBrowser : OpaqueWidget {
addChild(moduleScroll);

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


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

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

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

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

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


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

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

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

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

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

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

if (context()->plugin->isDownloading)
if (plugin::isDownloading)
downloadWidget->visible = true;
else if (context()->plugin->isLoggedIn())
else if (plugin::isLoggedIn())
manageWidget->visible = true;
else
loginWidget->visible = true;


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

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


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

// Get Model
Model *model = context()->plugin->getModel(pluginSlug, modelSlug);
Model *model = plugin::getModel(pluginSlug, modelSlug);
if (!model)
return NULL;



+ 19
- 19
src/asset.cpp View File

@@ -26,9 +26,9 @@ namespace asset {

void init(bool devMode) {
// Get system dir
if (gSystemDir.empty()) {
if (systemDir.empty()) {
if (devMode) {
gSystemDir = ".";
systemDir = ".";
}
else {
#if ARCH_MAC
@@ -39,26 +39,26 @@ void init(bool devMode) {
Boolean success = CFURLGetFileSystemRepresentation(resourcesUrl, TRUE, (UInt8*) resourcesBuf, sizeof(resourcesBuf));
assert(success);
CFRelease(resourcesUrl);
gSystemDir = resourcesBuf;
systemDir = resourcesBuf;
#endif
#if ARCH_WIN
char moduleBuf[MAX_PATH];
DWORD length = GetModuleFileName(NULL, moduleBuf, sizeof(moduleBuf));
assert(length > 0);
PathRemoveFileSpec(moduleBuf);
gSystemDir = moduleBuf;
systemDir = moduleBuf;
#endif
#if ARCH_LIN
// TODO For now, users should launch Rack from their terminal in the system directory
gSystemDir = ".";
systemDir = ".";
#endif
}
}

// Get user dir
if (gUserDir.empty()) {
if (userDir.empty()) {
if (devMode) {
gUserDir = ".";
userDir = ".";
}
else {
#if ARCH_WIN
@@ -66,15 +66,15 @@ void init(bool devMode) {
char documentsBuf[MAX_PATH];
HRESULT result = SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, documentsBuf);
assert(result == S_OK);
gUserDir = documentsBuf;
gUserDir += "/Rack";
userDir = documentsBuf;
userDir += "/Rack";
#endif
#if ARCH_MAC
// Get home directory
struct passwd *pw = getpwuid(getuid());
assert(pw);
gUserDir = pw->pw_dir;
gUserDir += "/Documents/Rack";
userDir = pw->pw_dir;
userDir += "/Documents/Rack";
#endif
#if ARCH_LIN
// Get home directory
@@ -84,24 +84,24 @@ void init(bool devMode) {
assert(pw);
homeBuf = pw->pw_dir;
}
gUserDir = homeBuf;
gUserDir += "/.Rack";
userDir = homeBuf;
userDir += "/.Rack";
#endif
}
}

system::createDirectory(gSystemDir);
system::createDirectory(gUserDir);
system::createDirectory(systemDir);
system::createDirectory(userDir);
}


std::string system(std::string filename) {
return gSystemDir + "/" + filename;
return systemDir + "/" + filename;
}


std::string user(std::string filename) {
return gUserDir + "/" + filename;
return userDir + "/" + filename;
}


@@ -111,8 +111,8 @@ std::string plugin(Plugin *plugin, std::string filename) {
}


std::string gSystemDir;
std::string gUserDir;
std::string systemDir;
std::string userDir;


} // namespace asset


+ 7
- 8
src/main.cpp View File

@@ -10,7 +10,7 @@
#include "engine/Engine.hpp"
#include "app/Scene.hpp"
#include "tags.hpp"
#include "plugin/PluginManager.hpp"
#include "plugin.hpp"
#include "context.hpp"
#include "ui.hpp"

@@ -48,10 +48,10 @@ int main(int argc, char *argv[]) {
devMode = true;
} break;
case 's': {
asset::gSystemDir = optarg;
asset::systemDir = optarg;
} break;
case 'u': {
asset::gUserDir = optarg;
asset::userDir = optarg;
} break;
default: break;
}
@@ -70,16 +70,16 @@ int main(int argc, char *argv[]) {
keyboard::init();
gamepad::init();
uiInit();
plugin::init(devMode);

// Log environment
INFO("%s %s", APP_NAME.c_str(), APP_VERSION.c_str());
if (devMode)
INFO("Development mode");
INFO("System directory: %s", asset::gSystemDir.c_str());
INFO("User directory: %s", asset::gUserDir.c_str());
INFO("System directory: %s", asset::systemDir.c_str());
INFO("User directory: %s", asset::userDir.c_str());

// Initialize app
context()->plugin = new PluginManager(devMode);
context()->engine = new Engine;
context()->event = new event::Context;
context()->scene = new Scene;
@@ -125,10 +125,9 @@ int main(int argc, char *argv[]) {
context()->window = NULL;
delete context()->engine;
context()->engine = NULL;
delete context()->plugin;
context()->plugin = NULL;

// Destroy environment
plugin::destroy();
uiDestroy();
bridgeDestroy();
midiDestroy();


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

@@ -1,4 +1,4 @@
#include "plugin/PluginManager.hpp"
#include "plugin.hpp"
#include "system.hpp"
#include "logger.hpp"
#include "network.hpp"
@@ -6,6 +6,7 @@
#include "string.hpp"
#include "context.hpp"
#include "app/common.hpp"
#include "plugin/callbacks.hpp"

#include <unistd.h>
#include <sys/types.h>
@@ -31,13 +32,14 @@


namespace rack {
namespace plugin {


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

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

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

// Add plugin to list
pluginManager->plugins.push_back(plugin);
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 PluginManager_syncPlugin(PluginManager *pluginManager, std::string slug, json_t *manifestJ, bool dryRun) {
static bool syncPlugin(std::string slug, json_t *manifestJ, bool dryRun) {
// Check that "status" is "available"
json_t *statusJ = json_object_get(manifestJ, "status");
if (!statusJ) {
@@ -126,7 +128,7 @@ static bool PluginManager_syncPlugin(PluginManager *pluginManager, std::string s
std::string latestVersion = json_string_value(latestVersionJ);

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

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

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

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

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

// Get user plugins directory
std::string userPlugins = asset::user("plugins");
mkdir(userPlugins.c_str(), 0755);

if (devMode) {
if (!devMode) {
// Copy Fundamental package to plugins directory if folder does not exist
std::string fundamentalSrc = asset::system("Fundamental.zip");
std::string fundamentalDest = asset::user("plugins/Fundamental.zip");
@@ -323,10 +325,10 @@ PluginManager::PluginManager(bool devMode) {

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

PluginManager::~PluginManager() {
void destroy() {
for (Plugin *plugin : plugins) {
// Free library handle
#if ARCH_WIN
@@ -344,7 +346,7 @@ PluginManager::~PluginManager() {
plugins.clear();
}

void PluginManager::logIn(std::string email, std::string password) {
void 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()));
@@ -369,11 +371,11 @@ void PluginManager::logIn(std::string email, std::string password) {
}
}

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

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

@@ -444,7 +446,7 @@ bool PluginManager::sync(bool dryRun) {
if (!manifestJ)
continue;

if (PluginManager_syncPlugin(this, slug, manifestJ, dryRun)) {
if (syncPlugin(slug, manifestJ, dryRun)) {
available = true;
}
}
@@ -452,15 +454,15 @@ bool PluginManager::sync(bool dryRun) {
return available;
}

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

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

Plugin *PluginManager::getPlugin(std::string pluginSlug) {
Plugin *getPlugin(std::string pluginSlug) {
for (Plugin *plugin : plugins) {
if (plugin->slug == pluginSlug) {
return plugin;
@@ -469,7 +471,7 @@ Plugin *PluginManager::getPlugin(std::string pluginSlug) {
return NULL;
}

Model *PluginManager::getModel(std::string pluginSlug, std::string modelSlug) {
Model *getModel(std::string pluginSlug, std::string modelSlug) {
Plugin *plugin = getPlugin(pluginSlug);
if (plugin) {
for (Model *model : plugin->models) {
@@ -482,4 +484,13 @@ Model *PluginManager::getModel(std::string pluginSlug, std::string modelSlug) {
}


std::list<Plugin*> plugins;
std::string token;
bool isDownloading = false;
float downloadProgress = 0.f;
std::string downloadName;
std::string loginStatus;


} // namespace plugin
} // namespace rack

+ 3
- 3
src/settings.cpp View File

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

// token
json_t *tokenJ = json_string(context()->plugin->token.c_str());
json_t *tokenJ = json_string(plugin::token.c_str());
json_object_set_new(rootJ, "token", tokenJ);

if (!context()->window->isMaximized()) {
@@ -84,7 +84,7 @@ static void settingsFromJson(json_t *rootJ) {
// token
json_t *tokenJ = json_object_get(rootJ, "token");
if (tokenJ)
context()->plugin->token = json_string_value(tokenJ);
plugin::token = json_string_value(tokenJ);

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


Loading…
Cancel
Save