-
-
Notifications
You must be signed in to change notification settings - Fork 99
Expand file tree
/
Copy pathPluginProcessor.h
More file actions
297 lines (216 loc) · 9.04 KB
/
PluginProcessor.h
File metadata and controls
297 lines (216 loc) · 9.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
/*
// Copyright (c) 2021-2025 Timothy Schoen
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
// WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*/
#pragma once
#include <juce_audio_processors/juce_audio_processors.h>
#include <juce_audio_devices/juce_audio_devices.h>
#include <juce_dsp/juce_dsp.h>
#if PERFETTO
# include <melatonin_perfetto/melatonin_perfetto.h>
#endif
#include "Utility/Config.h"
#include "Utility/Limiter.h"
#include "Utility/SettingsFile.h"
#include "Utility/AudioMidiFifo.h"
#include "Utility/SeqLock.h"
#include "Utility/MidiDeviceManager.h"
#include "Pd/Instance.h"
#include "Pd/Patch.h"
namespace pd {
class Library;
}
class PlugDataParameter;
class Autosave;
class InternalSynth;
class Recorder;
class SettingsFile;
class ToolbarSource;
struct PlugDataLook;
class PluginEditor;
class ConnectionMessageDisplay;
class Object;
class PluginProcessor final : public AudioProcessor
, public pd::Instance
, public SettingsFileListener {
public:
PluginProcessor();
~PluginProcessor() override;
static AudioProcessor::BusesProperties buildBusesProperties();
void setOversampling(int amount);
void setLimiterThreshold(int amount);
void setEnableLimiter(bool enabled);
bool getEnableLimiter();
void prepareToPlay(double sampleRate, int samplesPerBlock) override;
void numChannelsChanged() override;
void releaseResources() override { }
void updateAllEditorsLNF();
void flushMessageQueue();
void doubleFlushMessageQueue();
#ifndef JucePlugin_PreferredChannelConfigurations
bool isBusesLayoutSupported(BusesLayout const& layouts) const override;
#endif
void processBlock(AudioBuffer<float>&, MidiBuffer&) override;
void processBlockBypassed(AudioBuffer<float>& buffer, MidiBuffer&) override;
AudioProcessorEditor* createEditor() override;
bool hasEditor() const override;
String const getName() const override;
bool acceptsMidi() const override;
bool producesMidi() const override;
bool isMidiEffect() const override;
double getTailLengthSeconds() const override;
int getNumPrograms() override;
int getCurrentProgram() override;
void setCurrentProgram(int index) override;
String const getProgramName(int index) override;
void changeProgramName(int index, String const& newName) override;
void getStateInformation(MemoryBlock& destData) override;
void setStateInformation(void const* data, int sizeInBytes) override;
String findLostPatch(String const& name) const;
pd::Patch::Ptr findPatchInPluginMode(int editorIndex);
void receiveNoteOn(int channel, int pitch, int velocity) override;
void receiveControlChange(int channel, int controller, int value) override;
void receiveProgramChange(int channel, int value) override;
void receivePitchBend(int channel, int value) override;
void receiveAftertouch(int channel, int value) override;
void receivePolyAftertouch(int channel, int pitch, int value) override;
void receiveMidiByte(int port, int byte) override;
void receiveSysMessage(SmallString const& selector, SmallArray<pd::Atom> const& list) override;
void addTextToTextEditor(uint64_t ptr, SmallString const& text) override;
void hideTextEditorDialog(uint64_t ptr) override;
void showTextEditorDialog(uint64_t ptr, SmallString const& title, std::function<void(String, uint64_t)> save, std::function<void(uint64_t)> close) override;
void raiseTextEditorDialog(uint64_t ptr) override;
void clearTextEditor(uint64_t ptr) override;
bool isTextEditorDialogShown(uint64_t ptr) override;
void updateConsole(SmallString const& message, bool isWarning, int numMessages, bool newWarning) override;
void reloadAbstractions(File changedPatch, t_glist* except) override;
void processConstant(dsp::AudioBlock<float>);
void processVariable(dsp::AudioBlock<float>, MidiBuffer& midiBuffer);
MidiDeviceManager& getMidiDeviceManager();
bool canAddBus(bool isInput) const override
{
return true;
}
bool canRemoveBus(bool const isInput) const override
{
int const nbus = getBusCount(isInput);
return nbus > 0;
}
void settingsChanged(String const& name, var const& value) override;
void settingsFileReloaded() override;
static bool initialiseFilesystem();
#if JUCE_IOS
static void syncDirectoryFiles(File const& sourceDir, File const& targetDir, Time lastInitTime = Time(), bool deleteIfNotExists = false);
#endif
void updateSearchPaths();
void sendMidiBuffer(int device, MidiBuffer const& buffer);
void sendPlayhead();
void sendParameters();
void updateEnabledParameters();
SmallArray<PlugDataParameter*> getEnabledParameters();
SmallArray<PluginEditor*> getEditors() const;
void enableAudioParameter(SmallString const& name);
void disableAudioParameter(SmallString const& name);
void handleParameterMessage(SmallArray<pd::Atom> const& atoms) override;
void performLatencyCompensationChange(float value) override;
void sendParameterInfoChangeMessage();
void fillDataBuffer(SmallArray<pd::Atom> const& list) override;
void parseDataBuffer(XmlElement const& xml) override;
std::unique_ptr<XmlElement> extraData;
pd::Patch::Ptr loadPatch(String patch);
pd::Patch::Ptr loadPatch(URL const& patchURL);
void titleChanged() override;
void setTheme(String themeToUse, bool force = false);
void runBackupLoop();
bool toggleRecording(PluginEditor* editor);
int lastUIWidth = 1000, lastUIHeight = 660;
AtomicValue<float>* volume;
DynamicObject::Ptr pluginModeTheme;
float pluginModeScale = 1.0f;
String currentThemeName;
SettingsFile* settingsFile;
std::unique_ptr<pd::Library> objectLibrary;
File abstractions = ProjectInfo::versionDataDir.getChildFile("Abstractions");
Value commandLocked = Value(var(false));
std::unique_ptr<ToolbarSource> toolbarSource;
Value tailLength = Value(0.0f);
// Just so we never have to deal with deleting the default LnF
SharedResourcePointer<PlugDataLook> lnf;
static constexpr int numParameters = 512;
static constexpr int numInputBuses = 16;
static constexpr int numOutputBuses = 16;
// Protected mode value will decide if we apply clipping to output and remove non-finite numbers
AtomicValue<bool> enableLimiter = true;
// Zero means no oversampling
AtomicValue<int> oversampling = 0;
std::unique_ptr<InternalSynth> internalSynth;
OwnedArray<PluginEditor> openedEditors;
AtomicValue<ConnectionMessageDisplay*, Sequential> connectionListener = nullptr;
std::unique_ptr<Autosave> autosave;
private:
int customLatencySamples = 0;
SmoothedValue<float> smoothedGain;
AtomicValue<int> audioAdvancement = 0;
bool variableBlockSize = false;
AudioBuffer<float> audioBufferIn;
AudioBuffer<float> audioBufferOut;
AudioBuffer<float> bypassBuffer;
HeapArray<float> audioVectorIn;
HeapArray<float> audioVectorOut;
std::unique_ptr<AudioMidiFifo> inputFifo;
std::unique_ptr<AudioMidiFifo> outputFifo;
MidiBuffer blockMidiBuffer;
MidiBuffer midiBufferInternalSynth;
MidiDeviceManager midiDeviceManager;
AudioProcessLoadMeasurer cpuLoadMeasurer;
bool midiByteIsSysex = false;
uint8 midiByteBuffer[512] = { };
size_t midiByteIndex = 0;
SmallArray<pd::Atom> atoms_playhead;
SmallArray<PlugDataParameter*> enabledParameters;
int lastSetProgram = 0;
Limiter limiter;
std::unique_ptr<dsp::Oversampling<float>> oversampler;
UnorderedMap<uint64_t, std::unique_ptr<Component>> textEditorDialogs;
#if PERFETTO
std::unique_ptr<perfetto::TracingSession> tracingSession;
#endif
static inline String const else_version = "ELSE v1.0-rc14";
static inline String const cyclone_version = "cyclone v0.9-4";
static inline String const heavylib_version = "heavylib v0.4.1";
static inline String const gem_version = "Gem v0.94";
// this gets updated with live version data later
static String pdlua_version;
class HostInfoUpdater final : public AsyncUpdater {
public:
explicit HostInfoUpdater(PluginProcessor* parentProcessor)
: processor(*parentProcessor)
{
}
void update()
{
if (ProjectInfo::isStandalone)
return;
#if JUCE_IOS
handleAsyncUpdate(); // iOS doesn't like it if we do this asynchronously
#else
triggerAsyncUpdate();
#endif
}
private:
void handleAsyncUpdate() override
{
auto const details = AudioProcessorListener::ChangeDetails { }.withParameterInfoChanged(true);
processor.updateHostDisplay(details);
}
PluginProcessor& processor;
};
HostInfoUpdater hostInfoUpdater;
int backupRunLoopInterval;
TimedCallback backupRunLoop = TimedCallback([this] { runBackupLoop(); });
CriticalSection backupLoopLock;
std::atomic<bool> isProcessingAudio;
std::unique_ptr<Recorder> recorder;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginProcessor)
};