Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
5.5KB

  1. /*
  2. * Carla Plugin Thread
  3. * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the GPL.txt file
  16. */
  17. #include "carla_plugin_internal.hpp"
  18. #include <QtCore/QProcess>
  19. CARLA_BACKEND_START_NAMESPACE
  20. const char* PluginThreadMode2str(const CarlaPluginThread::PluginThreadMode mode)
  21. {
  22. switch (mode)
  23. {
  24. case CarlaPluginThread::PLUGIN_THREAD_DSSI_GUI:
  25. return "PLUGIN_THREAD_DSSI_GUI";
  26. case CarlaPluginThread::PLUGIN_THREAD_LV2_GUI:
  27. return "PLUGIN_THREAD_LV2_GUI";
  28. case CarlaPluginThread::PLUGIN_THREAD_VST_GUI:
  29. return "PLUGIN_THREAD_VST_GUI";
  30. case CarlaPluginThread::PLUGIN_THREAD_BRIDGE:
  31. return "PLUGIN_THREAD_BRIDGE";
  32. }
  33. qWarning("CarlaPluginThread::PluginThreadMode2str(%i) - invalid mode", mode);
  34. return nullptr;
  35. }
  36. CarlaPluginThread::CarlaPluginThread(CarlaBackend::CarlaEngine* const engine, CarlaBackend::CarlaPlugin* const plugin, const PluginThreadMode mode, QObject* const parent)
  37. : QThread(parent),
  38. kEngine(engine),
  39. kPlugin(plugin),
  40. kMode(mode)
  41. {
  42. qDebug("CarlaPluginThread::CarlaPluginThread(plugin:\"%s\", engine:\"%s\", %s)", plugin->name(), engine->getName(), PluginThreadMode2str(mode));
  43. fProcess = nullptr;
  44. }
  45. CarlaPluginThread::~CarlaPluginThread()
  46. {
  47. if (fProcess != nullptr)
  48. delete fProcess;
  49. }
  50. void CarlaPluginThread::setOscData(const char* const binary, const char* const label, const char* const data1)
  51. {
  52. fBinary = binary;
  53. fLabel = label;
  54. fData1 = data1;
  55. }
  56. void CarlaPluginThread::run()
  57. {
  58. qDebug("CarlaPluginThread::run()");
  59. if (fProcess == nullptr)
  60. {
  61. fProcess = new QProcess(nullptr);
  62. fProcess->setProcessChannelMode(QProcess::ForwardedChannels);
  63. #ifndef BUILD_BRIDGE
  64. fProcess->setProcessEnvironment(kEngine->getOptionsAsProcessEnvironment());
  65. #endif
  66. }
  67. QString name(kPlugin->name() ? kPlugin->name() : "(none)");
  68. QStringList arguments;
  69. switch (kMode)
  70. {
  71. case PLUGIN_THREAD_DSSI_GUI:
  72. /* osc_url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathUDP()).arg(kPlugin->id());
  73. /* filename */ arguments << kPlugin->filename();
  74. /* label */ arguments << (const char*)fLabel;
  75. /* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name());
  76. break;
  77. case PLUGIN_THREAD_LV2_GUI:
  78. /* osc_url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathTCP()).arg(kPlugin->id());
  79. /* URI */ arguments << (const char*)fLabel;
  80. /* ui-URI */ arguments << (const char*)fData1;
  81. /* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name());
  82. break;
  83. case PLUGIN_THREAD_VST_GUI:
  84. /* osc_url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathTCP()).arg(kPlugin->id());
  85. /* filename */ arguments << kPlugin->filename();
  86. /* ui-title */ arguments << QString("%1 (GUI)").arg(kPlugin->name());
  87. break;
  88. case PLUGIN_THREAD_BRIDGE:
  89. /* osc_url */ arguments << QString("%1/%2").arg(kEngine->getOscServerPathTCP()).arg(kPlugin->id());
  90. /* stype */ arguments << (const char*)fData1;
  91. /* filename */ arguments << kPlugin->filename();
  92. /* name */ arguments << name;
  93. /* label */ arguments << (const char*)fLabel;
  94. break;
  95. }
  96. fProcess->start((const char*)fBinary, arguments);
  97. fProcess->waitForStarted();
  98. switch (kMode)
  99. {
  100. case PLUGIN_THREAD_DSSI_GUI:
  101. case PLUGIN_THREAD_LV2_GUI:
  102. case PLUGIN_THREAD_VST_GUI:
  103. if (kPlugin->waitForOscGuiShow())
  104. {
  105. fProcess->waitForFinished(-1);
  106. if (fProcess->exitCode() == 0)
  107. {
  108. // Hide
  109. kEngine->callback(CarlaBackend::CALLBACK_SHOW_GUI, kPlugin->id(), 0, 0, 0.0, nullptr);
  110. qWarning("CarlaPluginThread::run() - GUI closed");
  111. }
  112. else
  113. {
  114. // Kill
  115. kEngine->callback(CarlaBackend::CALLBACK_SHOW_GUI, kPlugin->id(), -1, 0, 0.0, nullptr);
  116. qWarning("CarlaPluginThread::run() - GUI crashed");
  117. break;
  118. }
  119. }
  120. else
  121. {
  122. qDebug("CarlaPluginThread::run() - GUI timeout");
  123. kEngine->callback(CarlaBackend::CALLBACK_SHOW_GUI, kPlugin->id(), 0, 0, 0.0, nullptr);
  124. }
  125. break;
  126. case PLUGIN_THREAD_BRIDGE:
  127. fProcess->waitForFinished(-1);
  128. if (fProcess->exitCode() != 0)
  129. {
  130. qWarning("CarlaPluginThread::run() - bridge crashed");
  131. QString errorString = QString("Plugin '%1' has crashed!\n"
  132. "Saving now will lose its current settings.\n"
  133. "Please remove this plugin, and not rely on it from this point.").arg(kPlugin->name());
  134. kEngine->setLastError(errorString.toUtf8().constData());
  135. kEngine->callback(CarlaBackend::CALLBACK_ERROR, kPlugin->id(), 0, 0, 0.0, nullptr);
  136. }
  137. break;
  138. }
  139. }
  140. CARLA_BACKEND_END_NAMESPACE