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.

207 lines
6.3KB

  1. /*
  2. * Carla Native Plugin API (C++)
  3. * Copyright (C) 2012-2019 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. #ifndef CARLA_NATIVE_PROGRAMS_HPP_INCLUDED
  18. #define CARLA_NATIVE_PROGRAMS_HPP_INCLUDED
  19. #include "CarlaNative.hpp"
  20. #include "CarlaMathUtils.hpp"
  21. #include "CarlaMutex.hpp"
  22. #include "water/files/File.h"
  23. #include "water/memory/SharedResourcePointer.h"
  24. #include "water/text/StringArray.h"
  25. using water::Array;
  26. using water::File;
  27. using water::SharedResourcePointer;
  28. using water::String;
  29. using water::StringArray;
  30. /*!
  31. * @defgroup CarlaNativeAPI Carla Native API
  32. * @{
  33. */
  34. // -----------------------------------------------------------------------
  35. // ...
  36. enum FileType {
  37. FileNone,
  38. FileAudio,
  39. FileMIDI,
  40. };
  41. template <FileType fileType>
  42. struct NativePluginPresetManager {
  43. StringArray filenames;
  44. NativePluginPresetManager(const char* const paths, const char* const wildcard)
  45. : filenames()
  46. {
  47. CARLA_SAFE_ASSERT_RETURN(wildcard != nullptr,);
  48. if (paths == nullptr || paths[0] == '\0' || wildcard[0] == '\0')
  49. return;
  50. const StringArray splitPaths(StringArray::fromTokens(paths, CARLA_OS_SPLIT_STR, ""));
  51. for (String *it = splitPaths.begin(), *end = splitPaths.end(); it != end; ++it)
  52. {
  53. Array<File> results;
  54. if (File(*it).findChildFiles(results, File::findFiles|File::ignoreHiddenFiles, true, wildcard) > 0)
  55. {
  56. for (File *it2 = results.begin(), *end2 = results.end(); it2 != end2; ++it2)
  57. filenames.add(it2->getFullPathName());
  58. }
  59. }
  60. filenames.sort(true);
  61. }
  62. };
  63. // -----------------------------------------------------------------------
  64. // Native Plugin with MIDI programs class
  65. template <FileType fileType>
  66. class NativePluginWithMidiPrograms : public NativePluginClass
  67. {
  68. public:
  69. typedef NativePluginPresetManager<fileType> NativePluginPresetManagerType;
  70. typedef SharedResourcePointer<NativePluginPresetManagerType> NativeMidiPrograms;
  71. NativePluginWithMidiPrograms(const NativeHostDescriptor* const host,
  72. const NativeMidiPrograms& programs,
  73. const uint32_t numOutputs)
  74. : NativePluginClass(host),
  75. fRetMidiProgram(),
  76. fRetMidiProgramName(),
  77. fNextFilename(nullptr),
  78. fProgramChangeMutex(),
  79. kPrograms(programs),
  80. kNumOutputs(numOutputs) {}
  81. protected:
  82. // -------------------------------------------------------------------
  83. // New Plugin program calls
  84. virtual void setStateFromFile(const char* filename) = 0;
  85. virtual void process2(const float** inBuffer, float** outBuffer, uint32_t frames,
  86. const NativeMidiEvent* midiEvents, uint32_t midiEventCount) = 0;
  87. // -------------------------------------------------------------------
  88. // Plugin midi-program calls
  89. uint32_t getMidiProgramCount() const override
  90. {
  91. const NativePluginPresetManager<fileType>& pm(kPrograms.get());
  92. return static_cast<uint32_t>(pm.filenames.size());
  93. }
  94. const NativeMidiProgram* getMidiProgramInfo(const uint32_t uindex) const override
  95. {
  96. const int index = static_cast<int>(uindex);
  97. const NativePluginPresetManager<fileType>& pm(kPrograms.get());
  98. CARLA_SAFE_ASSERT_RETURN(index < pm.filenames.size(), nullptr);
  99. fRetMidiProgramName = File(pm.filenames.strings.getUnchecked(index)).getFileNameWithoutExtension();
  100. fRetMidiProgram.bank = 0;
  101. fRetMidiProgram.program = uindex;
  102. fRetMidiProgram.name = fRetMidiProgramName.toRawUTF8();
  103. return &fRetMidiProgram;
  104. }
  105. // -------------------------------------------------------------------
  106. // Plugin state calls
  107. void setMidiProgram(const uint8_t, const uint32_t, const uint32_t program) override
  108. {
  109. const int iprogram = static_cast<int>(program);
  110. const NativePluginPresetManager<fileType>& pm(kPrograms.get());
  111. CARLA_SAFE_ASSERT_RETURN(iprogram < pm.filenames.size(),);
  112. const char* const filename(pm.filenames.strings.getUnchecked(iprogram).toRawUTF8());
  113. const CarlaMutexLocker cml(fProgramChangeMutex);
  114. if (isOffline())
  115. {
  116. setStateFromFile(filename);
  117. }
  118. else
  119. {
  120. fNextFilename = filename;
  121. hostRequestIdle();
  122. }
  123. }
  124. // -------------------------------------------------------------------
  125. // Plugin process calls
  126. void process(const float** const inBuffer, float** const outBuffer, uint32_t frames,
  127. const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override
  128. {
  129. const CarlaMutexTryLocker cmtl(fProgramChangeMutex, isOffline());
  130. if (cmtl.wasLocked())
  131. {
  132. process2(inBuffer, outBuffer, frames, midiEvents, midiEventCount);
  133. }
  134. else
  135. {
  136. for (uint32_t i=0; i<kNumOutputs; ++i)
  137. carla_zeroFloats(outBuffer[i], frames);
  138. }
  139. }
  140. // -------------------------------------------------------------------
  141. // Plugin dispatcher calls
  142. void idle() override
  143. {
  144. if (const char* const filename = fNextFilename)
  145. {
  146. const CarlaMutexLocker cml(fProgramChangeMutex);
  147. fNextFilename = nullptr;
  148. setStateFromFile(filename);
  149. }
  150. }
  151. private:
  152. mutable NativeMidiProgram fRetMidiProgram;
  153. mutable String fRetMidiProgramName;
  154. const char* fNextFilename;
  155. CarlaMutex fProgramChangeMutex;
  156. const NativeMidiPrograms& kPrograms;
  157. const uint32_t kNumOutputs;
  158. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NativePluginWithMidiPrograms)
  159. };
  160. /**@}*/
  161. // -----------------------------------------------------------------------
  162. #endif // CARLA_NATIVE_PROGRAMS_HPP_INCLUDED