Collection of tools useful for audio production
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.

277 lines
8.4KB

  1. /*
  2. * Carla Backend
  3. * Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * 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 COPYING file
  16. */
  17. #include "carla_threads.h"
  18. #include "carla_plugin.h"
  19. #include <QtCore/QDebug>
  20. #include <QtCore/QProcess>
  21. // -----------------------------------------------------------------------
  22. // CarlaCheckThread
  23. CarlaCheckThread::CarlaCheckThread(CarlaBackend::CarlaEngine* const engine_, QObject* const parent) :
  24. QThread(parent),
  25. engine(engine_)
  26. {
  27. qDebug("CarlaCheckThread::CarlaCheckThread(%p)", parent);
  28. }
  29. CarlaCheckThread::~CarlaCheckThread()
  30. {
  31. qDebug("CarlaCheckThread::~CarlaCheckThread()");
  32. }
  33. void CarlaCheckThread::stopNow()
  34. {
  35. m_stopNow = true;
  36. // TESTING - let processing finish first
  37. QMutexLocker(&this->mutex); // FIXME
  38. if (isRunning() && ! wait(200))
  39. {
  40. quit();
  41. if (isRunning() && ! wait(300))
  42. terminate();
  43. }
  44. }
  45. void CarlaCheckThread::run()
  46. {
  47. qDebug("CarlaCheckThread::run()");
  48. bool oscControllerRegisted, usesSingleThread;
  49. unsigned short id;
  50. double value;
  51. m_stopNow = false;
  52. while (engine->isRunning() && ! m_stopNow)
  53. {
  54. const ScopedLocker m(this);
  55. oscControllerRegisted = engine->isOscControllerRegisted();
  56. for (unsigned short i=0; i < CarlaBackend::MAX_PLUGINS; i++)
  57. {
  58. CarlaBackend::CarlaPlugin* const plugin = engine->getPluginUnchecked(i);
  59. if (plugin && plugin->enabled())
  60. {
  61. id = plugin->id();
  62. usesSingleThread = (plugin->hints() & CarlaBackend::PLUGIN_USES_SINGLE_THREAD);
  63. // -------------------------------------------------------
  64. // Process postponed events
  65. if (! usesSingleThread)
  66. plugin->postEventsRun();
  67. // -------------------------------------------------------
  68. // Update parameter outputs
  69. if (oscControllerRegisted || ! usesSingleThread)
  70. {
  71. for (uint32_t i=0; i < plugin->parameterCount(); i++)
  72. {
  73. if (plugin->parameterIsOutput(i))
  74. {
  75. value = plugin->getParameterValue(i);
  76. // Update UI
  77. if (! usesSingleThread)
  78. plugin->uiParameterChange(i, value);
  79. // Update OSC control client
  80. if (oscControllerRegisted)
  81. engine->osc_send_set_parameter_value(id, i, value);
  82. }
  83. }
  84. }
  85. // -------------------------------------------------------
  86. // Update OSC control client
  87. if (oscControllerRegisted)
  88. {
  89. // Peak values
  90. if (plugin->audioInCount() > 0)
  91. {
  92. engine->osc_send_set_input_peak_value(id, 1, engine->getInputPeak(id, 0));
  93. engine->osc_send_set_input_peak_value(id, 2, engine->getInputPeak(id, 1));
  94. }
  95. if (plugin->audioOutCount() > 0)
  96. {
  97. engine->osc_send_set_output_peak_value(id, 1, engine->getOutputPeak(id, 0));
  98. engine->osc_send_set_output_peak_value(id, 2, engine->getOutputPeak(id, 1));
  99. }
  100. }
  101. }
  102. }
  103. msleep(50);
  104. }
  105. }
  106. // -----------------------------------------------------------------------
  107. // CarlaPluginThread
  108. const char* PluginThreadMode2str(const CarlaPluginThread::PluginThreadMode mode)
  109. {
  110. switch (mode)
  111. {
  112. case CarlaPluginThread::PLUGIN_THREAD_DSSI_GUI:
  113. return "PLUGIN_THREAD_DSSI_GUI";
  114. case CarlaPluginThread::PLUGIN_THREAD_LV2_GUI:
  115. return "PLUGIN_THREAD_LV2_GUI";
  116. case CarlaPluginThread::PLUGIN_THREAD_VST_GUI:
  117. return "PLUGIN_THREAD_VST_GUI";
  118. case CarlaPluginThread::PLUGIN_THREAD_BRIDGE:
  119. return "PLUGIN_THREAD_BRIDGE";
  120. }
  121. qWarning("CarlaPluginThread::PluginThreadMode2str(%i) - invalid mode", mode);
  122. return nullptr;
  123. }
  124. CarlaPluginThread::CarlaPluginThread(CarlaBackend::CarlaEngine* const engine_, CarlaBackend::CarlaPlugin* const plugin_, const PluginThreadMode mode_, QObject* const parent) :
  125. QThread(parent),
  126. engine(engine_),
  127. plugin(plugin_),
  128. mode(mode_)
  129. {
  130. qDebug("CarlaPluginThread::CarlaPluginThread(plugin:\"%s\", engine:\"%s\", %s)", plugin->name(), engine->getName(), PluginThreadMode2str(mode));
  131. m_process = nullptr;
  132. }
  133. CarlaPluginThread::~CarlaPluginThread()
  134. {
  135. if (m_process)
  136. delete m_process;
  137. }
  138. void CarlaPluginThread::setOscData(const char* const binary, const char* const label, const char* const data1)
  139. {
  140. m_binary = QString(binary);
  141. m_label = QString(label);
  142. m_data1 = QString(data1);
  143. }
  144. void CarlaPluginThread::run()
  145. {
  146. qDebug("CarlaPluginThread::run()");
  147. if (! m_process)
  148. m_process = new QProcess(nullptr);
  149. m_process->setProcessChannelMode(QProcess::ForwardedChannels);
  150. QStringList arguments;
  151. switch (mode)
  152. {
  153. case PLUGIN_THREAD_DSSI_GUI:
  154. /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath(), plugin->id());
  155. /* filename */ arguments << plugin->filename();
  156. /* label */ arguments << m_label;
  157. /* ui-title */ arguments << QString("%1 (GUI)").arg(plugin->name());
  158. break;
  159. case PLUGIN_THREAD_LV2_GUI:
  160. /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath(), plugin->id());
  161. /* URI */ arguments << m_label;
  162. /* ui-URI */ arguments << m_data1;
  163. /* ui-title */ arguments << QString("%1 (GUI)").arg(plugin->name());
  164. break;
  165. case PLUGIN_THREAD_VST_GUI:
  166. /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath(), plugin->id());
  167. /* filename */ arguments << plugin->filename();
  168. /* label */ arguments << m_label;
  169. /* ui-title */ arguments << QString("%1 (GUI)").arg(plugin->name());
  170. break;
  171. case PLUGIN_THREAD_BRIDGE:
  172. {
  173. const char* name = plugin->name();
  174. if (! name)
  175. name = "(none)";
  176. /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath(), plugin->id());
  177. /* stype */ arguments << m_data1;
  178. /* filename */ arguments << plugin->filename();
  179. /* name */ arguments << name;
  180. /* label */ arguments << m_label;
  181. break;
  182. }
  183. }
  184. qDebug() << m_binary;
  185. qDebug() << arguments;
  186. m_process->start(m_binary, arguments);
  187. m_process->waitForStarted();
  188. switch (mode)
  189. {
  190. case PLUGIN_THREAD_DSSI_GUI:
  191. case PLUGIN_THREAD_LV2_GUI:
  192. case PLUGIN_THREAD_VST_GUI:
  193. if (plugin->showOscGui())
  194. {
  195. m_process->waitForFinished(-1);
  196. if (m_process->exitCode() == 0)
  197. {
  198. // Hide
  199. engine->callback(CarlaBackend::CALLBACK_SHOW_GUI, plugin->id(), 0, 0, 0.0);
  200. qWarning("CarlaPluginThread::run() - GUI closed");
  201. }
  202. else
  203. {
  204. // Kill
  205. engine->callback(CarlaBackend::CALLBACK_SHOW_GUI, plugin->id(), -1, 0, 0.0);
  206. qWarning("CarlaPluginThread::run() - GUI crashed");
  207. break;
  208. }
  209. }
  210. else
  211. {
  212. qDebug("CarlaPluginThread::run() - GUI timeout");
  213. engine->callback(CarlaBackend::CALLBACK_SHOW_GUI, plugin->id(), 0, 0, 0.0);
  214. }
  215. break;
  216. case PLUGIN_THREAD_BRIDGE:
  217. m_process->waitForFinished(-1);
  218. #ifdef DEBUG
  219. if (m_process->exitCode() == 0)
  220. qDebug("CarlaPluginThread::run() - bridge closed");
  221. else
  222. qDebug("CarlaPluginThread::run() - bridge crashed");
  223. qDebug("%s", QString(m_process->readAllStandardOutput()).toUtf8().constData());
  224. #endif
  225. break;
  226. }
  227. }