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.

301 lines
9.0KB

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