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.

186 lines
5.8KB

  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 doc/GPL.txt file.
  16. */
  17. #include "CarlaPluginThread.hpp"
  18. #include "CarlaPlugin.hpp"
  19. #include "CarlaEngine.hpp"
  20. using juce::ChildProcess;
  21. using juce::String;
  22. using juce::StringArray;
  23. CARLA_BACKEND_START_NAMESPACE
  24. const char* PluginThreadMode2str(const CarlaPluginThread::Mode mode)
  25. {
  26. switch (mode)
  27. {
  28. case CarlaPluginThread::PLUGIN_THREAD_NULL:
  29. return "PLUGIN_THREAD_NULL";
  30. case CarlaPluginThread::PLUGIN_THREAD_DSSI_GUI:
  31. return "PLUGIN_THREAD_DSSI_GUI";
  32. case CarlaPluginThread::PLUGIN_THREAD_LV2_GUI:
  33. return "PLUGIN_THREAD_LV2_GUI";
  34. case CarlaPluginThread::PLUGIN_THREAD_VST_GUI:
  35. return "PLUGIN_THREAD_VST_GUI";
  36. case CarlaPluginThread::PLUGIN_THREAD_BRIDGE:
  37. return "PLUGIN_THREAD_BRIDGE";
  38. }
  39. carla_stderr("CarlaPluginThread::PluginThreadMode2str(%i) - invalid mode", mode);
  40. return nullptr;
  41. }
  42. CarlaPluginThread::CarlaPluginThread(CarlaBackend::CarlaEngine* const engine, CarlaBackend::CarlaPlugin* const plugin, const Mode mode)
  43. : juce::Thread("CarlaPluginThread"),
  44. fEngine(engine),
  45. fPlugin(plugin),
  46. fMode(mode)
  47. {
  48. carla_debug("CarlaPluginThread::CarlaPluginThread(plugin:\"%s\", engine:\"%s\", %s)", plugin->getName(), engine->getName(), PluginThreadMode2str(mode));
  49. setPriority(5);
  50. }
  51. void CarlaPluginThread::setMode(const CarlaPluginThread::Mode mode)
  52. {
  53. CARLA_ASSERT(! isThreadRunning());
  54. carla_debug("CarlaPluginThread::setMode(%s)", PluginThreadMode2str(mode));
  55. fMode = mode;
  56. }
  57. void CarlaPluginThread::setOscData(const char* const binary, const char* const label, const char* const extra1, const char* const extra2)
  58. {
  59. CARLA_ASSERT(! isThreadRunning());
  60. carla_debug("CarlaPluginThread::setOscData(\"%s\", \"%s\", \"%s\", \"%s\")", binary, label, extra1, extra2);
  61. fBinary = binary;
  62. fLabel = label;
  63. fExtra1 = extra1;
  64. fExtra2 = extra2;
  65. }
  66. void CarlaPluginThread::run()
  67. {
  68. carla_debug("CarlaPluginThread::run()");
  69. ChildProcess process;
  70. StringArray arguments;
  71. arguments.add((const char*)fBinary);
  72. String name(fPlugin->getName());
  73. if (name.isEmpty())
  74. name = "(none)";
  75. switch (fMode)
  76. {
  77. case PLUGIN_THREAD_NULL:
  78. break;
  79. case PLUGIN_THREAD_DSSI_GUI:
  80. /* osc-url */ arguments.add(String(fEngine->getOscServerPathUDP()) + "/" + String(fPlugin->getId()));
  81. /* filename */ arguments.add(fPlugin->getFilename());
  82. /* label */ arguments.add((const char*)fLabel);
  83. /* ui-title */ arguments.add(name + " (GUI)");
  84. break;
  85. case PLUGIN_THREAD_LV2_GUI:
  86. /* osc-url */ arguments.add(String(fEngine->getOscServerPathTCP()) + "/" + String(fPlugin->getId()));
  87. /* URI */ arguments.add((const char*)fLabel);
  88. /* ui-URI */ arguments.add((const char*)fExtra1);
  89. /* ui-title */ arguments.add(name + " (GUI)");
  90. break;
  91. case PLUGIN_THREAD_VST_GUI:
  92. /* osc-url */ arguments.add(String(fEngine->getOscServerPathTCP()) + "/" + String(fPlugin->getId()));
  93. /* filename */ arguments.add(fPlugin->getFilename());
  94. /* ui-title */ arguments.add(name + " (GUI)");
  95. break;
  96. case PLUGIN_THREAD_BRIDGE:
  97. /* osc-url */ arguments.add(String(fEngine->getOscServerPathTCP()) + "/" + String(fPlugin->getId()));
  98. /* stype */ arguments.add((const char*)fExtra1);
  99. /* filename */ arguments.add(fPlugin->getFilename());
  100. /* name */ arguments.add(name);
  101. /* label */ arguments.add((const char*)fLabel);
  102. /* SHM ids */ arguments.add((const char*)fExtra2);
  103. break;
  104. }
  105. if (! process.start(arguments))
  106. return;
  107. switch (fMode)
  108. {
  109. case PLUGIN_THREAD_NULL:
  110. break;
  111. case PLUGIN_THREAD_DSSI_GUI:
  112. case PLUGIN_THREAD_LV2_GUI:
  113. case PLUGIN_THREAD_VST_GUI:
  114. if (fPlugin->waitForOscGuiShow())
  115. {
  116. while (process.isRunning() && ! threadShouldExit())
  117. sleep(1000);
  118. // we only get here is UI was closed or thread asked to exit
  119. if (threadShouldExit())
  120. {
  121. if (process.isRunning())
  122. process.kill();
  123. }
  124. else
  125. {
  126. fEngine->callback(CarlaBackend::CALLBACK_SHOW_GUI, fPlugin->getId(), 0, 0, 0.0f, nullptr);
  127. }
  128. }
  129. else
  130. {
  131. if (process.isRunning() && ! process.waitForProcessToFinish(500))
  132. {
  133. process.kill();
  134. fEngine->callback(CarlaBackend::CALLBACK_SHOW_GUI, fPlugin->getId(), -1, 0, 0.0f, nullptr);
  135. carla_stderr("CarlaPluginThread::run() - GUI crashed while opening");
  136. }
  137. else
  138. {
  139. fEngine->callback(CarlaBackend::CALLBACK_SHOW_GUI, fPlugin->getId(), 0, 0, 0.0f, nullptr);
  140. carla_stderr("CarlaPluginThread::run() - GUI timeout");
  141. }
  142. }
  143. break;
  144. case PLUGIN_THREAD_BRIDGE:
  145. while (process.isRunning() && ! threadShouldExit())
  146. sleep(1000);
  147. if (threadShouldExit())
  148. {
  149. if (process.isRunning())
  150. process.kill();
  151. }
  152. break;
  153. }
  154. }
  155. CARLA_BACKEND_END_NAMESPACE