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.

213 lines
6.5KB

  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* const* inBuffer, float** outBuffer, uint32_t frames,
  86. const NativeMidiEvent* midiEvents, uint32_t midiEventCount) = 0;
  87. void invalidateNextFilename() noexcept
  88. {
  89. const CarlaMutexLocker cml(fProgramChangeMutex);
  90. fNextFilename = nullptr;
  91. }
  92. // -------------------------------------------------------------------
  93. // Plugin midi-program calls
  94. uint32_t getMidiProgramCount() const override
  95. {
  96. const NativePluginPresetManagerType& pm(kPrograms.get());
  97. return static_cast<uint32_t>(pm.filenames.size());
  98. }
  99. const NativeMidiProgram* getMidiProgramInfo(const uint32_t uindex) const override
  100. {
  101. const int index = static_cast<int>(uindex);
  102. const NativePluginPresetManagerType& pm(kPrograms.get());
  103. CARLA_SAFE_ASSERT_RETURN(index < pm.filenames.size(), nullptr);
  104. fRetMidiProgramName = File(pm.filenames.strings.getUnchecked(index)).getFileNameWithoutExtension();
  105. fRetMidiProgram.bank = 0;
  106. fRetMidiProgram.program = uindex;
  107. fRetMidiProgram.name = fRetMidiProgramName.toRawUTF8();
  108. return &fRetMidiProgram;
  109. }
  110. // -------------------------------------------------------------------
  111. // Plugin state calls
  112. void setMidiProgram(const uint8_t, const uint32_t, const uint32_t program) override
  113. {
  114. const int iprogram = static_cast<int>(program);
  115. const NativePluginPresetManagerType& pm(kPrograms.get());
  116. CARLA_SAFE_ASSERT_RETURN(iprogram < pm.filenames.size(),);
  117. const char* const filename(pm.filenames.strings.getUnchecked(iprogram).toRawUTF8());
  118. const CarlaMutexLocker cml(fProgramChangeMutex);
  119. if (isOffline())
  120. {
  121. setStateFromFile(filename);
  122. }
  123. else
  124. {
  125. fNextFilename = filename;
  126. hostRequestIdle();
  127. }
  128. }
  129. // -------------------------------------------------------------------
  130. // Plugin process calls
  131. void process(const float* const* const inBuffer, float** const outBuffer, uint32_t frames,
  132. const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override
  133. {
  134. const CarlaMutexTryLocker cmtl(fProgramChangeMutex, isOffline());
  135. if (cmtl.wasLocked())
  136. {
  137. process2(inBuffer, outBuffer, frames, midiEvents, midiEventCount);
  138. }
  139. else
  140. {
  141. for (uint32_t i=0; i<kNumOutputs; ++i)
  142. carla_zeroFloats(outBuffer[i], frames);
  143. }
  144. }
  145. // -------------------------------------------------------------------
  146. // Plugin dispatcher calls
  147. void idle() override
  148. {
  149. if (const char* const filename = fNextFilename)
  150. {
  151. const CarlaMutexLocker cml(fProgramChangeMutex);
  152. fNextFilename = nullptr;
  153. setStateFromFile(filename);
  154. }
  155. }
  156. private:
  157. mutable NativeMidiProgram fRetMidiProgram;
  158. mutable String fRetMidiProgramName;
  159. const char* fNextFilename;
  160. CarlaMutex fProgramChangeMutex;
  161. const NativeMidiPrograms& kPrograms;
  162. const uint32_t kNumOutputs;
  163. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NativePluginWithMidiPrograms)
  164. };
  165. /**@}*/
  166. // -----------------------------------------------------------------------
  167. #endif // CARLA_NATIVE_PROGRAMS_HPP_INCLUDED