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.

309 lines
9.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, %p)", engine, parent);
  28. Q_ASSERT(engine);
  29. }
  30. CarlaCheckThread::~CarlaCheckThread()
  31. {
  32. qDebug("CarlaCheckThread::~CarlaCheckThread()");
  33. }
  34. void CarlaCheckThread::startNow()
  35. {
  36. start(QThread::HighPriority);
  37. }
  38. void CarlaCheckThread::stopNow()
  39. {
  40. m_stopNow = true;
  41. // TESTING - let processing finish first
  42. QMutexLocker(&this->mutex); // FIXME
  43. if (isRunning() && ! wait(200))
  44. {
  45. quit();
  46. if (isRunning() && ! wait(300))
  47. terminate();
  48. }
  49. }
  50. void CarlaCheckThread::run()
  51. {
  52. qDebug("CarlaCheckThread::run()");
  53. using namespace CarlaBackend;
  54. bool oscControllerRegisted, usesSingleThread;
  55. unsigned short id, maxPluginNumber = CarlaEngine::maxPluginNumber();
  56. double value;
  57. m_stopNow = false;
  58. while (engine->isRunning() && ! m_stopNow)
  59. {
  60. const ScopedLocker m(this);
  61. #ifdef BUILD_BRIDGE
  62. oscControllerRegisted = true;
  63. #else
  64. oscControllerRegisted = engine->isOscControllerRegisted();
  65. #endif
  66. for (unsigned short i=0; i < maxPluginNumber; i++)
  67. {
  68. CarlaPlugin* const plugin = engine->getPluginUnchecked(i);
  69. if (plugin && plugin->enabled())
  70. {
  71. id = plugin->id();
  72. usesSingleThread = (plugin->hints() & PLUGIN_USES_SINGLE_THREAD);
  73. // -------------------------------------------------------
  74. // Process postponed events
  75. if (! usesSingleThread)
  76. plugin->postEventsRun();
  77. // -------------------------------------------------------
  78. // Update parameter outputs
  79. if (oscControllerRegisted || ! usesSingleThread)
  80. {
  81. for (uint32_t i=0; i < plugin->parameterCount(); i++)
  82. {
  83. if (plugin->parameterIsOutput(i))
  84. {
  85. value = plugin->getParameterValue(i);
  86. // Update UI
  87. if (! usesSingleThread)
  88. plugin->uiParameterChange(i, value);
  89. // Update OSC control client
  90. if (oscControllerRegisted)
  91. #ifdef BUILD_BRIDGE
  92. engine->osc_send_bridge_set_parameter_value(i, value);
  93. #else
  94. engine->osc_send_control_set_parameter_value(id, i, value);
  95. #endif
  96. }
  97. }
  98. }
  99. // -------------------------------------------------------
  100. // Update OSC control client
  101. if (oscControllerRegisted)
  102. {
  103. // Peak values
  104. if (plugin->audioInCount() > 0)
  105. {
  106. #ifdef BUILD_BRIDGE
  107. engine->osc_send_bridge_set_input_peak_value(1, engine->getInputPeak(id, 0));
  108. engine->osc_send_bridge_set_input_peak_value(2, engine->getInputPeak(id, 1));
  109. #else
  110. engine->osc_send_control_set_input_peak_value(id, 1, engine->getInputPeak(id, 0));
  111. engine->osc_send_control_set_input_peak_value(id, 2, engine->getInputPeak(id, 1));
  112. #endif
  113. }
  114. if (plugin->audioOutCount() > 0)
  115. {
  116. #ifdef BUILD_BRIDGE
  117. engine->osc_send_bridge_set_output_peak_value(1, engine->getOutputPeak(id, 0));
  118. engine->osc_send_bridge_set_output_peak_value(2, engine->getOutputPeak(id, 1));
  119. #else
  120. engine->osc_send_control_set_output_peak_value(id, 1, engine->getOutputPeak(id, 0));
  121. engine->osc_send_control_set_output_peak_value(id, 2, engine->getOutputPeak(id, 1));
  122. #endif
  123. }
  124. }
  125. }
  126. }
  127. msleep(50);
  128. }
  129. }
  130. // -----------------------------------------------------------------------
  131. // CarlaPluginThread
  132. #ifndef BUILD_BRIDGE
  133. const char* PluginThreadMode2str(const CarlaPluginThread::PluginThreadMode mode)
  134. {
  135. switch (mode)
  136. {
  137. case CarlaPluginThread::PLUGIN_THREAD_DSSI_GUI:
  138. return "PLUGIN_THREAD_DSSI_GUI";
  139. case CarlaPluginThread::PLUGIN_THREAD_LV2_GUI:
  140. return "PLUGIN_THREAD_LV2_GUI";
  141. case CarlaPluginThread::PLUGIN_THREAD_VST_GUI:
  142. return "PLUGIN_THREAD_VST_GUI";
  143. case CarlaPluginThread::PLUGIN_THREAD_BRIDGE:
  144. return "PLUGIN_THREAD_BRIDGE";
  145. }
  146. qWarning("CarlaPluginThread::PluginThreadMode2str(%i) - invalid mode", mode);
  147. return nullptr;
  148. }
  149. CarlaPluginThread::CarlaPluginThread(CarlaBackend::CarlaEngine* const engine_, CarlaBackend::CarlaPlugin* const plugin_, const PluginThreadMode mode_, QObject* const parent) :
  150. QThread(parent),
  151. engine(engine_),
  152. plugin(plugin_),
  153. mode(mode_)
  154. {
  155. qDebug("CarlaPluginThread::CarlaPluginThread(plugin:\"%s\", engine:\"%s\", %s)", plugin->name(), engine->getName(), PluginThreadMode2str(mode));
  156. m_process = nullptr;
  157. }
  158. CarlaPluginThread::~CarlaPluginThread()
  159. {
  160. if (m_process)
  161. delete m_process;
  162. }
  163. void CarlaPluginThread::setOscData(const char* const binary, const char* const label, const char* const data1)
  164. {
  165. m_binary = QString(binary);
  166. m_label = QString(label);
  167. m_data1 = QString(data1);
  168. }
  169. void CarlaPluginThread::run()
  170. {
  171. qDebug("CarlaPluginThread::run()");
  172. if (! m_process)
  173. m_process = new QProcess(nullptr);
  174. m_process->setProcessChannelMode(QProcess::ForwardedChannels);
  175. QStringList arguments;
  176. switch (mode)
  177. {
  178. case PLUGIN_THREAD_DSSI_GUI:
  179. /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath()).arg(plugin->id());
  180. /* filename */ arguments << plugin->filename();
  181. /* label */ arguments << m_label;
  182. /* ui-title */ arguments << QString("%1 (GUI)").arg(plugin->name());
  183. break;
  184. case PLUGIN_THREAD_LV2_GUI:
  185. /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath()).arg(plugin->id());
  186. /* URI */ arguments << m_label;
  187. /* ui-URI */ arguments << m_data1;
  188. /* ui-title */ arguments << QString("%1 (GUI)").arg(plugin->name());
  189. break;
  190. case PLUGIN_THREAD_VST_GUI:
  191. /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath()).arg(plugin->id());
  192. /* filename */ arguments << plugin->filename();
  193. /* ui-title */ arguments << QString("%1 (GUI)").arg(plugin->name());
  194. break;
  195. case PLUGIN_THREAD_BRIDGE:
  196. {
  197. const char* name = plugin->name();
  198. if (! name)
  199. name = "(none)";
  200. /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath()).arg(plugin->id());
  201. /* stype */ arguments << m_data1;
  202. /* filename */ arguments << plugin->filename();
  203. /* name */ arguments << name;
  204. /* label */ arguments << m_label;
  205. break;
  206. }
  207. }
  208. qDebug() << m_binary;
  209. qDebug() << arguments;
  210. m_process->start(m_binary, arguments);
  211. m_process->waitForStarted();
  212. switch (mode)
  213. {
  214. case PLUGIN_THREAD_DSSI_GUI:
  215. case PLUGIN_THREAD_LV2_GUI:
  216. case PLUGIN_THREAD_VST_GUI:
  217. if (plugin->showOscGui())
  218. {
  219. m_process->waitForFinished(-1);
  220. if (m_process->exitCode() == 0)
  221. {
  222. // Hide
  223. engine->callback(CarlaBackend::CALLBACK_SHOW_GUI, plugin->id(), 0, 0, 0.0);
  224. qWarning("CarlaPluginThread::run() - GUI closed");
  225. }
  226. else
  227. {
  228. // Kill
  229. engine->callback(CarlaBackend::CALLBACK_SHOW_GUI, plugin->id(), -1, 0, 0.0);
  230. qWarning("CarlaPluginThread::run() - GUI crashed");
  231. break;
  232. }
  233. }
  234. else
  235. {
  236. qDebug("CarlaPluginThread::run() - GUI timeout");
  237. engine->callback(CarlaBackend::CALLBACK_SHOW_GUI, plugin->id(), 0, 0, 0.0);
  238. }
  239. break;
  240. case PLUGIN_THREAD_BRIDGE:
  241. qDebug("CarlaPluginThread::run() - bridge starting...");
  242. m_process->waitForFinished(-1);
  243. qDebug("CarlaPluginThread::run() - bridge ended");
  244. #ifdef DEBUG
  245. if (m_process->exitCode() == 0)
  246. qDebug("CarlaPluginThread::run() - bridge closed");
  247. else
  248. qDebug("CarlaPluginThread::run() - bridge crashed");
  249. qDebug("%s", QString(m_process->readAllStandardOutput()).toUtf8().constData());
  250. #endif
  251. break;
  252. }
  253. }
  254. #endif