/* * Carla Plugin Thread * Copyright (C) 2012-2013 Filipe Coelho * * 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 2 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 GPL.txt file */ #include "CarlaPluginThread.hpp" #include "CarlaPlugin.hpp" #include "CarlaEngine.hpp" #include CARLA_BACKEND_START_NAMESPACE const char* PluginThreadMode2str(const CarlaPluginThread::Mode mode) { switch (mode) { case CarlaPluginThread::PLUGIN_THREAD_NULL: return "PLUGIN_THREAD_NULL"; case CarlaPluginThread::PLUGIN_THREAD_DSSI_GUI: return "PLUGIN_THREAD_DSSI_GUI"; case CarlaPluginThread::PLUGIN_THREAD_LV2_GUI: return "PLUGIN_THREAD_LV2_GUI"; case CarlaPluginThread::PLUGIN_THREAD_VST_GUI: return "PLUGIN_THREAD_VST_GUI"; case CarlaPluginThread::PLUGIN_THREAD_BRIDGE: return "PLUGIN_THREAD_BRIDGE"; } carla_stderr("CarlaPluginThread::PluginThreadMode2str(%i) - invalid mode", mode); return nullptr; } CarlaPluginThread::CarlaPluginThread(CarlaBackend::CarlaEngine* const engine, CarlaBackend::CarlaPlugin* const plugin, const Mode mode) : kEngine(engine), kPlugin(plugin), fMode(mode), fProcess(nullptr) { carla_debug("CarlaPluginThread::CarlaPluginThread(plugin:\"%s\", engine:\"%s\", %s)", plugin->name(), engine->getName(), PluginThreadMode2str(mode)); } CarlaPluginThread::~CarlaPluginThread() { if (fProcess != nullptr) delete fProcess; } void CarlaPluginThread::setMode(const CarlaPluginThread::Mode mode) { fMode = mode; } void CarlaPluginThread::setOscData(const char* const binary, const char* const label, const char* const extra) { fBinary = binary; fLabel = label; fExtra = extra; } void CarlaPluginThread::run() { carla_debug("CarlaPluginThread::run()"); if (fProcess == nullptr) { fProcess = new QProcess(nullptr); fProcess->setProcessChannelMode(QProcess::ForwardedChannels); #ifndef BUILD_BRIDGE //fProcess->setProcessEnvironment(kEngine->getOptionsAsProcessEnvironment()); #endif } QString name(kPlugin->name() ? kPlugin->name() : "(none)"); QStringList arguments; switch (fMode) { case PLUGIN_THREAD_NULL: break; case PLUGIN_THREAD_DSSI_GUI: /* osc_url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathUDP()).arg(kPlugin->id()); /* filename */ arguments << kPlugin->filename(); /* label */ arguments << (const char*)fLabel; /* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name()); break; case PLUGIN_THREAD_LV2_GUI: /* osc_url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathTCP()).arg(kPlugin->id()); /* URI */ arguments << (const char*)fLabel; /* ui-URI */ arguments << (const char*)fExtra; /* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name()); break; case PLUGIN_THREAD_VST_GUI: /* osc_url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathTCP()).arg(kPlugin->id()); /* filename */ arguments << kPlugin->filename(); /* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name()); break; case PLUGIN_THREAD_BRIDGE: /* osc_url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathTCP()).arg(kPlugin->id()); /* stype */ arguments << (const char*)fExtra; /* filename */ arguments << kPlugin->filename(); /* name */ arguments << name; /* label */ arguments << (const char*)fLabel; break; } fProcess->start((const char*)fBinary, arguments); fProcess->waitForStarted(); switch (fMode) { case PLUGIN_THREAD_NULL: break; case PLUGIN_THREAD_DSSI_GUI: case PLUGIN_THREAD_LV2_GUI: case PLUGIN_THREAD_VST_GUI: if (kPlugin->waitForOscGuiShow()) { fProcess->waitForFinished(-1); if (fProcess->exitCode() == 0) { // Hide kEngine->callback(CarlaBackend::CALLBACK_SHOW_GUI, kPlugin->id(), 0, 0, 0.0f, nullptr); carla_stdout("CarlaPluginThread::run() - GUI closed"); } else { // Kill kEngine->callback(CarlaBackend::CALLBACK_SHOW_GUI, kPlugin->id(), -1, 0, 0.0f, nullptr); carla_stderr("CarlaPluginThread::run() - GUI crashed"); } } else { carla_debug("CarlaPluginThread::run() - GUI timeout"); kEngine->callback(CarlaBackend::CALLBACK_SHOW_GUI, kPlugin->id(), 0, 0, 0.0f, nullptr); } break; case PLUGIN_THREAD_BRIDGE: fProcess->waitForFinished(-1); if (fProcess->exitCode() != 0) { carla_stderr("CarlaPluginThread::run() - bridge crashed"); CarlaString errorString("Plugin '" + CarlaString(kPlugin->name()) + "' has crashed!\n" "Saving now will lose its current settings.\n" "Please remove this plugin, and not rely on it from this point."); kEngine->callback(CarlaBackend::CALLBACK_ERROR, kPlugin->id(), 0, 0, 0.0f, (const char*)errorString); } break; } } CARLA_BACKEND_END_NAMESPACE