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.

198 lines
5.9KB

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