2 * Carla Native Plugin API (C++)
3 * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com>
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.
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.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #ifndef CARLA_NATIVE_PROGRAMS_HPP_INCLUDED
19 #define CARLA_NATIVE_PROGRAMS_HPP_INCLUDED
21 #include "CarlaNative.hpp"
23 #include "CarlaMathUtils.hpp"
24 #include "CarlaMutex.hpp"
26 #include "water/files/File.h"
27 #include "water/memory/SharedResourcePointer.h"
28 #include "water/text/StringArray.h"
31 using water::SharedResourcePointer
;
33 using water::StringArray
;
36 * @defgroup CarlaNativeAPI Carla Native API
40 // -----------------------------------------------------------------------
49 template <FileType fileType
>
50 struct NativePluginPresetManager
{
51 StringArray filenames
;
53 NativePluginPresetManager(const char* const paths
, const char* const wildcard
)
56 CARLA_SAFE_ASSERT_RETURN(wildcard
!= nullptr,);
58 if (paths
== nullptr || paths
[0] == '\0' || wildcard
[0] == '\0')
61 const StringArray
splitPaths(StringArray::fromTokens(paths
, CARLA_OS_SPLIT_STR
, ""));
63 for (String
*it
= splitPaths
.begin(), *end
= splitPaths
.end(); it
!= end
; ++it
)
65 std::vector
<File
> results
;
67 if (const uint count
= File(*it
).findChildFiles(results
, File::findFiles
|File::ignoreHiddenFiles
, true, wildcard
))
69 for (uint i
=0; i
<count
; ++i
)
70 filenames
.add(results
[i
].getFullPathName());
78 // -----------------------------------------------------------------------
79 // Native Plugin with MIDI programs class
81 template <FileType fileType
>
82 class NativePluginWithMidiPrograms
: public NativePluginClass
85 typedef NativePluginPresetManager
<fileType
> NativePluginPresetManagerType
;
86 typedef SharedResourcePointer
<NativePluginPresetManagerType
> NativeMidiPrograms
;
88 NativePluginWithMidiPrograms(const NativeHostDescriptor
* const host
,
89 const NativeMidiPrograms
& programs
,
90 const uint32_t numOutputs
)
91 : NativePluginClass(host
),
93 fRetMidiProgramName(),
94 fNextFilename(nullptr),
95 fProgramChangeMutex(),
97 kNumOutputs(numOutputs
) {}
100 // -------------------------------------------------------------------
101 // New Plugin program calls
103 virtual void setStateFromFile(const char* filename
) = 0;
104 virtual void process2(const float* const* inBuffer
, float** outBuffer
, uint32_t frames
,
105 const NativeMidiEvent
* midiEvents
, uint32_t midiEventCount
) = 0;
107 void invalidateNextFilename() noexcept
109 const CarlaMutexLocker
cml(fProgramChangeMutex
);
110 fNextFilename
= nullptr;
113 // -------------------------------------------------------------------
114 // Plugin midi-program calls
116 uint32_t getMidiProgramCount() const override
118 const NativePluginPresetManagerType
& pm(kPrograms
.get());
119 return static_cast<uint32_t>(pm
.filenames
.size());
122 const NativeMidiProgram
* getMidiProgramInfo(const uint32_t uindex
) const override
124 const int index
= static_cast<int>(uindex
);
126 const NativePluginPresetManagerType
& pm(kPrograms
.get());
127 CARLA_SAFE_ASSERT_RETURN(index
< pm
.filenames
.size(), nullptr);
129 fRetMidiProgramName
= File(pm
.filenames
.strings
.getUnchecked(index
)).getFileNameWithoutExtension();
131 fRetMidiProgram
.bank
= 0;
132 fRetMidiProgram
.program
= uindex
;
133 fRetMidiProgram
.name
= fRetMidiProgramName
.toRawUTF8();
135 return &fRetMidiProgram
;
138 // -------------------------------------------------------------------
139 // Plugin state calls
141 void setMidiProgram(const uint8_t, const uint32_t, const uint32_t program
) override
143 const int iprogram
= static_cast<int>(program
);
145 const NativePluginPresetManagerType
& pm(kPrograms
.get());
146 CARLA_SAFE_ASSERT_RETURN(iprogram
< pm
.filenames
.size(),);
148 const char* const filename(pm
.filenames
.strings
.getUnchecked(iprogram
).toRawUTF8());
150 const CarlaMutexLocker
cml(fProgramChangeMutex
);
154 setStateFromFile(filename
);
158 fNextFilename
= filename
;
163 // -------------------------------------------------------------------
164 // Plugin process calls
166 void process(const float* const* const inBuffer
, float** const outBuffer
, uint32_t frames
,
167 const NativeMidiEvent
* const midiEvents
, const uint32_t midiEventCount
) override
169 const CarlaMutexTryLocker
cmtl(fProgramChangeMutex
, isOffline());
171 if (cmtl
.wasLocked())
173 process2(inBuffer
, outBuffer
, frames
, midiEvents
, midiEventCount
);
177 for (uint32_t i
=0; i
<kNumOutputs
; ++i
)
178 carla_zeroFloats(outBuffer
[i
], frames
);
182 // -------------------------------------------------------------------
183 // Plugin dispatcher calls
187 if (const char* const filename
= fNextFilename
)
189 const CarlaMutexLocker
cml(fProgramChangeMutex
);
191 fNextFilename
= nullptr;
192 setStateFromFile(filename
);
197 mutable NativeMidiProgram fRetMidiProgram
;
198 mutable String fRetMidiProgramName
;
199 const char* fNextFilename
;
200 CarlaMutex fProgramChangeMutex
;
201 const NativeMidiPrograms
& kPrograms
;
202 const uint32_t kNumOutputs
;
204 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NativePluginWithMidiPrograms
)
209 // -----------------------------------------------------------------------
211 #endif // CARLA_NATIVE_PROGRAMS_HPP_INCLUDED