| @@ -1,6 +1,6 @@ | |||
| RACK_DIR ?= . | |||
| # VERSION := 1.dev.$(shell git rev-parse --short HEAD) | |||
| VERSION := 1.1.0 | |||
| VERSION := 1.dev.$(shell git rev-parse --short HEAD) | |||
| # VERSION := 1.1.0 | |||
| FLAGS += -DVERSION=$(VERSION) | |||
| FLAGS += -Iinclude -Idep/include | |||
| @@ -12,15 +12,17 @@ namespace rack { | |||
| namespace app { | |||
| extern std::string APP_NAME; | |||
| extern std::string APP_VERSION; | |||
| extern std::string APP_VERSION_UPDATE; | |||
| extern std::string API_URL; | |||
| extern std::string API_VERSION; | |||
| extern std::string ABI_VERSION; | |||
| extern const std::string APP_NAME; | |||
| extern const std::string APP_VERSION; | |||
| extern const std::string APP_ARCH; | |||
| static const float SVG_DPI = 75.0; | |||
| static const float MM_PER_IN = 25.4; | |||
| extern const std::string ABI_VERSION; | |||
| extern const std::string API_URL; | |||
| extern const std::string API_VERSION; | |||
| static const float SVG_DPI = 75.f; | |||
| static const float MM_PER_IN = 25.4f; | |||
| /** Converts inch measurements to pixels */ | |||
| @@ -50,8 +52,5 @@ static const math::Vec RACK_OFFSET = RACK_GRID_SIZE.mult(math::Vec(2000, 100)); | |||
| static const math::Vec BUS_BOARD_GRID_SIZE = math::Vec(RACK_GRID_WIDTH * 20, RACK_GRID_HEIGHT); | |||
| void init(); | |||
| } // namespace app | |||
| } // namespace rack | |||
| @@ -0,0 +1,26 @@ | |||
| #pragma once | |||
| #include <common.hpp> | |||
| namespace rack { | |||
| /** Automatically updates the application. | |||
| */ | |||
| namespace updater { | |||
| extern std::string version; | |||
| extern std::string changelogUrl; | |||
| extern float progress; | |||
| void init(); | |||
| bool isUpdateAvailable(); | |||
| /** Updates Rack automatically or opens the browser to the URL. | |||
| Blocking. Call on a detached thread. | |||
| */ | |||
| void update(); | |||
| } // namespace updater | |||
| } // namespace rack | |||
| @@ -15,6 +15,7 @@ | |||
| #include <system.hpp> | |||
| #include <plugin.hpp> | |||
| #include <patch.hpp> | |||
| #include <updater.hpp> | |||
| #include <osdialog.h> | |||
| #include <thread> | |||
| @@ -61,6 +62,16 @@ struct UrlItem : ui::MenuItem { | |||
| } | |||
| }; | |||
| struct FolderItem : ui::MenuItem { | |||
| std::string path; | |||
| void onAction(const event::Action &e) override { | |||
| std::thread t([=] { | |||
| system::openFolder(path); | |||
| }); | |||
| t.detach(); | |||
| } | |||
| }; | |||
| //////////////////// | |||
| // File | |||
| //////////////////// | |||
| @@ -701,15 +712,35 @@ struct LibraryButton : MenuButton { | |||
| // Help | |||
| //////////////////// | |||
| struct UserFolderItem : ui::MenuItem { | |||
| struct UpdateItem : ui::MenuItem { | |||
| ui::Menu *createChildMenu() override { | |||
| ui::Menu *menu = new ui::Menu; | |||
| UrlItem *changelogUrl = new UrlItem; | |||
| changelogUrl->text = "Changelog"; | |||
| changelogUrl->url = updater::changelogUrl; | |||
| menu->addChild(changelogUrl); | |||
| return menu; | |||
| } | |||
| void step() override { | |||
| if (updater::progress > 0) { | |||
| rightText = string::f("%.0f%%", updater::progress * 100.f); | |||
| } | |||
| MenuItem::step(); | |||
| } | |||
| void onAction(const event::Action &e) override { | |||
| std::thread t([] { | |||
| system::openFolder(asset::user("")); | |||
| std::thread t([=] { | |||
| updater::update(); | |||
| }); | |||
| t.detach(); | |||
| e.consume(NULL); | |||
| } | |||
| }; | |||
| struct HelpButton : MenuButton { | |||
| NotificationIcon *notification; | |||
| @@ -723,11 +754,10 @@ struct HelpButton : MenuButton { | |||
| menu->box.pos = getAbsoluteOffset(math::Vec(0, box.size.y)); | |||
| menu->box.size.x = box.size.x; | |||
| if (hasUpdate()) { | |||
| UrlItem *updateItem = new UrlItem; | |||
| if (updater::isUpdateAvailable()) { | |||
| UpdateItem *updateItem = new UpdateItem; | |||
| updateItem->text = "Update " + APP_NAME; | |||
| updateItem->rightText = APP_VERSION + " → " + APP_VERSION_UPDATE; | |||
| updateItem->url = "https://vcvrack.com/"; | |||
| updateItem->rightText = APP_VERSION + " → " + updater::version; | |||
| menu->addChild(updateItem); | |||
| } | |||
| @@ -742,20 +772,17 @@ struct HelpButton : MenuButton { | |||
| websiteItem->url = "https://vcvrack.com/"; | |||
| menu->addChild(websiteItem); | |||
| UserFolderItem *folderItem = new UserFolderItem; | |||
| FolderItem *folderItem = new FolderItem; | |||
| folderItem->text = "Open user folder"; | |||
| folderItem->path = asset::user(""); | |||
| menu->addChild(folderItem); | |||
| } | |||
| void step() override { | |||
| notification->box.pos = math::Vec(0, 0); | |||
| notification->visible = hasUpdate(); | |||
| notification->visible = updater::isUpdateAvailable(); | |||
| MenuButton::step(); | |||
| } | |||
| bool hasUpdate() { | |||
| return !APP_VERSION_UPDATE.empty() && APP_VERSION_UPDATE != APP_VERSION; | |||
| } | |||
| }; | |||
| //////////////////// | |||
| @@ -1,45 +1,24 @@ | |||
| #include <app/common.hpp> | |||
| #include <settings.hpp> | |||
| #include <network.hpp> | |||
| #include <thread> | |||
| namespace rack { | |||
| namespace app { | |||
| std::string APP_NAME = "VCV Rack"; | |||
| std::string APP_VERSION = TOSTRING(VERSION); | |||
| std::string APP_VERSION_UPDATE; | |||
| std::string API_URL = "https://api.vcvrack.com"; | |||
| std::string API_VERSION = "1"; | |||
| std::string ABI_VERSION = "1"; | |||
| static void checkVersion() { | |||
| std::string versionUrl = app::API_URL + "/version"; | |||
| json_t *versionResJ = network::requestJson(network::METHOD_GET, versionUrl, NULL); | |||
| if (!versionResJ) { | |||
| WARN("Request for version failed"); | |||
| return; | |||
| } | |||
| DEFER({ | |||
| json_decref(versionResJ); | |||
| }); | |||
| json_t *versionJ = json_object_get(versionResJ, "version"); | |||
| if (versionJ) | |||
| APP_VERSION_UPDATE = json_string_value(versionJ); | |||
| } | |||
| void init() { | |||
| if (!settings::devMode) { | |||
| std::thread t([] { | |||
| checkVersion(); | |||
| }); | |||
| t.detach(); | |||
| } | |||
| } | |||
| const std::string APP_NAME = "VCV Rack"; | |||
| const std::string APP_VERSION = TOSTRING(VERSION); | |||
| #if defined ARCH_WIN | |||
| const std::string APP_ARCH = "win"; | |||
| #elif ARCH_MAC | |||
| const std::string APP_ARCH = "mac"; | |||
| #elif defined ARCH_LIN | |||
| const std::string APP_ARCH = "lin"; | |||
| #endif | |||
| const std::string ABI_VERSION = "1"; | |||
| const std::string API_URL = "https://api.vcvrack.com"; | |||
| const std::string API_VERSION = "1"; | |||
| } // namespace app | |||
| @@ -16,6 +16,7 @@ | |||
| #include <ui.hpp> | |||
| #include <system.hpp> | |||
| #include <string.hpp> | |||
| #include <updater.hpp> | |||
| #include <osdialog.h> | |||
| #include <thread> | |||
| @@ -150,7 +151,7 @@ int main(int argc, char *argv[]) { | |||
| keyboard::init(); | |||
| gamepad::init(); | |||
| plugin::init(); | |||
| app::init(); | |||
| updater::init(); | |||
| if (!settings::headless) { | |||
| ui::init(); | |||
| windowInit(); | |||
| @@ -476,21 +476,13 @@ void syncUpdate(Update *update) { | |||
| isSyncingUpdate = false; | |||
| }); | |||
| #if defined ARCH_WIN | |||
| std::string arch = "win"; | |||
| #elif ARCH_MAC | |||
| std::string arch = "mac"; | |||
| #elif defined ARCH_LIN | |||
| std::string arch = "lin"; | |||
| #endif | |||
| std::string downloadUrl = app::API_URL + "/download"; | |||
| downloadUrl += "?token=" + network::encodeUrl(settings::token); | |||
| downloadUrl += "&slug=" + network::encodeUrl(update->pluginSlug); | |||
| downloadUrl += "&version=" + network::encodeUrl(update->version); | |||
| downloadUrl += "&arch=" + network::encodeUrl(arch); | |||
| downloadUrl += "&arch=" + network::encodeUrl(app::APP_ARCH); | |||
| INFO("Downloading plugin %s %s %s", update->pluginSlug.c_str(), update->version.c_str(), arch.c_str()); | |||
| INFO("Downloading plugin %s %s %s", update->pluginSlug.c_str(), update->version.c_str(), app::APP_ARCH.c_str()); | |||
| // Download zip | |||
| std::string pluginDest = asset::pluginsPath + "/" + update->pluginSlug + ".zip"; | |||
| @@ -0,0 +1,83 @@ | |||
| #include <updater.hpp> | |||
| #include <settings.hpp> | |||
| #include <app/common.hpp> | |||
| #include <network.hpp> | |||
| #include <system.hpp> | |||
| #include <app.hpp> | |||
| #include <window.hpp> | |||
| #include <thread> | |||
| namespace rack { | |||
| namespace updater { | |||
| std::string version; | |||
| std::string changelogUrl; | |||
| float progress = 0.f; | |||
| static std::string downloadUrl; | |||
| static void checkVersion() { | |||
| std::string versionUrl = app::API_URL + "/version"; | |||
| json_t *resJ = network::requestJson(network::METHOD_GET, versionUrl, NULL); | |||
| if (!resJ) { | |||
| WARN("Request for version failed"); | |||
| return; | |||
| } | |||
| DEFER({ | |||
| json_decref(resJ); | |||
| }); | |||
| json_t *versionJ = json_object_get(resJ, "version"); | |||
| if (versionJ) | |||
| version = json_string_value(versionJ); | |||
| json_t *changelogUrlJ = json_object_get(resJ, "changelogUrl"); | |||
| if (changelogUrlJ) | |||
| changelogUrl = json_string_value(changelogUrlJ); | |||
| json_t *downloadUrlsJ = json_object_get(resJ, "downloadUrls"); | |||
| if (downloadUrlsJ) { | |||
| json_t *downloadUrlJ = json_object_get(downloadUrlsJ, app::APP_ARCH.c_str()); | |||
| if (downloadUrlJ) | |||
| downloadUrl = json_string_value(downloadUrlJ); | |||
| } | |||
| } | |||
| void init() { | |||
| if (!settings::devMode) { | |||
| std::thread t([] { | |||
| checkVersion(); | |||
| }); | |||
| t.detach(); | |||
| } | |||
| } | |||
| void update() { | |||
| if (downloadUrl == "") | |||
| return; | |||
| #if defined ARCH_WIN | |||
| // Download and launch the installer on Windows | |||
| std::string path = asset::user("Rack-setup.exe"); | |||
| network::requestDownload(downloadUrl, path, &progress); | |||
| system::runProcessDetached(path); | |||
| #else | |||
| // Open the browser on Mac and Linux. The user will know what to do. | |||
| system::openBrowser(downloadUrl); | |||
| #endif | |||
| APP->window->close(); | |||
| } | |||
| bool isUpdateAvailable() { | |||
| return (version != "") && (version != app::APP_VERSION); | |||
| } | |||
| } // namespace updater | |||
| } // namespace rack | |||