305 lines
9.7 KiB
C++
305 lines
9.7 KiB
C++
/*
|
|
* DISTRHO Cardinal Plugin
|
|
* Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 3 of
|
|
* the License, or any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* For a full copy of the GNU General Public License see the LICENSE file.
|
|
*/
|
|
|
|
#include "Application.hpp"
|
|
#include "Window.hpp"
|
|
#include "RemoteUI.hpp"
|
|
|
|
#include <asset.hpp>
|
|
#include <patch.hpp>
|
|
#include <random.hpp>
|
|
#include <settings.hpp>
|
|
#include <system.hpp>
|
|
|
|
#include <app/Browser.hpp>
|
|
#include <app/Scene.hpp>
|
|
#include <engine/Engine.hpp>
|
|
#include <ui/common.hpp>
|
|
|
|
#include "PluginContext.hpp"
|
|
#include "extra/ScopedValueSetter.hpp"
|
|
|
|
#define CARDINAL_TEMPLATE_NAME "init/main.vcv"
|
|
|
|
extern const std::string CARDINAL_VERSION;
|
|
|
|
namespace rack {
|
|
namespace asset {
|
|
std::string patchesPath();
|
|
void destroy();
|
|
}
|
|
namespace engine {
|
|
void Engine_setAboutToClose(Engine*);
|
|
}
|
|
namespace plugin {
|
|
void initStaticPlugins();
|
|
void destroyStaticPlugins();
|
|
}
|
|
}
|
|
|
|
START_NAMESPACE_DISTRHO
|
|
|
|
bool isUsingNativeAudio() noexcept { return false; }
|
|
bool supportsAudioInput() { return false; }
|
|
bool supportsBufferSizeChanges() { return false; }
|
|
bool supportsMIDI() { return false; }
|
|
bool isAudioInputEnabled() { return false; }
|
|
bool isMIDIEnabled() { return false; }
|
|
uint getBufferSize() { return 0; }
|
|
bool requestAudioInput() { return false; }
|
|
bool requestBufferSizeChange(uint) { return false; }
|
|
bool requestMIDI() { return false; }
|
|
const char* getPluginFormatName() noexcept { return "Remote"; }
|
|
|
|
FileBrowserHandle fileBrowserCreate(bool, ulong, double, const FileBrowserOptions&) { return nullptr; }
|
|
|
|
uint32_t Plugin::getBufferSize() const noexcept { return 128; }
|
|
double Plugin::getSampleRate() const noexcept { return 48000; }
|
|
bool Plugin::writeMidiEvent(const MidiEvent&) noexcept { return false; }
|
|
|
|
void UI::editParameter(uint, bool) {}
|
|
void UI::setParameterValue(uint, float) {}
|
|
void UI::setState(const char*, const char*) {}
|
|
bool UI::openFileBrowser(const FileBrowserOptions&) { return false; }
|
|
|
|
END_NAMESPACE_DISTRHO
|
|
|
|
int main(const int argc, const char* argv[])
|
|
{
|
|
using namespace rack;
|
|
|
|
std::string templatePath, factoryTemplatePath;
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
#ifdef DISTRHO_OS_WASM
|
|
settings::allowCursorLock = true;
|
|
#else
|
|
settings::allowCursorLock = false;
|
|
#endif
|
|
settings::autoCheckUpdates = false;
|
|
settings::autosaveInterval = 0;
|
|
settings::devMode = true;
|
|
settings::isPlugin = true;
|
|
settings::skipLoadOnLaunch = true;
|
|
settings::showTipsOnLaunch = false;
|
|
settings::windowPos = math::Vec(0, 0);
|
|
|
|
// copied from https://community.vcvrack.com/t/16-colour-cable-palette/15951
|
|
settings::cableColors = {
|
|
color::fromHexString("#ff5252"),
|
|
color::fromHexString("#ff9352"),
|
|
color::fromHexString("#ffd452"),
|
|
color::fromHexString("#e8ff52"),
|
|
color::fromHexString("#a8ff52"),
|
|
color::fromHexString("#67ff52"),
|
|
color::fromHexString("#52ff7d"),
|
|
color::fromHexString("#52ffbe"),
|
|
color::fromHexString("#52ffff"),
|
|
color::fromHexString("#52beff"),
|
|
color::fromHexString("#527dff"),
|
|
color::fromHexString("#6752ff"),
|
|
color::fromHexString("#a852ff"),
|
|
color::fromHexString("#e952ff"),
|
|
color::fromHexString("#ff52d4"),
|
|
color::fromHexString("#ff5293"),
|
|
};
|
|
|
|
system::init();
|
|
logger::init();
|
|
random::init();
|
|
ui::init();
|
|
|
|
#ifdef CARDINAL_PLUGIN_SOURCE_DIR
|
|
// Make system dir point to source code location as fallback
|
|
asset::systemDir = CARDINAL_PLUGIN_SOURCE_DIR DISTRHO_OS_SEP_STR "Rack";
|
|
asset::bundlePath.clear();
|
|
|
|
// If source code dir does not exist use install target prefix as system dir
|
|
if (!system::exists(system::join(asset::systemDir, "res")))
|
|
#endif
|
|
{
|
|
#if defined(DISTRHO_OS_WASM)
|
|
asset::systemDir = "/resources";
|
|
#elif defined(ARCH_MAC)
|
|
asset::systemDir = "/Library/Application Support/Cardinal";
|
|
#elif defined(ARCH_WIN)
|
|
const std::string commonprogfiles = getSpecialPath(kSpecialPathCommonProgramFiles);
|
|
if (! commonprogfiles.empty())
|
|
asset::systemDir = system::join(commonprogfiles, "Cardinal");
|
|
#else
|
|
asset::systemDir = CARDINAL_PLUGIN_PREFIX "/share/cardinal";
|
|
#endif
|
|
|
|
asset::bundlePath = system::join(asset::systemDir, "PluginManifests");
|
|
}
|
|
|
|
asset::userDir = asset::systemDir;
|
|
|
|
const std::string patchesPath = asset::patchesPath();
|
|
#ifdef DISTRHO_OS_WASM
|
|
templatePath = system::join(patchesPath, CARDINAL_WASM_WELCOME_TEMPLATE_FILENAME);
|
|
#else
|
|
templatePath = system::join(patchesPath, CARDINAL_TEMPLATE_NAME);
|
|
#endif
|
|
factoryTemplatePath = system::join(patchesPath, CARDINAL_TEMPLATE_NAME);
|
|
|
|
// Log environment
|
|
INFO("%s %s %s, compatible with Rack version %s", APP_NAME.c_str(), APP_EDITION.c_str(), CARDINAL_VERSION.c_str(), APP_VERSION.c_str());
|
|
INFO("%s", system::getOperatingSystemInfo().c_str());
|
|
INFO("System directory: %s", asset::systemDir.c_str());
|
|
INFO("User directory: %s", asset::userDir.c_str());
|
|
INFO("Template patch: %s", templatePath.c_str());
|
|
INFO("System template patch: %s", factoryTemplatePath.c_str());
|
|
|
|
// Report to user if something is wrong with the installation
|
|
if (asset::systemDir.empty())
|
|
{
|
|
d_stderr2("Failed to locate Cardinal plugin bundle.\n"
|
|
"Install Cardinal with its bundle folder intact and try again.");
|
|
}
|
|
else if (! system::exists(asset::systemDir))
|
|
{
|
|
d_stderr2("System directory \"%s\" does not exist.\n"
|
|
"Make sure Cardinal was downloaded and installed correctly.", asset::systemDir.c_str());
|
|
}
|
|
|
|
INFO("Initializing plugins");
|
|
plugin::initStaticPlugins();
|
|
|
|
INFO("Initializing plugin browser DB");
|
|
app::browserInit();
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// create unique temporary path for this instance
|
|
std::string fAutosavePath;
|
|
|
|
try {
|
|
char uidBuf[24];
|
|
const std::string tmp = rack::system::getTempDirectory();
|
|
|
|
for (int i=1;; ++i)
|
|
{
|
|
std::snprintf(uidBuf, sizeof(uidBuf), "Cardinal.%04d", i);
|
|
const std::string trypath = rack::system::join(tmp, uidBuf);
|
|
|
|
if (! rack::system::exists(trypath))
|
|
{
|
|
if (rack::system::createDirectories(trypath))
|
|
fAutosavePath = trypath;
|
|
break;
|
|
}
|
|
}
|
|
} DISTRHO_SAFE_EXCEPTION("create unique temporary path");
|
|
|
|
CardinalPluginContext* const context = new CardinalPluginContext(nullptr);
|
|
rack::contextSet(context);
|
|
|
|
const float sampleRate = 48000;
|
|
rack::settings::sampleRate = sampleRate;
|
|
|
|
context->bufferSize = 512;
|
|
context->sampleRate = sampleRate;
|
|
|
|
context->engine = new rack::engine::Engine;
|
|
context->engine->setSampleRate(sampleRate);
|
|
|
|
context->history = new rack::history::State;
|
|
context->patch = new rack::patch::Manager;
|
|
context->patch->autosavePath = fAutosavePath;
|
|
context->patch->templatePath = templatePath;
|
|
context->patch->factoryTemplatePath = factoryTemplatePath;
|
|
|
|
context->event = new rack::widget::EventState;
|
|
context->scene = new rack::app::Scene;
|
|
context->event->rootWidget = context->scene;
|
|
|
|
context->window = new rack::window::Window;
|
|
|
|
context->patch->loadTemplate();
|
|
context->scene->rackScroll->reset();
|
|
// swap to factory template after first load
|
|
context->patch->templatePath = context->patch->factoryTemplatePath;
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
Application app;
|
|
Window window(app);
|
|
window.setIgnoringKeyRepeat(true);
|
|
window.setResizable(true);
|
|
window.setTitle("CardinalRemote");
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
const double scaleFactor = window.getScaleFactor();
|
|
|
|
window.setGeometryConstraints(648 * scaleFactor, 538 * scaleFactor);
|
|
|
|
if (scaleFactor != 1.0)
|
|
window.setSize(DISTRHO_UI_DEFAULT_WIDTH * scaleFactor,
|
|
DISTRHO_UI_DEFAULT_HEIGHT * scaleFactor);
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
ScopedPointer<CardinalRemoteUI> remoteUI;
|
|
|
|
{
|
|
const Window::ScopedGraphicsContext sgc(window);
|
|
remoteUI = new CardinalRemoteUI(window, templatePath);
|
|
}
|
|
|
|
window.show();
|
|
app.exec();
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
{
|
|
context->patch->clear();
|
|
|
|
// do a little dance to prevent context scene deletion from saving to temp dir
|
|
const ScopedValueSetter<bool> svs(rack::settings::headless, true);
|
|
Engine_setAboutToClose(context->engine);
|
|
delete context;
|
|
}
|
|
|
|
if (! fAutosavePath.empty())
|
|
rack::system::removeRecursively(fAutosavePath);
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
INFO("Clearing asset paths");
|
|
asset::bundlePath.clear();
|
|
asset::systemDir.clear();
|
|
asset::userDir.clear();
|
|
|
|
INFO("Destroying plugins");
|
|
plugin::destroyStaticPlugins();
|
|
|
|
INFO("Destroying colourized assets");
|
|
asset::destroy();
|
|
|
|
INFO("Destroying settings");
|
|
settings::destroy();
|
|
|
|
INFO("Destroying logger");
|
|
logger::destroy();
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
return 0;
|
|
}
|