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.

748 lines
25KB

  1. /*
  2. * Carla Native Plugins
  3. * Copyright (C) 2013-2023 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 "CarlaNativePrograms.hpp"
  18. #include "CarlaString.hpp"
  19. #include "audio-base.hpp"
  20. // --------------------------------------------------------------------------------------------------------------------
  21. #ifndef __MOD_DEVICES__
  22. class AudioFilePlugin : public NativePluginWithMidiPrograms<FileAudio>
  23. #else
  24. class AudioFilePlugin : public NativePluginClass
  25. #endif
  26. {
  27. public:
  28. #ifndef __MOD_DEVICES__
  29. static constexpr const char* const audiofilesWildcard =
  30. #ifdef HAVE_SNDFILE
  31. "*.aif;*.aifc;*.aiff;*.au;*.bwf;*.flac;*.htk;*.iff;*.mat4;*.mat5;*.oga;*.ogg;*.opus;"
  32. "*.paf;*.pvf;*.pvf5;*.sd2;*.sf;*.snd;*.svx;*.vcc;*.w64;*.wav;*.xi;"
  33. #endif
  34. #ifdef HAVE_FFMPEG
  35. "*.3g2;*.3gp;*.aac;*.ac3;*.amr;*.ape;*.mp2;*.mp3;*.mpc;*.wma;"
  36. #ifndef HAVE_SNDFILE
  37. "*.flac;*.oga;*.ogg;*.w64;*.wav;"
  38. #endif
  39. #else
  40. "*.mp3;"
  41. #endif
  42. ;
  43. enum PendingInlineDisplay : uint8_t {
  44. InlineDisplayNotPending,
  45. InlineDisplayNeedRequest,
  46. InlineDisplayRequesting
  47. };
  48. #endif
  49. enum Parameters {
  50. kParameterLooping,
  51. kParameterHostSync,
  52. kParameterVolume,
  53. kParameterEnabled,
  54. kParameterInfoChannels,
  55. kParameterInfoBitRate,
  56. kParameterInfoBitDepth,
  57. kParameterInfoSampleRate,
  58. kParameterInfoLength,
  59. kParameterInfoPosition,
  60. kParameterInfoPoolFill,
  61. kParameterCount
  62. };
  63. AudioFilePlugin(const NativeHostDescriptor* const host)
  64. #ifndef __MOD_DEVICES__
  65. : NativePluginWithMidiPrograms<FileAudio>(host, fPrograms, 3),
  66. fPrograms(hostGetFilePath("audio"), audiofilesWildcard)
  67. #else
  68. : NativePluginClass(host)
  69. #endif
  70. // fWasPlayingBefore(false),
  71. // fNeedsFileRead(false),
  72. // fEntireFileLoaded(false),
  73. // fMaxFrame(0),
  74. // fReadableBufferFill(0.0f),
  75. // fPool(),
  76. // fReader(),
  77. // fFilename(),
  78. // fPreviewData()
  79. // #ifndef __MOD_DEVICES__
  80. // , fInlineDisplay()
  81. // #endif
  82. {
  83. }
  84. ~AudioFilePlugin() override
  85. {
  86. // fReader.destroy();
  87. // fPool.destroy();
  88. }
  89. protected:
  90. // ----------------------------------------------------------------------------------------------------------------
  91. // Plugin parameter calls
  92. uint32_t getParameterCount() const override
  93. {
  94. return kParameterCount;
  95. }
  96. const NativeParameter* getParameterInfo(const uint32_t index) const override
  97. {
  98. static NativeParameter param;
  99. param.scalePointCount = 0;
  100. param.scalePoints = nullptr;
  101. param.unit = nullptr;
  102. param.ranges.step = 1.0f;
  103. param.ranges.stepSmall = 1.0f;
  104. param.ranges.stepLarge = 1.0f;
  105. param.designation = NATIVE_PARAMETER_DESIGNATION_NONE;
  106. switch (index)
  107. {
  108. case kParameterLooping:
  109. param.name = "Loop Mode";
  110. param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE|
  111. NATIVE_PARAMETER_IS_ENABLED|
  112. NATIVE_PARAMETER_IS_BOOLEAN);
  113. param.ranges.def = 1.0f;
  114. param.ranges.min = 0.0f;
  115. param.ranges.max = 1.0f;
  116. break;
  117. case kParameterHostSync:
  118. param.name = "Host Sync";
  119. param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE|
  120. NATIVE_PARAMETER_IS_ENABLED|
  121. NATIVE_PARAMETER_IS_BOOLEAN);
  122. #ifdef __MOD_DEVICES__
  123. param.ranges.def = 0.0f;
  124. #else
  125. param.ranges.def = 1.0f;
  126. #endif
  127. param.ranges.min = 0.0f;
  128. param.ranges.max = 1.0f;
  129. break;
  130. case kParameterVolume:
  131. param.name = "Volume";
  132. param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE|
  133. NATIVE_PARAMETER_IS_ENABLED);
  134. param.ranges.def = 100.0f;
  135. param.ranges.min = 0.0f;
  136. param.ranges.max = 127.0f;
  137. param.ranges.stepSmall = 0.5f;
  138. param.ranges.stepLarge = 10.0f;
  139. param.unit = "%";
  140. break;
  141. case kParameterEnabled:
  142. param.name = "Enabled";
  143. param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE|
  144. NATIVE_PARAMETER_IS_ENABLED|
  145. NATIVE_PARAMETER_IS_BOOLEAN|
  146. NATIVE_PARAMETER_USES_DESIGNATION);
  147. param.ranges.def = 1.0f;
  148. param.ranges.min = 0.0f;
  149. param.ranges.max = 1.0f;
  150. param.designation = NATIVE_PARAMETER_DESIGNATION_ENABLED;
  151. break;
  152. case kParameterInfoChannels:
  153. param.name = "Num Channels";
  154. param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE|
  155. NATIVE_PARAMETER_IS_ENABLED|
  156. NATIVE_PARAMETER_IS_INTEGER|
  157. NATIVE_PARAMETER_IS_OUTPUT);
  158. param.ranges.def = 0.0f;
  159. param.ranges.min = 0.0f;
  160. param.ranges.max = 2.0f;
  161. break;
  162. case kParameterInfoBitRate:
  163. param.name = "Bit Rate";
  164. param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE|
  165. NATIVE_PARAMETER_IS_ENABLED|
  166. NATIVE_PARAMETER_IS_INTEGER|
  167. NATIVE_PARAMETER_IS_OUTPUT);
  168. param.ranges.def = 0.0f;
  169. param.ranges.min = -1.0f;
  170. param.ranges.max = 384000.0f * 64.0f * 2.0f;
  171. break;
  172. case kParameterInfoBitDepth:
  173. param.name = "Bit Depth";
  174. param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE|
  175. NATIVE_PARAMETER_IS_ENABLED|
  176. NATIVE_PARAMETER_IS_INTEGER|
  177. NATIVE_PARAMETER_IS_OUTPUT);
  178. param.ranges.def = 0.0f;
  179. param.ranges.min = 0.0f;
  180. param.ranges.max = 64.0f;
  181. break;
  182. case kParameterInfoSampleRate:
  183. param.name = "Sample Rate";
  184. param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE|
  185. NATIVE_PARAMETER_IS_ENABLED|
  186. NATIVE_PARAMETER_IS_INTEGER|
  187. NATIVE_PARAMETER_IS_OUTPUT);
  188. param.ranges.def = 0.0f;
  189. param.ranges.min = 0.0f;
  190. param.ranges.max = 384000.0f;
  191. break;
  192. case kParameterInfoLength:
  193. param.name = "Length";
  194. param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE|
  195. NATIVE_PARAMETER_IS_ENABLED|
  196. NATIVE_PARAMETER_IS_OUTPUT);
  197. param.ranges.def = 0.0f;
  198. param.ranges.min = 0.0f;
  199. param.ranges.max = (float)INT64_MAX;
  200. param.unit = "s";
  201. break;
  202. case kParameterInfoPosition:
  203. param.name = "Position";
  204. param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE|
  205. NATIVE_PARAMETER_IS_ENABLED|
  206. NATIVE_PARAMETER_IS_OUTPUT);
  207. param.ranges.def = 0.0f;
  208. param.ranges.min = 0.0f;
  209. param.ranges.max = 100.0f;
  210. param.unit = "%";
  211. break;
  212. case kParameterInfoPoolFill:
  213. param.name = "Pool Fill";
  214. param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE|
  215. NATIVE_PARAMETER_IS_ENABLED|
  216. NATIVE_PARAMETER_IS_OUTPUT);
  217. param.ranges.def = 0.0f;
  218. param.ranges.min = 0.0f;
  219. param.ranges.max = 100.0f;
  220. param.unit = "%";
  221. break;
  222. default:
  223. return nullptr;
  224. }
  225. return &param;
  226. }
  227. float getParameterValue(const uint32_t index) const override
  228. {
  229. switch (index)
  230. {
  231. case kParameterLooping:
  232. return fLoopMode ? 1.0f : 0.0f;
  233. case kParameterHostSync:
  234. return fHostSync ? 1.f : 0.f;
  235. case kParameterEnabled:
  236. return fEnabled ? 1.f : 0.f;
  237. case kParameterVolume:
  238. return fVolume * 100.f;
  239. case kParameterInfoPosition:
  240. return fLastPosition;
  241. case kParameterInfoPoolFill:
  242. return fReadableBufferFill;
  243. case kParameterInfoBitRate:
  244. return static_cast<float>(fReader.getCurrentBitRate());
  245. }
  246. const ADInfo nfo = fReader.getFileInfo();
  247. switch (index)
  248. {
  249. case kParameterInfoChannels:
  250. return static_cast<float>(nfo.channels);
  251. case kParameterInfoBitDepth:
  252. return static_cast<float>(nfo.bit_depth);
  253. case kParameterInfoSampleRate:
  254. return static_cast<float>(nfo.sample_rate);
  255. case kParameterInfoLength:
  256. return static_cast<float>(nfo.length)/1000.f;
  257. }
  258. return 0.f;
  259. }
  260. void setParameterValue(const uint32_t index, const float value) override
  261. {
  262. if (index == kParameterVolume)
  263. {
  264. fVolume = value / 100.f;
  265. return;
  266. }
  267. const bool b = value > 0.5f;
  268. switch (index)
  269. {
  270. case kParameterLooping:
  271. if (fLoopMode != b)
  272. fLoopMode = b;
  273. break;
  274. case kParameterHostSync:
  275. if (fHostSync != b)
  276. {
  277. fInternalTransportFrame = 0;
  278. fHostSync = b;
  279. }
  280. break;
  281. case kParameterEnabled:
  282. if (fEnabled != b)
  283. {
  284. fInternalTransportFrame = 0;
  285. fEnabled = b;
  286. }
  287. break;
  288. default:
  289. break;
  290. }
  291. }
  292. // ----------------------------------------------------------------------------------------------------------------
  293. // Plugin state calls
  294. void setCustomData(const char* const key, const char* const value) override
  295. {
  296. if (std::strcmp(key, "file") != 0)
  297. return;
  298. #ifndef __MOD_DEVICES__
  299. invalidateNextFilename();
  300. #endif
  301. loadFilename(value);
  302. }
  303. #ifndef __MOD_DEVICES__
  304. void setStateFromFile(const char* const filename) override
  305. {
  306. loadFilename(filename);
  307. }
  308. #endif
  309. // ----------------------------------------------------------------------------------------------------------------
  310. // Plugin process calls
  311. #ifndef __MOD_DEVICES__
  312. void process2(const float* const*, float** const outBuffer, const uint32_t frames,
  313. const NativeMidiEvent*, uint32_t) override
  314. #else
  315. void process(const float* const*, float** const outBuffer, const uint32_t frames,
  316. const NativeMidiEvent*, uint32_t) override
  317. #endif
  318. {
  319. float* const out1 = outBuffer[0];
  320. float* const out2 = outBuffer[1];
  321. float* const playCV = outBuffer[2];
  322. if (! fDoProcess)
  323. {
  324. // carla_stderr("P: no process");
  325. carla_zeroFloats(out1, frames);
  326. carla_zeroFloats(out2, frames);
  327. carla_zeroFloats(playCV, frames);
  328. fLastPosition = 0.f;
  329. fReadableBufferFill = 0.f;
  330. return;
  331. }
  332. bool needsIdleRequest = false;
  333. bool playing;
  334. uint64_t framePos;
  335. if (fHostSync)
  336. {
  337. const NativeTimeInfo* const timePos = getTimeInfo();
  338. playing = fEnabled && timePos->playing;
  339. framePos = timePos->frame;
  340. }
  341. else
  342. {
  343. playing = fEnabled;
  344. framePos = fInternalTransportFrame;
  345. if (playing)
  346. fInternalTransportFrame += frames;
  347. }
  348. // not playing
  349. if (! playing)
  350. {
  351. carla_zeroFloats(out1, frames);
  352. carla_zeroFloats(out2, frames);
  353. carla_zeroFloats(playCV, frames);
  354. return;
  355. }
  356. if (fReader.tickFrames(outBuffer, 0, frames, framePos, fLoopMode, isOffline()) && ! fPendingFileRead)
  357. {
  358. fPendingFileRead = true;
  359. needsIdleRequest = true;
  360. }
  361. fLastPosition = fReader.getLastPlayPosition() * 100.f;
  362. fReadableBufferFill = fReader.getReadableBufferFill() * 100.f;
  363. const float volume = fVolume;
  364. if (carla_isNotEqual(volume, 1.0f))
  365. {
  366. carla_multiply(out1, volume, frames);
  367. carla_multiply(out2, volume, frames);
  368. }
  369. #ifndef __MOD_DEVICES__
  370. if (fInlineDisplay.writtenValues < 32)
  371. {
  372. fInlineDisplay.lastValuesL[fInlineDisplay.writtenValues] = carla_findMaxNormalizedFloat(out1, frames);
  373. fInlineDisplay.lastValuesR[fInlineDisplay.writtenValues] = carla_findMaxNormalizedFloat(out2, frames);
  374. ++fInlineDisplay.writtenValues;
  375. }
  376. if (fInlineDisplay.pending == InlineDisplayNotPending)
  377. {
  378. needsIdleRequest = true;
  379. fInlineDisplay.pending = InlineDisplayNeedRequest;
  380. }
  381. #endif
  382. if (needsIdleRequest)
  383. hostRequestIdle();
  384. }
  385. // ----------------------------------------------------------------------------------------------------------------
  386. // Plugin UI calls
  387. void uiShow(const bool show) override
  388. {
  389. if (! show)
  390. return;
  391. if (const char* const filename = uiOpenFile(false, "Open Audio File", ""))
  392. uiCustomDataChanged("file", filename);
  393. uiClosed();
  394. }
  395. // ----------------------------------------------------------------------------------------------------------------
  396. // Plugin dispatcher calls
  397. void idle() override
  398. {
  399. #ifndef __MOD_DEVICES__
  400. NativePluginWithMidiPrograms<FileAudio>::idle();
  401. if (fInlineDisplay.pending == InlineDisplayNeedRequest)
  402. {
  403. fInlineDisplay.pending = InlineDisplayRequesting;
  404. hostQueueDrawInlineDisplay();
  405. }
  406. #endif
  407. if (fPendingFileRead)
  408. {
  409. fPendingFileRead = false;
  410. fReader.readPoll();
  411. }
  412. }
  413. void sampleRateChanged(double) override
  414. {
  415. if (char* const filename = fFilename.releaseBufferPointer())
  416. {
  417. loadFilename(filename);
  418. std::free(filename);
  419. }
  420. }
  421. #ifndef __MOD_DEVICES__
  422. const NativeInlineDisplayImageSurface* renderInlineDisplay(const uint32_t rwidth, const uint32_t height) override
  423. {
  424. CARLA_SAFE_ASSERT_RETURN(height > 4, nullptr);
  425. const uint32_t width = rwidth == height ? height * 4 : rwidth;
  426. /* NOTE the code is this function is not optimized, still learning my way through pixels...
  427. */
  428. const size_t stride = width * 4;
  429. const size_t dataSize = stride * height;
  430. const uint pxToMove = fDoProcess ? fInlineDisplay.writtenValues : 0;
  431. uchar* data = fInlineDisplay.data;
  432. if (fInlineDisplay.dataSize != dataSize || data == nullptr)
  433. {
  434. delete[] data;
  435. data = new uchar[dataSize];
  436. std::memset(data, 0, dataSize);
  437. fInlineDisplay.data = data;
  438. fInlineDisplay.dataSize = dataSize;
  439. }
  440. else if (pxToMove != 0)
  441. {
  442. // shift all previous values to the left
  443. for (uint w=0; w < width - pxToMove; ++w)
  444. for (uint h=0; h < height; ++h)
  445. std::memmove(&data[h * stride + w * 4], &data[h * stride + (w+pxToMove) * 4], 4);
  446. }
  447. fInlineDisplay.width = static_cast<int>(width);
  448. fInlineDisplay.height = static_cast<int>(height);
  449. fInlineDisplay.stride = static_cast<int>(stride);
  450. if (pxToMove != 0)
  451. {
  452. const uint h2 = height / 2;
  453. // clear current line
  454. for (uint w=width-pxToMove; w < width; ++w)
  455. for (uint h=0; h < height; ++h)
  456. memset(&data[h * stride + w * 4], 0, 4);
  457. // draw upper/left
  458. for (uint i=0; i < pxToMove && i < 32; ++i)
  459. {
  460. const float valueL = fInlineDisplay.lastValuesL[i];
  461. const float valueR = fInlineDisplay.lastValuesR[i];
  462. const uint h2L = static_cast<uint>(valueL * (float)h2);
  463. const uint h2R = static_cast<uint>(valueR * (float)h2);
  464. const uint w = width - pxToMove + i;
  465. for (uint h=0; h < h2L; ++h)
  466. {
  467. // -30dB
  468. //if (valueL < 0.032f)
  469. // continue;
  470. data[(h2 - h) * stride + w * 4 + 3] = 160;
  471. // -12dB
  472. if (valueL < 0.25f)
  473. {
  474. data[(h2 - h) * stride + w * 4 + 1] = 255;
  475. }
  476. // -3dB
  477. else if (valueL < 0.70f)
  478. {
  479. data[(h2 - h) * stride + w * 4 + 2] = 255;
  480. data[(h2 - h) * stride + w * 4 + 1] = 255;
  481. }
  482. else
  483. {
  484. data[(h2 - h) * stride + w * 4 + 2] = 255;
  485. }
  486. }
  487. for (uint h=0; h < h2R; ++h)
  488. {
  489. // -30dB
  490. //if (valueR < 0.032f)
  491. // continue;
  492. data[(h2 + h) * stride + w * 4 + 3] = 160;
  493. // -12dB
  494. if (valueR < 0.25f)
  495. {
  496. data[(h2 + h) * stride + w * 4 + 1] = 255;
  497. }
  498. // -3dB
  499. else if (valueR < 0.70f)
  500. {
  501. data[(h2 + h) * stride + w * 4 + 2] = 255;
  502. data[(h2 + h) * stride + w * 4 + 1] = 255;
  503. }
  504. else
  505. {
  506. data[(h2 + h) * stride + w * 4 + 2] = 255;
  507. }
  508. }
  509. }
  510. }
  511. fInlineDisplay.writtenValues = 0;
  512. fInlineDisplay.pending = InlineDisplayNotPending;
  513. return (NativeInlineDisplayImageSurface*)(NativeInlineDisplayImageSurfaceCompat*)&fInlineDisplay;
  514. }
  515. #endif
  516. // ----------------------------------------------------------------------------------------------------------------
  517. private:
  518. bool fLoopMode = true;
  519. #ifdef __MOD_DEVICES__
  520. bool fHostSync = false;
  521. #else
  522. bool fHostSync = true;
  523. #endif
  524. bool fEnabled = true;
  525. bool fDoProcess = false;
  526. bool fPendingFileRead = false;
  527. uint32_t fInternalTransportFrame = 0;
  528. float fLastPosition = 0.f;
  529. float fReadableBufferFill = 0.f;
  530. float fVolume = 1.f;
  531. AudioFileReader fReader;
  532. CarlaString fFilename;
  533. float fPreviewData[108] = {};
  534. #ifndef __MOD_DEVICES__
  535. NativeMidiPrograms fPrograms;
  536. struct InlineDisplay : NativeInlineDisplayImageSurfaceCompat {
  537. float lastValuesL[32] = {};
  538. float lastValuesR[32] = {};
  539. volatile PendingInlineDisplay pending = InlineDisplayNotPending;
  540. volatile uint8_t writtenValues = 0;
  541. InlineDisplay()
  542. : NativeInlineDisplayImageSurfaceCompat() {}
  543. ~InlineDisplay()
  544. {
  545. if (data != nullptr)
  546. {
  547. delete[] data;
  548. data = nullptr;
  549. }
  550. }
  551. CARLA_DECLARE_NON_COPYABLE(InlineDisplay)
  552. CARLA_PREVENT_HEAP_ALLOCATION
  553. } fInlineDisplay;
  554. #endif
  555. void loadFilename(const char* const filename)
  556. {
  557. CARLA_ASSERT(filename != nullptr);
  558. carla_stdout("AudioFilePlugin::loadFilename(\"%s\")", filename);
  559. fDoProcess = false;
  560. fReader.destroy();
  561. fFilename.clear();
  562. if (filename == nullptr || *filename == '\0')
  563. return;
  564. constexpr uint32_t kPreviewDataLen = sizeof(fPreviewData)/sizeof(float);
  565. if (fReader.loadFilename(filename, static_cast<uint32_t>(getSampleRate()), kPreviewDataLen, fPreviewData))
  566. {
  567. fInternalTransportFrame = 0;
  568. fDoProcess = true;
  569. fFilename = filename;
  570. hostSendPreviewBufferData('f', kPreviewDataLen, fPreviewData);
  571. }
  572. }
  573. PluginClassEND(AudioFilePlugin)
  574. static const char* _get_buffer_port_name(NativePluginHandle, const uint32_t index, const bool isOutput)
  575. {
  576. if (!isOutput)
  577. return nullptr;
  578. switch (index)
  579. {
  580. case 0:
  581. return "output_1";
  582. case 1:
  583. return "output_2";
  584. case 2:
  585. return "Play status";
  586. }
  587. return nullptr;
  588. }
  589. static const NativePortRange* _get_buffer_port_range(NativePluginHandle, const uint32_t index, const bool isOutput)
  590. {
  591. if (!isOutput || index != 2)
  592. return nullptr;
  593. static NativePortRange npr = { 0.f, 10.f };
  594. return &npr;
  595. }
  596. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AudioFilePlugin)
  597. };
  598. // --------------------------------------------------------------------------------------------------------------------
  599. CARLA_API_EXPORT
  600. void carla_register_native_plugin_audiofile();
  601. CARLA_API_EXPORT
  602. void carla_register_native_plugin_audiofile()
  603. {
  604. static const NativePluginDescriptor audiofileDesc = {
  605. /* category */ NATIVE_PLUGIN_CATEGORY_UTILITY,
  606. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE
  607. #ifndef __MOD_DEVICES__
  608. |NATIVE_PLUGIN_HAS_INLINE_DISPLAY
  609. #endif
  610. |NATIVE_PLUGIN_HAS_UI
  611. |NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE
  612. |NATIVE_PLUGIN_REQUESTS_IDLE
  613. |NATIVE_PLUGIN_USES_CONTROL_VOLTAGE
  614. |NATIVE_PLUGIN_USES_TIME),
  615. /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING,
  616. /* audioIns */ 0,
  617. /* audioOuts */ 2,
  618. /* midiIns */ 0,
  619. /* midiOuts */ 0,
  620. /* paramIns */ 1,
  621. /* paramOuts */ 0,
  622. /* name */ "Audio File",
  623. /* label */ "audiofile",
  624. /* maker */ "falkTX",
  625. /* copyright */ "GNU GPL v2+",
  626. AudioFilePlugin::_instantiate,
  627. AudioFilePlugin::_cleanup,
  628. AudioFilePlugin::_get_parameter_count,
  629. AudioFilePlugin::_get_parameter_info,
  630. AudioFilePlugin::_get_parameter_value,
  631. AudioFilePlugin::_get_midi_program_count,
  632. AudioFilePlugin::_get_midi_program_info,
  633. AudioFilePlugin::_set_parameter_value,
  634. AudioFilePlugin::_set_midi_program,
  635. AudioFilePlugin::_set_custom_data,
  636. AudioFilePlugin::_ui_show,
  637. AudioFilePlugin::_ui_idle,
  638. AudioFilePlugin::_ui_set_parameter_value,
  639. AudioFilePlugin::_ui_set_midi_program,
  640. AudioFilePlugin::_ui_set_custom_data,
  641. AudioFilePlugin::_activate,
  642. AudioFilePlugin::_deactivate,
  643. AudioFilePlugin::_process,
  644. AudioFilePlugin::_get_state,
  645. AudioFilePlugin::_set_state,
  646. AudioFilePlugin::_dispatcher,
  647. AudioFilePlugin::_render_inline_display,
  648. /* cvIns */ 0,
  649. /* cvOuts */ 1,
  650. AudioFilePlugin::_get_buffer_port_name,
  651. AudioFilePlugin::_get_buffer_port_range,
  652. /* ui_width */ 0,
  653. /* ui_height */ 0
  654. };
  655. carla_register_native_plugin(&audiofileDesc);
  656. }
  657. // --------------------------------------------------------------------------------------------------------------------