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.

906 lines
25KB

  1. /*
  2. * Carla Backend
  3. * Copyright (C) 2012 Filipe Coelho <falktx@falktx.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_plugin.h"
  18. #include "plugins/carla_native.h"
  19. CARLA_BACKEND_START_NAMESPACE
  20. struct NativePluginMidiData {
  21. uint32_t count;
  22. uint32_t* rindexes;
  23. CarlaEngineMidiPort** ports;
  24. NativePluginMidiData()
  25. : count(0),
  26. rindexes(nullptr),
  27. ports(nullptr) {}
  28. };
  29. class NativePluginScopedInitiliazer
  30. {
  31. public:
  32. NativePluginScopedInitiliazer()
  33. {
  34. }
  35. ~NativePluginScopedInitiliazer()
  36. {
  37. for (size_t i=0; i < descriptors.size(); i++)
  38. {
  39. const PluginDescriptor* const desc = descriptors[i];
  40. if (desc->_fini)
  41. desc->_fini((struct _PluginDescriptor*)desc);
  42. }
  43. descriptors.clear();
  44. }
  45. void initializeIfNeeded(const PluginDescriptor* const desc)
  46. {
  47. if (descriptors.empty() || std::find(descriptors.begin(), descriptors.end(), desc) == descriptors.end())
  48. {
  49. if (desc->_init)
  50. desc->_init((struct _PluginDescriptor*)desc);
  51. descriptors.push_back(desc);
  52. }
  53. }
  54. private:
  55. std::vector<const PluginDescriptor*> descriptors;
  56. };
  57. static NativePluginScopedInitiliazer scopedInitliazer;
  58. class NativePlugin : public CarlaPlugin
  59. {
  60. public:
  61. NativePlugin(CarlaEngine* const engine, const unsigned short id)
  62. : CarlaPlugin(engine, id)
  63. {
  64. qDebug("NativePlugin::NativePlugin()");
  65. m_type = PLUGIN_INTERNAL;
  66. descriptor = nullptr;
  67. handle = nullptr;
  68. }
  69. ~NativePlugin()
  70. {
  71. qDebug("NativePlugin::~NativePlugin()");
  72. if (descriptor)
  73. {
  74. if (descriptor->deactivate && m_activeBefore)
  75. {
  76. if (handle)
  77. descriptor->deactivate(handle);
  78. //if (h2)
  79. // descriptor->deactivate(h2);
  80. }
  81. if (descriptor->cleanup)
  82. {
  83. if (handle)
  84. descriptor->cleanup(handle);
  85. //if (h2)
  86. // descriptor->cleanup(h2);
  87. }
  88. }
  89. }
  90. // -------------------------------------------------------------------
  91. // Information (base)
  92. PluginCategory category()
  93. {
  94. Q_ASSERT(descriptor);
  95. if (descriptor)
  96. return (PluginCategory)descriptor->category;
  97. return getPluginCategoryFromName(m_name);
  98. }
  99. // -------------------------------------------------------------------
  100. // Information (count)
  101. uint32_t midiInCount()
  102. {
  103. return mIn.count;
  104. }
  105. uint32_t midiOutCount()
  106. {
  107. return mOut.count;
  108. }
  109. uint32_t parameterScalePointCount(const uint32_t parameterId)
  110. {
  111. Q_ASSERT(descriptor);
  112. Q_ASSERT(parameterId < param.count);
  113. int32_t rindex = param.data[parameterId].rindex;
  114. if (descriptor && rindex < (int32_t)descriptor->portCount)
  115. {
  116. const PluginPort* const port = &descriptor->ports[rindex];
  117. if (port)
  118. return port->scalePointCount;
  119. }
  120. return 0;
  121. }
  122. // -------------------------------------------------------------------
  123. // Information (per-plugin data)
  124. double getParameterValue(const uint32_t parameterId)
  125. {
  126. Q_ASSERT(descriptor);
  127. Q_ASSERT(handle);
  128. Q_ASSERT(parameterId < param.count);
  129. if (descriptor && handle)
  130. return descriptor->get_parameter_value(handle, parameterId);
  131. return 0.0;
  132. }
  133. double getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId)
  134. {
  135. Q_ASSERT(descriptor);
  136. Q_ASSERT(parameterId < param.count);
  137. Q_ASSERT(scalePointId < parameterScalePointCount(parameterId));
  138. const int32_t rindex = param.data[parameterId].rindex;
  139. if (descriptor && rindex < (int32_t)descriptor->portCount)
  140. {
  141. const PluginPort* const port = &descriptor->ports[rindex];
  142. if (port && scalePointId < port->scalePointCount)
  143. {
  144. const PluginPortScalePoint* const scalePoint = &port->scalePoints[scalePointId];
  145. if (scalePoint)
  146. return scalePoint->value;
  147. }
  148. }
  149. return 0.0;
  150. }
  151. void getLabel(char* const strBuf)
  152. {
  153. Q_ASSERT(descriptor);
  154. if (descriptor && descriptor->label)
  155. strncpy(strBuf, descriptor->label, STR_MAX);
  156. else
  157. CarlaPlugin::getLabel(strBuf);
  158. }
  159. void getMaker(char* const strBuf)
  160. {
  161. Q_ASSERT(descriptor);
  162. if (descriptor && descriptor->maker)
  163. strncpy(strBuf, descriptor->maker, STR_MAX);
  164. else
  165. CarlaPlugin::getMaker(strBuf);
  166. }
  167. void getCopyright(char* const strBuf)
  168. {
  169. Q_ASSERT(descriptor);
  170. if (descriptor && descriptor->copyright)
  171. strncpy(strBuf, descriptor->copyright, STR_MAX);
  172. else
  173. CarlaPlugin::getCopyright(strBuf);
  174. }
  175. void getRealName(char* const strBuf)
  176. {
  177. Q_ASSERT(descriptor);
  178. if (descriptor && descriptor->name)
  179. strncpy(strBuf, descriptor->name, STR_MAX);
  180. else
  181. CarlaPlugin::getRealName(strBuf);
  182. }
  183. void getParameterName(const uint32_t parameterId, char* const strBuf)
  184. {
  185. Q_ASSERT(descriptor);
  186. Q_ASSERT(parameterId < param.count);
  187. const int32_t rindex = param.data[parameterId].rindex;
  188. if (descriptor && rindex < (int32_t)descriptor->portCount)
  189. {
  190. const PluginPort* const port = &descriptor->ports[rindex];
  191. if (port && port->name)
  192. {
  193. strncpy(strBuf, port->name, STR_MAX);
  194. return;
  195. }
  196. }
  197. CarlaPlugin::getParameterName(parameterId, strBuf);
  198. }
  199. void getParameterText(const uint32_t parameterId, char* const strBuf)
  200. {
  201. Q_ASSERT(descriptor);
  202. Q_ASSERT(handle);
  203. Q_ASSERT(parameterId < param.count);
  204. if (descriptor && handle)
  205. {
  206. const int32_t rindex = param.data[parameterId].rindex;
  207. const char* const text = descriptor->get_parameter_text(handle, rindex);
  208. if (text)
  209. {
  210. strncpy(strBuf, text, STR_MAX);
  211. return;
  212. }
  213. }
  214. CarlaPlugin::getParameterText(parameterId, strBuf);
  215. }
  216. void getParameterUnit(const uint32_t parameterId, char* const strBuf)
  217. {
  218. Q_ASSERT(descriptor);
  219. Q_ASSERT(handle);
  220. Q_ASSERT(parameterId < param.count);
  221. if (descriptor && handle)
  222. {
  223. const int32_t rindex = param.data[parameterId].rindex;
  224. const char* const unit = descriptor->get_parameter_unit(handle, rindex);
  225. if (unit)
  226. {
  227. strncpy(strBuf, unit, STR_MAX);
  228. return;
  229. }
  230. }
  231. CarlaPlugin::getParameterUnit(parameterId, strBuf);
  232. }
  233. void getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf)
  234. {
  235. Q_ASSERT(descriptor);
  236. Q_ASSERT(parameterId < param.count);
  237. Q_ASSERT(scalePointId < parameterScalePointCount(parameterId));
  238. int32_t rindex = param.data[parameterId].rindex;
  239. if (descriptor && rindex < (int32_t)descriptor->portCount)
  240. {
  241. const PluginPort* const port = &descriptor->ports[rindex];
  242. if (port && scalePointId < port->scalePointCount)
  243. {
  244. const PluginPortScalePoint* const scalePoint = &port->scalePoints[scalePointId];
  245. if (scalePoint && scalePoint->label)
  246. {
  247. strncpy(strBuf, scalePoint->label, STR_MAX);
  248. return;
  249. }
  250. }
  251. }
  252. CarlaPlugin::getParameterScalePointLabel(parameterId, scalePointId, strBuf);
  253. }
  254. // -------------------------------------------------------------------
  255. // Set data (plugin-specific stuff)
  256. void setParameterValue(const uint32_t parameterId, double value, const bool sendGui, const bool sendOsc, const bool sendCallback)
  257. {
  258. Q_ASSERT(descriptor);
  259. Q_ASSERT(handle);
  260. Q_ASSERT(parameterId < param.count);
  261. if (descriptor && handle)
  262. descriptor->set_parameter_value(handle, parameterId, fixParameterValue(value, param.ranges[parameterId]));
  263. CarlaPlugin::setParameterValue(parameterId, value, sendGui, sendOsc, sendCallback);
  264. }
  265. void setCustomData(const CustomDataType type, const char* const key, const char* const value, const bool sendGui)
  266. {
  267. Q_ASSERT(descriptor);
  268. Q_ASSERT(handle);
  269. Q_ASSERT(type == CUSTOM_DATA_STRING);
  270. Q_ASSERT(key);
  271. Q_ASSERT(value);
  272. if (type != CUSTOM_DATA_STRING)
  273. return qCritical("NativePlugin::setCustomData(%s, \"%s\", \"%s\", %s) - type is not string", CustomDataType2str(type), key, value, bool2str(sendGui));
  274. if (! key)
  275. return qCritical("NativePlugin::setCustomData(%s, \"%s\", \"%s\", %s) - key is null", CustomDataType2str(type), key, value, bool2str(sendGui));
  276. if (! value)
  277. return qCritical("Nativelugin::setCustomData(%s, \"%s\", \"%s\", %s) - value is null", CustomDataType2str(type), key, value, bool2str(sendGui));
  278. if (descriptor && handle)
  279. descriptor->set_custom_data(handle, key, value);
  280. CarlaPlugin::setCustomData(type, key, value, sendGui);
  281. }
  282. void setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool block)
  283. {
  284. Q_ASSERT(descriptor);
  285. Q_ASSERT(handle);
  286. Q_ASSERT(index >= -1 && index < (int32_t)midiprog.count);
  287. if (index < -1)
  288. index = -1;
  289. else if (index > (int32_t)midiprog.count)
  290. return;
  291. if (descriptor && handle && index >= 0)
  292. {
  293. if (x_engine->isOffline())
  294. {
  295. const CarlaEngine::ScopedLocker m(x_engine, block);
  296. descriptor->set_midi_program(handle, midiprog.data[index].bank, midiprog.data[index].program);
  297. }
  298. else
  299. {
  300. const ScopedDisabler m(this, block);
  301. descriptor->set_midi_program(handle, midiprog.data[index].bank, midiprog.data[index].program);
  302. }
  303. }
  304. CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, block);
  305. }
  306. // -------------------------------------------------------------------
  307. // Set gui stuff
  308. void showGui(const bool yesNo)
  309. {
  310. Q_ASSERT(descriptor);
  311. if (descriptor && handle)
  312. descriptor->show_gui(handle, yesNo);
  313. }
  314. void idleGui()
  315. {
  316. // FIXME - this should not be called if there's no GUI!
  317. Q_ASSERT(descriptor);
  318. if (descriptor && descriptor->idle_gui && handle)
  319. descriptor->idle_gui(handle);
  320. }
  321. // -------------------------------------------------------------------
  322. // Plugin state
  323. void reload()
  324. {
  325. qDebug("NativePlugin::reload() - start");
  326. Q_ASSERT(descriptor);
  327. // Safely disable plugin for reload
  328. const ScopedDisabler m(this);
  329. if (x_client->isActive())
  330. x_client->deactivate();
  331. // Remove client ports
  332. removeClientPorts();
  333. // Delete old data
  334. deleteBuffers();
  335. uint32_t aIns, aOuts, mIns, mOuts, params, j;
  336. aIns = aOuts = mIns = mOuts = params = 0;
  337. const double sampleRate = x_engine->getSampleRate();
  338. const uint32_t portCount = descriptor->portCount;
  339. for (uint32_t i=0; i < portCount; i++)
  340. {
  341. const PortType portType = descriptor->ports[i].type;
  342. const uint32_t portHints = descriptor->ports[i].hints;
  343. if (portType == PORT_TYPE_AUDIO)
  344. {
  345. if (portHints & PORT_HINT_IS_OUTPUT)
  346. aOuts += 1;
  347. else
  348. aIns += 1;
  349. }
  350. else if (portType == PORT_TYPE_MIDI)
  351. {
  352. if (portHints & PORT_HINT_IS_OUTPUT)
  353. mOuts += 1;
  354. else
  355. mIns += 1;
  356. }
  357. else if (portType == PORT_TYPE_PARAMETER)
  358. params += 1;
  359. }
  360. if (aIns > 0)
  361. {
  362. aIn.ports = new CarlaEngineAudioPort*[aIns];
  363. aIn.rindexes = new uint32_t[aIns];
  364. }
  365. if (aOuts > 0)
  366. {
  367. aOut.ports = new CarlaEngineAudioPort*[aOuts];
  368. aOut.rindexes = new uint32_t[aOuts];
  369. }
  370. if (mIns > 0)
  371. {
  372. mIn.ports = new CarlaEngineMidiPort*[mIns];
  373. mIn.rindexes = new uint32_t[mIns];
  374. }
  375. if (mOuts > 0)
  376. {
  377. mOut.ports = new CarlaEngineMidiPort*[mOuts];
  378. mOut.rindexes = new uint32_t[mOuts];
  379. }
  380. if (params > 0)
  381. {
  382. param.data = new ParameterData[params];
  383. param.ranges = new ParameterRanges[params];
  384. }
  385. const int portNameSize = CarlaEngine::maxPortNameSize() - 2;
  386. char portName[portNameSize];
  387. bool needsCtrlIn = false;
  388. bool needsCtrlOut = false;
  389. for (uint32_t i=0; i < portCount; i++)
  390. {
  391. const PortType portType = descriptor->ports[i].type;
  392. const uint32_t portHints = descriptor->ports[i].hints;
  393. if (portType == PORT_TYPE_AUDIO || portType == PORT_TYPE_MIDI)
  394. {
  395. if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS)
  396. {
  397. strcpy(portName, m_name);
  398. strcat(portName, ":");
  399. strncat(portName, descriptor->ports[i].name, portNameSize/2);
  400. }
  401. else
  402. strncpy(portName, descriptor->ports[i].name, portNameSize);
  403. }
  404. if (portType == PORT_TYPE_AUDIO)
  405. {
  406. if (portHints & PORT_HINT_IS_OUTPUT)
  407. {
  408. j = aOut.count++;
  409. aOut.ports[j] = (CarlaEngineAudioPort*)x_client->addPort(CarlaEnginePortTypeAudio, portName, false);
  410. aOut.rindexes[j] = i;
  411. needsCtrlIn = true;
  412. }
  413. else
  414. {
  415. j = aIn.count++;
  416. aIn.ports[j] = (CarlaEngineAudioPort*)x_client->addPort(CarlaEnginePortTypeAudio, portName, true);
  417. aIn.rindexes[j] = i;
  418. }
  419. }
  420. else if (portType == PORT_TYPE_MIDI)
  421. {
  422. if (portHints & PORT_HINT_IS_OUTPUT)
  423. {
  424. j = aOut.count++;
  425. mOut.ports[j] = (CarlaEngineMidiPort*)x_client->addPort(CarlaEnginePortTypeMIDI, portName, false);
  426. mOut.rindexes[j] = i;
  427. }
  428. else
  429. {
  430. j = aIn.count++;
  431. mIn.ports[j] = (CarlaEngineMidiPort*)x_client->addPort(CarlaEnginePortTypeMIDI, portName, true);
  432. mIn.rindexes[j] = i;
  433. }
  434. }
  435. else if (portType == PORT_TYPE_PARAMETER)
  436. {
  437. j = param.count++;
  438. param.data[j].index = j;
  439. param.data[j].rindex = i;
  440. param.data[j].hints = 0;
  441. param.data[j].midiChannel = 0;
  442. param.data[j].midiCC = -1;
  443. double min, max, def, step, stepSmall, stepLarge;
  444. ::ParameterRanges ranges = { 0.0, 0.0, 1.0, 0.01, 0.0001, 0.1 };
  445. descriptor->get_parameter_ranges(handle, i, &ranges);
  446. // min value
  447. min = ranges.min;
  448. // max value
  449. min = ranges.max;
  450. if (min > max)
  451. max = min;
  452. else if (max < min)
  453. min = max;
  454. if (max - min == 0.0)
  455. {
  456. qWarning("Broken plugin parameter: max - min == 0");
  457. max = min + 0.1;
  458. }
  459. // default value
  460. def = ranges.def;
  461. if (def < min)
  462. def = min;
  463. else if (def > max)
  464. def = max;
  465. if (portHints & PORT_HINT_USES_SAMPLE_RATE)
  466. {
  467. min *= sampleRate;
  468. max *= sampleRate;
  469. def *= sampleRate;
  470. param.data[j].hints |= PARAMETER_USES_SAMPLERATE;
  471. }
  472. if (portHints & PORT_HINT_IS_BOOLEAN)
  473. {
  474. step = max - min;
  475. stepSmall = step;
  476. stepLarge = step;
  477. param.data[j].hints |= PARAMETER_IS_BOOLEAN;
  478. }
  479. else if (portHints & PORT_HINT_IS_INTEGER)
  480. {
  481. step = 1.0;
  482. stepSmall = 1.0;
  483. stepLarge = 10.0;
  484. param.data[j].hints |= PARAMETER_IS_INTEGER;
  485. }
  486. else
  487. {
  488. double range = max - min;
  489. step = range/100.0;
  490. stepSmall = range/1000.0;
  491. stepLarge = range/10.0;
  492. }
  493. if (portHints & PORT_HINT_IS_OUTPUT)
  494. {
  495. param.data[j].type = PARAMETER_OUTPUT;
  496. needsCtrlOut = true;
  497. }
  498. else
  499. {
  500. param.data[j].type = PARAMETER_INPUT;
  501. needsCtrlIn = true;
  502. }
  503. // extra parameter hints
  504. if (portHints & PORT_HINT_IS_ENABLED)
  505. param.data[j].hints |= PARAMETER_IS_ENABLED;
  506. if (portHints & PORT_HINT_IS_AUTOMABLE)
  507. param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
  508. if (portHints & PORT_HINT_IS_LOGARITHMIC)
  509. param.data[j].hints |= PARAMETER_IS_LOGARITHMIC;
  510. if (portHints & PORT_HINT_USES_SCALEPOINTS)
  511. param.data[j].hints |= PARAMETER_USES_SCALEPOINTS;
  512. if (portHints & PORT_HINT_USES_CUSTOM_TEXT)
  513. param.data[j].hints |= PARAMETER_USES_CUSTOM_TEXT;
  514. param.ranges[j].min = min;
  515. param.ranges[j].max = max;
  516. param.ranges[j].def = def;
  517. param.ranges[j].step = step;
  518. param.ranges[j].stepSmall = stepSmall;
  519. param.ranges[j].stepLarge = stepLarge;
  520. }
  521. }
  522. if (needsCtrlIn)
  523. {
  524. if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS)
  525. {
  526. strcpy(portName, m_name);
  527. strcat(portName, ":control-in");
  528. }
  529. else
  530. strcpy(portName, "control-in");
  531. param.portCin = (CarlaEngineControlPort*)x_client->addPort(CarlaEnginePortTypeControl, portName, true);
  532. }
  533. if (needsCtrlOut)
  534. {
  535. if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS)
  536. {
  537. strcpy(portName, m_name);
  538. strcat(portName, ":control-out");
  539. }
  540. else
  541. strcpy(portName, "control-out");
  542. param.portCout = (CarlaEngineControlPort*)x_client->addPort(CarlaEnginePortTypeControl, portName, false);
  543. }
  544. aIn.count = aIns;
  545. aOut.count = aOuts;
  546. param.count = params;
  547. // plugin checks
  548. m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE);
  549. if (aOuts > 0 && (aIns == aOuts || aIns == 1))
  550. m_hints |= PLUGIN_CAN_DRYWET;
  551. if (aOuts > 0)
  552. m_hints |= PLUGIN_CAN_VOLUME;
  553. if (aOuts >= 2 && aOuts%2 == 0)
  554. m_hints |= PLUGIN_CAN_BALANCE;
  555. m_hints |= getPluginHintsFromNative(descriptor->hints);
  556. reloadPrograms(true);
  557. x_client->activate();
  558. qDebug("NativePlugin::reload() - end");
  559. }
  560. // -------------------------------------------------------------------
  561. // Cleanup
  562. void removeClientPorts()
  563. {
  564. qDebug("NativePlugin::removeClientPorts() - start");
  565. for (uint32_t i=0; i < mIn.count; i++)
  566. {
  567. delete mIn.ports[i];
  568. mIn.ports[i] = nullptr;
  569. }
  570. for (uint32_t i=0; i < mOut.count; i++)
  571. {
  572. delete mOut.ports[i];
  573. mOut.ports[i] = nullptr;
  574. }
  575. CarlaPlugin::removeClientPorts();
  576. qDebug("NativePlugin::removeClientPorts() - end");
  577. }
  578. void initBuffers()
  579. {
  580. uint32_t i;
  581. for (i=0; i < mIn.count; i++)
  582. {
  583. if (mIn.ports[i])
  584. mIn.ports[i]->initBuffer(x_engine);
  585. }
  586. for (i=0; i < mOut.count; i++)
  587. {
  588. if (mOut.ports[i])
  589. mOut.ports[i]->initBuffer(x_engine);
  590. }
  591. CarlaPlugin::initBuffers();
  592. }
  593. void deleteBuffers()
  594. {
  595. qDebug("NativePlugin::deleteBuffers() - start");
  596. if (mIn.count > 0)
  597. {
  598. delete[] mIn.ports;
  599. delete[] mIn.rindexes;
  600. }
  601. if (mOut.count > 0)
  602. {
  603. delete[] mOut.ports;
  604. delete[] mOut.rindexes;
  605. }
  606. mIn.count = 0;
  607. mIn.ports = nullptr;
  608. mIn.rindexes = nullptr;
  609. mOut.count = 0;
  610. mOut.ports = nullptr;
  611. mOut.rindexes = nullptr;
  612. CarlaPlugin::deleteBuffers();
  613. qDebug("NativePlugin::deleteBuffers() - end");
  614. }
  615. // -------------------------------------------------------------------
  616. static size_t getPluginCount()
  617. {
  618. return pluginDescriptors.size();
  619. }
  620. static const PluginDescriptor* getPlugin(size_t index)
  621. {
  622. Q_ASSERT(index < pluginDescriptors.size());
  623. if (index < pluginDescriptors.size())
  624. return pluginDescriptors[index];
  625. return nullptr;
  626. }
  627. static void registerPlugin(const PluginDescriptor* desc)
  628. {
  629. pluginDescriptors.push_back(desc);
  630. }
  631. // -------------------------------------------------------------------
  632. bool init(const char* const name, const char* const label)
  633. {
  634. // ---------------------------------------------------------------
  635. // get descriptor that matches label
  636. for (size_t i=0; i < pluginDescriptors.size(); i++)
  637. {
  638. descriptor = pluginDescriptors[i];
  639. if (! descriptor)
  640. break;
  641. if (strcmp(descriptor->label, label) == 0)
  642. break;
  643. descriptor = nullptr;
  644. }
  645. if (! descriptor)
  646. {
  647. setLastError("Invalid internal plugin");
  648. return false;
  649. }
  650. scopedInitliazer.initializeIfNeeded(descriptor);
  651. // ---------------------------------------------------------------
  652. // initialize plugin
  653. handle = descriptor->instantiate((struct _PluginDescriptor*)descriptor, nullptr); // TODO - host
  654. if (! handle)
  655. {
  656. setLastError("Plugin failed to initialize");
  657. return false;
  658. }
  659. // ---------------------------------------------------------------
  660. // get info
  661. if (name)
  662. m_name = x_engine->getUniqueName(name);
  663. else
  664. m_name = x_engine->getUniqueName(descriptor->name);
  665. // ---------------------------------------------------------------
  666. // register client
  667. x_client = x_engine->addClient(this);
  668. if (! x_client->isOk())
  669. {
  670. setLastError("Failed to register plugin client");
  671. return false;
  672. }
  673. return true;
  674. }
  675. private:
  676. const PluginDescriptor* descriptor;
  677. PluginHandle handle;
  678. NativePluginMidiData mIn;
  679. NativePluginMidiData mOut;
  680. static std::vector<const PluginDescriptor*> pluginDescriptors;
  681. };
  682. std::vector<const PluginDescriptor*> NativePlugin::pluginDescriptors;
  683. CarlaPlugin* CarlaPlugin::newNative(const initializer& init)
  684. {
  685. qDebug("CarlaPlugin::newNative(%p, \"%s\", \"%s\", \"%s\")", init.engine, init.filename, init.name, init.label);
  686. short id = init.engine->getNewPluginId();
  687. if (id < 0 || id > CarlaEngine::maxPluginNumber())
  688. {
  689. setLastError("Maximum number of plugins reached");
  690. return nullptr;
  691. }
  692. NativePlugin* const plugin = new NativePlugin(init.engine, id);
  693. if (! plugin->init(init.name, init.label))
  694. {
  695. delete plugin;
  696. return nullptr;
  697. }
  698. plugin->reload();
  699. plugin->registerToOsc();
  700. return plugin;
  701. }
  702. size_t CarlaPlugin::getNativePluginCount()
  703. {
  704. return NativePlugin::getPluginCount();
  705. }
  706. const PluginDescriptor* CarlaPlugin::getNativePlugin(size_t index)
  707. {
  708. return NativePlugin::getPlugin(index);
  709. }
  710. CARLA_BACKEND_END_NAMESPACE
  711. void carla_register_native_plugin(const PluginDescriptor* desc)
  712. {
  713. CarlaBackend::NativePlugin::registerPlugin(desc);
  714. }