Cleanup
[carla.git] / source / native-plugins / bigmeter.cpp
blob387148e47b1f67b892e80d80ba3b0bed033a0d3d
1 /*
2 * Carla Native Plugins
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 #include "CarlaDefines.h"
20 #include "CarlaMathUtils.hpp"
21 #include "CarlaNativeExtUI.hpp"
23 #include "water/maths/MathsFunctions.h"
25 using water::roundToIntAccurate;
27 // -----------------------------------------------------------------------
29 class BigMeterPlugin : public NativePluginAndUiClass
31 public:
32 BigMeterPlugin(const NativeHostDescriptor* const host)
33 : NativePluginAndUiClass(host, "bigmeter-ui"),
34 fColor(1),
35 fStyle(1),
36 fOutLeft(0.0f),
37 fOutRight(0.0f),
38 fInlineDisplay() {}
40 protected:
41 // -------------------------------------------------------------------
42 // Plugin parameter calls
44 uint32_t getParameterCount() const override
46 return 4;
49 const NativeParameter* getParameterInfo(const uint32_t index) const override
51 CARLA_SAFE_ASSERT_RETURN(index < 4, nullptr);
53 static NativeParameter param;
54 static NativeParameterScalePoint scalePoints[3];
56 int hints = NATIVE_PARAMETER_IS_ENABLED|NATIVE_PARAMETER_IS_AUTOMATABLE;
58 param.name = nullptr;
59 param.unit = nullptr;
60 param.ranges.def = 0.0f;
61 param.ranges.min = 0.0f;
62 param.ranges.max = 1.0f;
63 param.ranges.step = 1.0f;
64 param.ranges.stepSmall = 1.0f;
65 param.ranges.stepLarge = 1.0f;
66 param.scalePointCount = 0;
67 param.scalePoints = nullptr;
69 switch (index)
71 case 0:
72 hints |= NATIVE_PARAMETER_IS_INTEGER|NATIVE_PARAMETER_USES_SCALEPOINTS;
73 param.name = "Color";
74 param.ranges.def = 1.0f;
75 param.ranges.min = 1.0f;
76 param.ranges.max = 2.0f;
77 scalePoints[0].value = 1.0f;
78 scalePoints[0].label = "Green";
79 scalePoints[1].value = 2.0f;
80 scalePoints[1].label = "Blue";
81 param.scalePointCount = 2;
82 param.scalePoints = scalePoints;
83 break;
84 case 1:
85 hints |= NATIVE_PARAMETER_IS_INTEGER|NATIVE_PARAMETER_USES_SCALEPOINTS;
86 param.name = "Style";
87 param.ranges.def = 1.0f;
88 param.ranges.min = 1.0f;
89 param.ranges.max = 3.0f;
90 scalePoints[0].value = 1.0f;
91 scalePoints[0].label = "Default";
92 scalePoints[1].value = 2.0f;
93 scalePoints[1].label = "OpenAV";
94 scalePoints[2].value = 3.0f;
95 scalePoints[2].label = "RNCBC";
96 param.scalePointCount = 3;
97 param.scalePoints = scalePoints;
98 break;
99 case 2:
100 hints |= NATIVE_PARAMETER_IS_OUTPUT;
101 param.name = "Out Left";
102 break;
103 case 3:
104 hints |= NATIVE_PARAMETER_IS_OUTPUT;
105 param.name = "Out Right";
106 break;
109 param.hints = static_cast<NativeParameterHints>(hints);
111 return &param;
114 float getParameterValue(const uint32_t index) const override
116 switch (index)
118 case 0:
119 return float(fColor);
120 case 1:
121 return float(fStyle);
122 case 2:
123 return fOutLeft;
124 case 3:
125 return fOutRight;
126 default:
127 return 0.0f;
131 // -------------------------------------------------------------------
132 // Plugin state calls
134 void setParameterValue(const uint32_t index, const float value) override
136 switch (index)
138 case 0:
139 fColor = roundToIntAccurate(value);
140 break;
141 case 1:
142 fStyle = roundToIntAccurate(value);
143 break;
144 default:
145 break;
149 // -------------------------------------------------------------------
150 // Plugin process calls
152 void activate() override
154 fOutLeft = 0.0f;
155 fOutRight = 0.0f;
158 void process(const float* const* inputs, float**, const uint32_t frames,
159 const NativeMidiEvent* const, const uint32_t) override
161 fOutLeft = carla_findMaxNormalizedFloat(inputs[0], frames);
162 fOutRight = carla_findMaxNormalizedFloat(inputs[1], frames);
164 bool needsInlineRender = fInlineDisplay.pending < 0;
166 if (carla_isNotEqual(fOutLeft, fInlineDisplay.lastLeft))
168 fInlineDisplay.lastLeft = fOutLeft;
169 needsInlineRender = true;
172 if (carla_isNotEqual(fOutRight, fInlineDisplay.lastRight))
174 fInlineDisplay.lastRight = fOutRight;
175 needsInlineRender = true;
178 if (needsInlineRender && fInlineDisplay.pending != 1 && fInlineDisplay.pending != 2)
180 fInlineDisplay.pending = 1;
181 hostRequestIdle();
185 // -------------------------------------------------------------------
186 // Plugin dispatcher calls
188 void idle() override
190 if (fInlineDisplay.pending == 1)
192 fInlineDisplay.pending = 2;
193 hostQueueDrawInlineDisplay();
197 const NativeInlineDisplayImageSurface* renderInlineDisplay(const uint32_t rwidth, const uint32_t height) override
199 CARLA_SAFE_ASSERT_RETURN(rwidth > 0 && height > 0, nullptr);
201 const uint32_t width = rwidth == height ? height / 6 : rwidth;
202 const size_t stride = width * 4;
203 const size_t dataSize = stride * height;
205 uchar* data = fInlineDisplay.data;
207 if (fInlineDisplay.dataSize < dataSize || data == nullptr)
209 delete[] data;
210 data = new uchar[dataSize];
211 std::memset(data, 0, dataSize);
212 fInlineDisplay.data = data;
213 fInlineDisplay.dataSize = dataSize;
216 std::memset(data, 0, dataSize);
218 fInlineDisplay.width = static_cast<int>(width);
219 fInlineDisplay.height = static_cast<int>(height);
220 fInlineDisplay.stride = static_cast<int>(stride);
222 const uint heightValueLeft = static_cast<uint>(fInlineDisplay.lastLeft * static_cast<float>(height));
223 const uint heightValueRight = static_cast<uint>(fInlineDisplay.lastRight * static_cast<float>(height));
225 for (uint h=0; h < height; ++h)
227 for (uint w=0; w < width; ++w)
229 // data[h * stride + w * 4 + 0] = 0;
230 // data[h * stride + w * 4 + 1] = 255;
231 // data[h * stride + w * 4 + 2] = 0;
232 data[h * stride + w * 4 + 3] = 160;
236 for (uint h=0; h < heightValueLeft; ++h)
238 const uint h2 = height - h - 1;
240 for (uint w=0; w < width / 2; ++w)
242 data[h2 * stride + w * 4 + 0] = 200;
243 data[h2 * stride + w * 4 + 1] = 0;
244 data[h2 * stride + w * 4 + 2] = 0;
245 data[h2 * stride + w * 4 + 3] = 255;
249 for (uint h=0; h < heightValueRight; ++h)
251 const uint h2 = height - h - 1;
253 for (uint w=width / 2; w < width; ++w)
255 data[h2 * stride + w * 4 + 0] = 200;
256 data[h2 * stride + w * 4 + 1] = 0;
257 data[h2 * stride + w * 4 + 2] = 0;
258 data[h2 * stride + w * 4 + 3] = 255;
262 // draw 1px border
263 for (uint w=0; w < width; ++w)
265 // data[w * 4 + 0] = 0;
266 // data[w * 4 + 1] = 0;
267 // data[w * 4 + 2] = 255;
268 data[w * 4 + 3] = 120;
270 // data[(height - 1) * stride + w * 4 + 0] = 0;
271 // data[(height - 1) * stride + w * 4 + 1] = 0;
272 // data[(height - 1) * stride + w * 4 + 2] = 255;
273 data[(height - 1) * stride + w * 4 + 3] = 120;
276 for (uint h=0; h < height; ++h)
278 // data[h * stride + 0] = 0;
279 // data[h * stride + 1] = 0;
280 // data[h * stride + 2] = 255;
281 data[h * stride + 3] = 120;
283 data[h * stride + (width / 2) * 4 + 0] = 0;
284 data[h * stride + (width / 2) * 4 + 1] = 0;
285 data[h * stride + (width / 2) * 4 + 2] = 0;
286 data[h * stride + (width / 2) * 4 + 3] = 160;
288 // data[h * stride + (width - 1) * 4 + 0] = 0;
289 // data[h * stride + (width - 1) * 4 + 1] = 0;
290 // data[h * stride + (width - 1) * 4 + 2] = 255;
291 data[h * stride + (width - 1) * 4 + 3] = 120;
294 fInlineDisplay.pending = rwidth == height ? -1 : 0;
295 return (NativeInlineDisplayImageSurface*)(NativeInlineDisplayImageSurfaceCompat*)&fInlineDisplay;
298 private:
299 int fColor, fStyle;
300 float fOutLeft, fOutRight;
302 struct InlineDisplay : NativeInlineDisplayImageSurfaceCompat {
303 float lastLeft;
304 float lastRight;
305 volatile int pending;
307 InlineDisplay()
308 : NativeInlineDisplayImageSurfaceCompat(),
309 lastLeft(0.0f),
310 lastRight(0.0f),
311 pending(0) {}
313 ~InlineDisplay()
315 if (data != nullptr)
317 delete[] data;
318 data = nullptr;
322 CARLA_DECLARE_NON_COPYABLE(InlineDisplay)
323 CARLA_PREVENT_HEAP_ALLOCATION
324 } fInlineDisplay;
326 PluginClassEND(BigMeterPlugin)
327 CARLA_DECLARE_NON_COPYABLE(BigMeterPlugin)
330 // -----------------------------------------------------------------------
332 static const NativePluginDescriptor bigmeterDesc = {
333 /* category */ NATIVE_PLUGIN_CATEGORY_UTILITY,
334 /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE
335 |NATIVE_PLUGIN_HAS_INLINE_DISPLAY
336 |NATIVE_PLUGIN_HAS_UI
337 |NATIVE_PLUGIN_REQUESTS_IDLE),
338 /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING,
339 /* audioIns */ 2,
340 /* audioOuts */ 0,
341 /* midiIns */ 0,
342 /* midiOuts */ 0,
343 /* paramIns */ 2,
344 /* paramOuts */ 2,
345 /* name */ "Big Meter",
346 /* label */ "bigmeter",
347 /* maker */ "falkTX",
348 /* copyright */ "GNU GPL v2+",
349 PluginDescriptorFILL(BigMeterPlugin)
352 // -----------------------------------------------------------------------
354 CARLA_API_EXPORT
355 void carla_register_native_plugin_bigmeter();
357 CARLA_API_EXPORT
358 void carla_register_native_plugin_bigmeter()
360 carla_register_native_plugin(&bigmeterDesc);
363 // -----------------------------------------------------------------------