1 /* B.Slizr
2 * Step Sequencer Effect Plugin
3 *
4 * Copyright (C) 2018, 2019 by Sven Jähnichen
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #include <string>
22 #include <iostream>
23 #include <cstdlib>
24 #include <cmath>
25 #include <exception>
26 #include <map>
27 #include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
28 #include <lv2/lv2plug.in/ns/ext/atom/atom.h>
29 #include <lv2/lv2plug.in/ns/ext/atom/forge.h>
30 #include "BWidgets/Widget.hpp"
31 #include "BWidgets/Window.hpp"
32 #include "BWidgets/Label.hpp"
33 #include "BWidgets/DrawingSurface.hpp"
34 #include "BWidgets/HSwitch.hpp"
35 #include "BWidgets/VSlider.hpp"
36 #include "BWidgets/VSliderValue.hpp"
37 #include "BWidgets/HSliderValue.hpp"
38 #include "BWidgets/DialValue.hpp"
39
40 #include "main.h"
41 #include "screen.h"
42
43 #ifdef LOCALEFILE
44 #include LOCALEFILE
45 #else
46 #include "Locale_EN.hpp"
47 #endif
48
49 #ifdef SKINFILE
50 #include SKINFILE
51 #else
52 #include "Skin_Default.hpp"
53 #endif
54
55 #ifndef MESSAGENR_
56 #define MESSAGENR_
57 enum MessageNr
58 {
59 NO_MSG = 0,
60 JACK_STOP_MSG = 1,
61 MAX_MSG = 1
62 };
63 #endif /* MESSAGENR_ */
64
65 #define SCALEMIN -60
66 #define SCALEMAX 30
67 #define BG_FILE "surface.png"
68
69 #define DB_CO(g) ((g) > -90.0f ? powf(10.0f, (g) * 0.05f) : 0.0f)
70 #define CO_DB(g) ((g) > 0.0001f ? logf((g)) / 0.05f : -90.0f)
71 #define LIM(g , max) ((g) > (max) ? (max) : (g))
72 #define INT(g) (int) (g + 0.5)
73 #define RESIZE(widget, x, y, w, h, sz) (widget).moveTo ((x) * (sz), (y) * (sz)); (widget).resize ((w) * (sz), (h) * (sz));
74
75 const std::string messageStrings[MAX_MSG + 1] =
76 {
77 "",
78 "*** " BSLIZR_LABEL_JACK_STOP " ***"
79 };
80
81 class BSlizr_GUI : public BWidgets::Window
82 {
83 public:
84 BSlizr_GUI (const char *bundle_path, const LV2_Feature *const *features, PuglNativeView parentWindow);
85 ~BSlizr_GUI ();
86 void portEvent (uint32_t port_index, uint32_t buffer_size, uint32_t format, const void *buffer);
87 void send_record_on ();
88 void send_record_off ();
89 virtual void onConfigureRequest (BEvents::ExposeEvent* event) override;
90 void applyTheme (BStyles::Theme& theme) override;
91
92 LV2UI_Controller controller;
93 LV2UI_Write_Function write_function;
94
95
96 private:
97 void resizeGUI ();
98 void rearrange_step_controllers (float nrSteps_newf);
99 static void valueChangedCallback (BEvents::Event* event);
100 bool init_Stepshape ();
101 void destroy_Stepshape ();
102 void redrawStepshape ();
103 bool init_mainMonitor ();
104 void destroy_mainMonitor ();
105 void add_monitor_data (BSlizrNotifications* notifications, uint32_t notificationsCount, uint32_t& end);
106 void redrawMainMonitor ();
107
108
109 BWidgets::Widget mContainer;
110 BWidgets::Widget sContainer;
111 BWidgets::HSwitch monitorSwitch;
112 BWidgets::DrawingSurface monitorDisplay;
113 BWidgets::Label monitorLabel;
114 BWidgets::VSlider scaleControl;
115 BWidgets::DrawingSurface stepshapeDisplay;
116 BWidgets::DialValue attackControl;
117 BWidgets::Label attackLabel;
118 BWidgets::DialValue releaseControl;
119 BWidgets::Label releaseLabel;
120 BWidgets::HSliderValue sequencesperbarControl;
121 BWidgets::Label sequencesperbarLabel;
122 BWidgets::HSliderValue nrStepsControl;
123 BWidgets::Label nrStepsLabel;
124 BWidgets::Label stepshapeLabel;
125 BWidgets::Label sequencemonitorLabel;
126 BWidgets::Label messageLabel;
127 std::array<BWidgets::VSliderValue, MAXSTEPS> stepControl;
128
129 cairo_surface_t* surface;
130 cairo_t* cr1;
131 cairo_t* cr2;
132 cairo_t* cr3;
133 cairo_t* cr4;
134 cairo_pattern_t* pat1;
135 cairo_pattern_t* pat2;
136 cairo_pattern_t* pat3;
137 cairo_pattern_t* pat4;
138 cairo_pattern_t* pat5;
139
140 struct
141 {
142 bool record_on;
143 uint32_t width;
144 uint32_t height;
145 std::array<BSlizrNotifications, MONITORBUFFERSIZE> data;
146 uint32_t horizonPos;
147 } mainMonitor;
148
149 std::string pluginPath;
150 double sz;
151 cairo_surface_t* bgImageSurface;
152
153 float scale;
154 float attack;
155 float release;
156 float nrSteps;
157 float sequencesperbar;
158 std::array<float, MAXSTEPS> step;
159
160 LV2_Atom_Forge forge;
161 BSlizrURIs uris;
162 LV2_URID_Map* map;
163
164
165
166 // Definition of styles
167 BColors::ColorSet fgColors = BSLIZR_FG_COLORS;
168 BColors::ColorSet txColors = BSLIZR_TX_COLORS;
169 BColors::ColorSet bgColors = BSLIZR_BG_COLORS;
170 BColors::Color ink = {0.0, 0.75, 0.2, 1.0};
171
172 BStyles::Border border = {{ink, 1.0}, 0.0, 2.0, 0.0};
173 BStyles::Fill widgetBg = BStyles::noFill;
174 BStyles::Fill screenBg = BStyles::Fill (BColors::Color (BSLIZR_SCREEN_BG_COLORS));
175 BStyles::Border screenBorder = BStyles::Border (BStyles::Line (BColors::Color (0.0, 0.0, 0.0, 0.75), 4.0));
176 BStyles::Font defaultFont = BStyles::Font ("Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL, 12.0,
177 BStyles::TEXT_ALIGN_CENTER, BStyles::TEXT_VALIGN_MIDDLE);
178 BStyles::StyleSet defaultStyles = {"default", {{"background", STYLEPTR (&BStyles::noFill)},
179 {"border", STYLEPTR (&BStyles::noBorder)}}};
180 BStyles::StyleSet labelStyles = {"labels", {{"background", STYLEPTR (&BStyles::noFill)},
181 {"border", STYLEPTR (&BStyles::noBorder)},
182 {"textcolors", STYLEPTR (&txColors)},
183 {"font", STYLEPTR (&defaultFont)}}};
184
185 BStyles::Theme theme = BStyles::Theme ({
186 defaultStyles,
187 {"B.Slizr", {{"background", STYLEPTR (&BStyles::blackFill)},
188 {"border", STYLEPTR (&BStyles::noBorder)}}},
189 {"main", {{"background", STYLEPTR (&widgetBg)},
190 {"border", STYLEPTR (&BStyles::noBorder)}}},
191 {"widget", {{"uses", STYLEPTR (&defaultStyles)}}},
192 {"monitor", {{"background", STYLEPTR (&BStyles::blackFill)},
193 {"border", STYLEPTR (&border)}}},
194 {"dial", {{"uses", STYLEPTR (&defaultStyles)},
195 {"fgcolors", STYLEPTR (&fgColors)},
196 {"bgcolors", STYLEPTR (&bgColors)},
197 {"textcolors", STYLEPTR (&fgColors)},
198 {"font", STYLEPTR (&defaultFont)}}},
199 {"dial/focus", {{"background", STYLEPTR (&screenBg)},
200 {"border", STYLEPTR (&screenBorder)},
201 {"textcolors", STYLEPTR (&txColors)},
202 {"font", STYLEPTR (&defaultFont)}}},
203 {"slider", {{"uses", STYLEPTR (&defaultStyles)},
204 {"fgcolors", STYLEPTR (&fgColors)},
205 {"bgcolors", STYLEPTR (&bgColors)},
206 {"textcolors", STYLEPTR (&fgColors)},
207 {"font", STYLEPTR (&defaultFont)}}},
208 {"slider/focus",{{"background", STYLEPTR (&screenBg)},
209 {"border", STYLEPTR (&screenBorder)},
210 {"textcolors", STYLEPTR (&txColors)},
211 {"font", STYLEPTR (&defaultFont)}}},
212 {"switch", {{"uses", STYLEPTR (&defaultStyles)},
213 {"fgcolors", STYLEPTR (&fgColors)},
214 {"bgcolors", STYLEPTR (&bgColors)}}},
215 {"switch/focus",{{"background", STYLEPTR (&screenBg)},
216 {"border", STYLEPTR (&screenBorder)},
217 {"textcolors", STYLEPTR (&txColors)},
218 {"font", STYLEPTR (&defaultFont)}}},
219 {"label", {{"uses", STYLEPTR (&labelStyles)}}},
220 {"hilabel", {{"uses", STYLEPTR (&labelStyles)},
221 {"textcolors", STYLEPTR (&BColors::whites)}}},
222 });
223 };
224
225
BSlizr_GUI(const char * bundle_path,const LV2_Feature * const * features,PuglNativeView parentWindow)226 BSlizr_GUI::BSlizr_GUI (const char *bundle_path, const LV2_Feature *const *features, PuglNativeView parentWindow) :
227 Window (800, 560, "B.Slizr", parentWindow, true, PUGL_MODULE, 0),
228 controller (NULL), write_function (NULL),
229 mContainer (0, 0, 800, 560, "main"),
230 sContainer (260, 330, 480, 130, "widget"),
231 monitorSwitch (690, 25, 40, 16, "switch", 0.0),
232 monitorDisplay (260, 70, 480, 240, "monitor"),
233 monitorLabel (680, 45, 60, 20, "label", BSLIZR_LABEL_MONITOR),
234 scaleControl (760, 80, 14, 230, "slider", 0.0, SCALEMIN, SCALEMAX, 0.1),
235 stepshapeDisplay (30, 320, 180, 140, "monitor"),
236 attackControl (40, 465, 50, 60, "dial", 0.2, 0.01, 1.0, 0.01, "%1.2f"),
237 attackLabel (20, 520, 90, 20, "label", BSLIZR_LABEL_ATTACK),
238 releaseControl (150, 465, 50, 60, "dial", 0.2, 0.01, 1.0, -0.01, "%1.2f"),
239 releaseLabel (130, 520, 90, 20, "label", BSLIZR_LABEL_RELEASE),
240 sequencesperbarControl (260, 492, 120, 28, "slider", 1.0, 1.0, 8.0, 1.0, "%1.0f"),
241 sequencesperbarLabel (250, 520, 140, 20, "label", BSLIZR_LABEL_SEQUENCES_PER_BAR),
242 nrStepsControl (400, 492, 380, 28, "slider", 1.0, 1.0, MAXSTEPS, 1.0, "%2.0f"),
243 nrStepsLabel (400, 520, 380, 20, "label", BSLIZR_LABEL_NUMBER_OF_STEPS),
244 stepshapeLabel (33, 323, 100, 20, "label", BSLIZR_LABEL_STEP_SHAPE),
245 sequencemonitorLabel (263, 73, 140, 20, "label", BSLIZR_LABEL_SEQUENCE_MONITOR),
246 messageLabel (420, 73, 280, 20, "hilabel", ""),
247
248 surface (NULL), cr1 (NULL), cr2 (NULL), cr3 (NULL), cr4 (NULL), pat1 (NULL), pat2 (NULL), pat3 (NULL), pat4 (NULL), pat5 (NULL),
249 pluginPath (bundle_path ? std::string (bundle_path) : std::string ("")), sz (1.0), bgImageSurface (nullptr),
250 scale (DB_CO(0.0)), attack (0.2), release (0.2), nrSteps (16.0), sequencesperbar (4.0), step (),
251 map (NULL)
252
253
254 {
255 if (!init_mainMonitor () || !init_Stepshape ())
256 {
257 std::cerr << "BSlizr.lv2#GUI: Failed to init monitor." << std::endl;
258 destroy_mainMonitor ();
259 destroy_Stepshape ();
260 throw std::bad_alloc ();
261 }
262
263 //Initialialize and configure stepControllers
264 for (int i = 0; i < MAXSTEPS; ++i)
265 {
266 stepControl[i] = BWidgets::VSliderValue ((i + 0.5) * 480 / MAXSTEPS - 10, 0, 28, 130, "slider", 1.0, 0.0, 1.0, 0.01, "%1.2f");
267 stepControl[i].setHardChangeable (false);
268 stepControl[i].setScrollable (true);
269 stepControl[i].rename ("slider");
270 stepControl[i].setCallbackFunction (BEvents::EventType::VALUE_CHANGED_EVENT, BSlizr_GUI::valueChangedCallback);
271 stepControl[i].applyTheme (theme, "slider");
272 stepControl[i].getDisplayLabel ()->setState (BColors::ACTIVE);
273 sContainer.add (stepControl[i]);
274 }
275
276 // Set callbacks
277 monitorSwitch.setCallbackFunction (BEvents::EventType::VALUE_CHANGED_EVENT, BSlizr_GUI::valueChangedCallback);
278 scaleControl.setCallbackFunction (BEvents::EventType::VALUE_CHANGED_EVENT, BSlizr_GUI::valueChangedCallback);
279 attackControl.setCallbackFunction (BEvents::EventType::VALUE_CHANGED_EVENT, BSlizr_GUI::valueChangedCallback);
280 releaseControl.setCallbackFunction (BEvents::EventType::VALUE_CHANGED_EVENT, BSlizr_GUI::valueChangedCallback);
281 sequencesperbarControl.setCallbackFunction (BEvents::EventType::VALUE_CHANGED_EVENT, BSlizr_GUI::valueChangedCallback);
282 nrStepsControl.setCallbackFunction (BEvents::EventType::VALUE_CHANGED_EVENT, BSlizr_GUI::valueChangedCallback);
283
284 // Configure widgets
285 bgImageSurface = cairo_image_surface_create_from_png ((pluginPath + BG_FILE).c_str());
286 widgetBg.loadFillFromCairoSurface (bgImageSurface);
287 scaleControl.setScrollable (true);
288 attackControl.setScrollable (true);
289 attackControl.setHardChangeable (false);
290 releaseControl.setScrollable (true);
291 releaseControl.setHardChangeable (false);
292 sequencesperbarControl.setScrollable (true);
293 nrStepsControl.setScrollable (true);
294 applyTheme (theme);
295
296 // Pack widgets
297 mContainer.add (monitorSwitch);
298 mContainer.add (monitorDisplay);
299 mContainer.add (monitorLabel);
300 mContainer.add (scaleControl);
301 mContainer.add (stepshapeDisplay);
302 mContainer.add (attackControl);
303 mContainer.add (attackLabel);
304 mContainer.add (releaseControl);
305 mContainer.add (releaseLabel);
306 mContainer.add (sequencesperbarControl);
307 mContainer.add (sequencesperbarLabel);
308 mContainer.add (nrStepsControl);
309 mContainer.add (nrStepsLabel);
310 mContainer.add (stepshapeLabel);
311 mContainer.add (sequencemonitorLabel);
312 mContainer.add (messageLabel);
313 mContainer.add (sContainer);
314 add (mContainer);
315
316 //Scan host features for URID map
317 LV2_URID_Map* m = NULL;
318 for (int i = 0; features[i]; ++i)
319 {
320 if (strcmp(features[i]->URI, LV2_URID__map) == 0) m = (LV2_URID_Map*) features[i]->data;
321 }
322 if (!m) throw std::invalid_argument ("Host does not support urid:map");
323
324 //Map URIS
325 map = m;
326 getURIs (map, &uris);
327
328 // Initialize forge
329 lv2_atom_forge_init (&forge,map);
330 }
331
~BSlizr_GUI()332 BSlizr_GUI::~BSlizr_GUI()
333 {
334 send_record_off ();
335 destroy_mainMonitor ();
336 destroy_Stepshape ();
337 }
338
portEvent(uint32_t port_index,uint32_t buffer_size,uint32_t format,const void * buffer)339 void BSlizr_GUI::portEvent(uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer)
340 {
341 // Notify port
342 if ((format == uris.atom_eventTransfer) && (port_index == Notify))
343 {
344 const LV2_Atom* atom = (const LV2_Atom*) buffer;
345 if ((atom->type == uris.atom_Blank) || (atom->type == uris.atom_Object))
346 {
347 const LV2_Atom_Object* obj = (const LV2_Atom_Object*) atom;
348
349 // Monitor notification
350 if (obj->body.otype == uris.notify_event)
351 {
352 const LV2_Atom* data = NULL;
353 lv2_atom_object_get(obj, uris.notify_key, &data, 0);
354 if (data && (data->type == uris.atom_Vector))
355 {
356 const LV2_Atom_Vector* vec = (const LV2_Atom_Vector*) data;
357 if (vec->body.child_type == uris.atom_Float)
358 {
359 uint32_t notificationsCount = (uint32_t) ((data->size - sizeof(LV2_Atom_Vector_Body)) / sizeof (BSlizrNotifications));
360 BSlizrNotifications* notifications = (BSlizrNotifications*) (&vec->body + 1);
361 if (notificationsCount > 0)
362 {
363 add_monitor_data (notifications, notificationsCount, mainMonitor.horizonPos);
364 redrawMainMonitor ();
365 }
366 }
367 }
368 else std::cerr << "BSlizr.lv2#GUI: Corrupt audio message." << std::endl;
369 }
370
371 // Message notification
372 else if (obj->body.otype == uris.notify_messageEvent)
373 {
374 const LV2_Atom* data = NULL;
375 lv2_atom_object_get(obj, uris.notify_message, &data, 0);
376 if (data && (data->type == uris.atom_Int))
377 {
378 const int messageNr = ((LV2_Atom_Int*)data)->body;
379 std::string msg = ((messageNr >= NO_MSG) && (messageNr <= MAX_MSG) ? messageStrings[messageNr] : "");
380 messageLabel.setText (msg);
381 }
382 }
383 }
384 }
385
386 // Scan remaining ports
387 else if ((format == 0) && (port_index >= Attack) && (port_index < Step_ + MAXSTEPS))
388 {
389 float* pval = (float*) buffer;
390 switch (port_index) {
391 case Attack:
392 attack = *pval;
393 attackControl.setValue (*pval);
394 break;
395 case Release:
396 release = *pval;
397 releaseControl.setValue (*pval);
398 break;
399 case SequencesPerBar:
400 sequencesperbar = *pval;
401 sequencesperbarControl.setValue (*pval);
402 break;
403 case NrSteps:
404 if (nrSteps != *pval)
405 {
406 rearrange_step_controllers (*pval);
407 nrSteps = *pval;
408 }
409 redrawMainMonitor ();
410 nrStepsControl.setValue (*pval);
411 break;
412 default:
413 if ((port_index >= Step_) and (port_index < Step_ + MAXSTEPS))
414 {
415 step[port_index-Step_] = *pval;
416 stepControl[port_index-Step_].setValue (*pval);
417 }
418 }
419 }
420
421 }
422
resizeGUI()423 void BSlizr_GUI::resizeGUI()
424 {
425 hide ();
426
427 // Resize Fonts
428 defaultFont.setFontSize (12 * sz);
429
430 // Resize Background
431 cairo_surface_t* surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 800 * sz, 560 * sz);
432 cairo_t* cr = cairo_create (surface);
433 cairo_scale (cr, sz, sz);
434 cairo_set_source_surface(cr, bgImageSurface, 0, 0);
435 cairo_paint(cr);
436 widgetBg.loadFillFromCairoSurface(surface);
437 cairo_destroy (cr);
438 cairo_surface_destroy (surface);
439
440 // Resize widgets
441 RESIZE (mContainer, 0, 0, 800, 560, sz);
442 RESIZE (monitorSwitch, 690, 25, 40, 16, sz);
443 RESIZE (monitorDisplay, 260, 70, 480, 240, sz);
444 RESIZE (monitorLabel, 680, 45, 60, 20, sz);
445 RESIZE (scaleControl, 760, 80, 14, 230, sz);
446 RESIZE (stepshapeDisplay, 30, 320, 180, 140, sz);
447 RESIZE (attackControl, 40, 465, 50, 60, sz);
448 RESIZE (attackLabel, 20, 520, 90, 20, sz);
449 RESIZE (releaseControl, 150, 465, 50, 60, sz);
450 RESIZE (releaseLabel, 130, 520, 90, 20, sz);
451 RESIZE (sequencesperbarControl, 260, 492, 120, 28, sz);
452 RESIZE (sequencesperbarLabel, 250, 520, 140, 20, sz);
453 RESIZE (nrStepsControl, 400, 492, 380, 28, sz);
454 RESIZE (nrStepsLabel, 400, 520, 380, 20, sz);
455 RESIZE (stepshapeLabel, 33, 323, 100, 20, sz);
456 RESIZE (sequencemonitorLabel, 263, 73, 140, 20, sz);
457 RESIZE (messageLabel, 420, 73, 280, 20,sz);
458 RESIZE (sContainer, 260, 330, 480, 130, sz);
459 for (int i = 0; i < MAXSTEPS; ++i) {RESIZE (stepControl[i], (i + 0.5) * 480 / nrSteps - 10, 0, 28, 130, sz);}
460
461 // Update monitors
462 destroy_Stepshape ();
463 init_Stepshape ();
464 redrawStepshape ();
465 destroy_mainMonitor ();
466 init_mainMonitor ();
467 redrawMainMonitor ();
468
469 // Apply changes
470 applyTheme (theme);
471 show ();
472 }
473
applyTheme(BStyles::Theme & theme)474 void BSlizr_GUI::applyTheme (BStyles::Theme& theme)
475 {
476 mContainer.applyTheme (theme);
477 monitorSwitch.applyTheme (theme);
478 monitorDisplay.applyTheme (theme);
479 monitorLabel.applyTheme (theme);
480 scaleControl.applyTheme (theme);
481 stepshapeDisplay.applyTheme (theme);
482 attackControl.applyTheme (theme);
483 attackLabel.applyTheme (theme);
484 releaseControl.applyTheme (theme);
485 releaseLabel.applyTheme (theme);
486 sequencesperbarControl.applyTheme (theme);
487 sequencesperbarLabel.applyTheme (theme);
488 nrStepsControl.applyTheme (theme);
489 nrStepsLabel.applyTheme (theme);
490 stepshapeLabel.applyTheme (theme);
491 sequencemonitorLabel.applyTheme (theme);
492 messageLabel.applyTheme (theme);
493 sContainer.applyTheme (theme);
494 for (int i = 0; i < MAXSTEPS; ++i)
495 {
496 stepControl[i].applyTheme (theme);
497 stepControl[i].update (); // TODO Remove if fixed in BWidgets TK
498 }
499 }
500
onConfigureRequest(BEvents::ExposeEvent * event)501 void BSlizr_GUI::onConfigureRequest (BEvents::ExposeEvent* event)
502 {
503 Window::onConfigureRequest (event);
504
505 sz = (getWidth() / 800 > getHeight() / 560 ? getHeight() / 560 : getWidth() / 800);
506 resizeGUI ();
507 }
508
send_record_on()509 void BSlizr_GUI::send_record_on ()
510 {
511 uint8_t obj_buf[64];
512 lv2_atom_forge_set_buffer(&forge, obj_buf, sizeof(obj_buf));
513
514 LV2_Atom_Forge_Frame frame;
515 LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_object(&forge, &frame, 0, uris.ui_on);
516 lv2_atom_forge_pop(&forge, &frame);
517 write_function(controller, Control_2, lv2_atom_total_size(msg), uris.atom_eventTransfer, msg);
518 monitorSwitch.setValue (1.0);
519 }
520
send_record_off()521 void BSlizr_GUI::send_record_off ()
522 {
523 uint8_t obj_buf[64];
524 lv2_atom_forge_set_buffer(&forge, obj_buf, sizeof(obj_buf));
525
526 LV2_Atom_Forge_Frame frame;
527 LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_object(&forge, &frame, 0, uris.ui_off);
528 lv2_atom_forge_pop(&forge, &frame);
529 write_function(controller, Control_2, lv2_atom_total_size(msg), uris.atom_eventTransfer, msg);
530 monitorSwitch.setValue (0.0);
531 }
532
rearrange_step_controllers(float nrSteps_newf)533 void BSlizr_GUI::rearrange_step_controllers (float nrSteps_newf)
534 {
535 int nrSteps_old = INT (nrSteps);
536 int nrSteps_new = INT (nrSteps_newf);
537
538 if ((nrSteps_old < 1) || (nrSteps_old > MAXSTEPS) || (nrSteps_new < 1) || (nrSteps_old > MAXSTEPS)) return;
539
540 for (int i = 0; i < MAXSTEPS; ++i)
541 {
542 if (i < nrSteps_new)
543 {
544 stepControl[i].moveTo (((i + 0.5) * 480 / nrSteps_new - 10) * sz, 0);
545 stepControl[i].show ();
546 }
547 else stepControl[i].hide ();
548 }
549 }
550
valueChangedCallback(BEvents::Event * event)551 void BSlizr_GUI::valueChangedCallback (BEvents::Event* event)
552 {
553 if ((event) && (event->getWidget ()))
554 {
555 BWidgets::ValueWidget* widget = (BWidgets::ValueWidget*) event->getWidget ();
556
557 if (widget->getMainWindow ())
558 {
559 BSlizr_GUI* ui = (BSlizr_GUI*) widget->getMainWindow ();
560
561 // monitor on/off changed
562 if (widget == &ui->monitorSwitch)
563 {
564 int value = INT (widget->getValue ());
565 if (value == 1)
566 {
567 ui->mainMonitor.record_on = true;
568 ui->send_record_on ();
569 }
570 else
571 {
572 ui->mainMonitor.record_on = false;
573 ui->send_record_off ();
574 }
575 return;
576 }
577
578 // Scale changed
579 if (widget == &ui->scaleControl)
580 {
581 float value = (float) widget->getValue ();
582 ui->scale = DB_CO (value);
583 if (ui->scale < 0.0001f) ui->scale = 0.0001f;
584 ui->redrawMainMonitor ();
585 }
586
587 // Attack changed
588 if (widget == &ui->attackControl)
589 {
590 ui->attack = (float) widget->getValue ();
591 ui->write_function(ui->controller, Attack, sizeof(ui->attack), 0, &ui->attack);
592 ui->redrawStepshape ();
593 return;
594 }
595
596 // Release changed
597 if (widget == &ui->releaseControl)
598 {
599 ui->release = (float) widget->getValue ();
600 ui->write_function(ui->controller, Release, sizeof(ui->release), 0, &ui->release);
601 ui->redrawStepshape ();
602 return;
603 }
604
605 // Step size changed
606 if (widget == &ui->sequencesperbarControl)
607 {
608 ui->sequencesperbar = (float) widget->getValue ();
609 ui->write_function(ui->controller, SequencesPerBar, sizeof(ui->sequencesperbar), 0, &ui->sequencesperbar);
610 return;
611 }
612
613 // nrSteps changed
614 if (widget == &ui->nrStepsControl)
615 {
616 float nrSteps_new = (float) widget->getValue ();
617 if (nrSteps_new != ui->nrSteps) ui->rearrange_step_controllers (nrSteps_new);
618 ui->nrSteps = nrSteps_new;
619 ui->write_function(ui->controller, NrSteps, sizeof(ui->nrSteps), 0, &ui->nrSteps);
620 ui->redrawMainMonitor ();
621 return;
622 }
623
624 // Step controllers changed
625 for (int i = 0; i < ui->nrSteps; i++)
626 {
627 if (widget == &ui->stepControl[i])
628 {
629 ui->step[i] = (float) widget->getValue ();
630 ui->write_function(ui->controller, Step_+i , sizeof(ui->step[i]), 0, &ui->step[i]);
631 return;
632 }
633 }
634 }
635 }
636 }
637
init_Stepshape()638 bool BSlizr_GUI::init_Stepshape ()
639 {
640 double height = stepshapeDisplay.getEffectiveHeight ();
641 pat5 = cairo_pattern_create_linear (0, 0, 0, height);
642
643 return (pat5 && (cairo_pattern_status (pat5) == CAIRO_STATUS_SUCCESS));
644 }
645
destroy_Stepshape()646 void BSlizr_GUI::destroy_Stepshape ()
647 {
648 //Destroy also mainMonitors cairo data
649 if (pat5 && (cairo_pattern_status (pat5) == CAIRO_STATUS_SUCCESS)) cairo_pattern_destroy (pat5);
650 }
651
redrawStepshape()652 void BSlizr_GUI::redrawStepshape ()
653 {
654 double width = stepshapeDisplay.getEffectiveWidth ();
655 double height = stepshapeDisplay.getEffectiveHeight ();
656
657 cairo_t* cr = cairo_create (stepshapeDisplay.getDrawingSurface ());
658 if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) return;
659
660 // Draw background
661 cairo_set_source_rgba (cr, CAIRO_BG_COLOR);
662 cairo_rectangle (cr, 0.0, 0.0, width, height);
663 cairo_fill (cr);
664 cairo_set_source_rgba (cr, CAIRO_BG_COLOR2);
665 cairo_set_line_width (cr, 1);
666 cairo_move_to (cr, 0, 0.2 * height);
667 cairo_line_to (cr, width, 0.2 * height);
668 cairo_move_to (cr, 0, 0.55 * height);
669 cairo_line_to (cr, width, 0.55 * height);
670 cairo_move_to (cr, 0, 0.9 * height);
671 cairo_line_to (cr, width, 0.9 * height);
672 cairo_move_to (cr, 0.25 * width, 0);
673 cairo_line_to (cr, 0.25 * width, height);
674 cairo_move_to (cr, 0.5 * width, 0);
675 cairo_line_to (cr, 0.5 * width, height);
676 cairo_move_to (cr, 0.75 * width, 0);
677 cairo_line_to (cr, 0.75 * width, height);
678 cairo_stroke (cr);
679
680 // Draw step shape
681 cairo_set_source_rgba (cr, CAIRO_INK1, 1.0);
682 cairo_set_line_width (cr, 3);
683
684 cairo_move_to (cr, 0, 0.9 * height);
685 cairo_line_to (cr, width * 0.25, 0.9 * height);
686 if ((attack + release) > 1)
687 {
688 float crosspointX = attack / (attack + release);
689 float crosspointY = crosspointX / attack - (crosspointX - (1 - release)) / release;
690 cairo_line_to (cr, width* 0.25 + crosspointX * width * 0.5, 0.9 * height - 0.7 * height * crosspointY);
691 }
692 else
693 {
694 cairo_line_to (cr, width * 0.25 + attack * width * 0.5 , 0.2 * height);
695 cairo_line_to (cr, width * 0.75 - release * width * 0.5, 0.2 * height);
696
697 }
698 cairo_line_to (cr, width * 0.75, 0.9 * height);
699 cairo_line_to (cr, width, 0.9 * height);
700
701 cairo_stroke_preserve (cr);
702
703 cairo_pattern_add_color_stop_rgba (pat5, 0.1, CAIRO_INK1, 1);
704 cairo_pattern_add_color_stop_rgba (pat5, 0.9, CAIRO_INK1, 0);
705 cairo_set_source (cr, pat5);
706 cairo_line_to(cr, 0, 0.9 * height);
707 cairo_set_line_width (cr, 0);
708 cairo_fill (cr);
709
710 cairo_destroy (cr);
711
712 stepshapeDisplay.update ();
713 }
714
init_mainMonitor()715 bool BSlizr_GUI::init_mainMonitor ()
716 {
717 //Initialize mainMonitor
718 mainMonitor.record_on = true;
719 mainMonitor.width = 0;
720 mainMonitor.height = 0;
721 mainMonitor.data.fill (defaultNotification);
722 mainMonitor.horizonPos = 0;
723
724 //Initialize mainMonitors cairo data
725 double width = monitorDisplay.getEffectiveWidth ();
726 double height = monitorDisplay.getEffectiveHeight ();
727 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
728 cr1 = cairo_create (surface);
729 cr2 = cairo_create (surface);
730 cr3 = cairo_create (surface);
731 cr4 = cairo_create (surface);
732 pat1 = cairo_pattern_create_linear (0, 0, 0, height);
733 cairo_pattern_add_color_stop_rgba (pat1, 0.1, CAIRO_INK1, 1);
734 cairo_pattern_add_color_stop_rgba (pat1, 0.6, CAIRO_INK1, 0);
735 pat2 = cairo_pattern_create_linear (0, 0, 0, height);
736 cairo_pattern_add_color_stop_rgba (pat2, 0.1, CAIRO_INK2, 1);
737 cairo_pattern_add_color_stop_rgba (pat2, 0.6, CAIRO_INK2, 0);
738 pat3 = cairo_pattern_create_linear (0, height, 0, 0);
739 cairo_pattern_add_color_stop_rgba (pat3, 0.1, CAIRO_INK1, 1);
740 cairo_pattern_add_color_stop_rgba (pat3, 0.6, CAIRO_INK1, 0);
741 pat4 = cairo_pattern_create_linear (0, height, 0, 0);
742 cairo_pattern_add_color_stop_rgba (pat4, 0.1, CAIRO_INK2, 1);
743 cairo_pattern_add_color_stop_rgba (pat4, 0.6, CAIRO_INK2, 0);
744
745 return (pat4 && (cairo_pattern_status (pat4) == CAIRO_STATUS_SUCCESS) &&
746 pat3 && (cairo_pattern_status (pat3) == CAIRO_STATUS_SUCCESS) &&
747 pat2 && (cairo_pattern_status (pat2) == CAIRO_STATUS_SUCCESS) &&
748 pat1 && (cairo_pattern_status (pat1) == CAIRO_STATUS_SUCCESS) &&
749 cr4 && (cairo_status (cr4) == CAIRO_STATUS_SUCCESS) &&
750 cr3 && (cairo_status (cr3) == CAIRO_STATUS_SUCCESS)&&
751 cr2 && (cairo_status (cr2) == CAIRO_STATUS_SUCCESS) &&
752 cr1 && (cairo_status (cr1) == CAIRO_STATUS_SUCCESS) &&
753 surface && (cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS));
754 }
755
destroy_mainMonitor()756 void BSlizr_GUI::destroy_mainMonitor ()
757 {
758 //Destroy also mainMonitors cairo data
759 if (pat4 && (cairo_pattern_status (pat4) == CAIRO_STATUS_SUCCESS)) cairo_pattern_destroy (pat4);
760 if (pat3 && (cairo_pattern_status (pat3) == CAIRO_STATUS_SUCCESS)) cairo_pattern_destroy (pat3);
761 if (pat2 && (cairo_pattern_status (pat2) == CAIRO_STATUS_SUCCESS)) cairo_pattern_destroy (pat2);
762 if (pat1 && (cairo_pattern_status (pat1) == CAIRO_STATUS_SUCCESS)) cairo_pattern_destroy (pat1);
763 if (cr4 && (cairo_status (cr4) == CAIRO_STATUS_SUCCESS)) cairo_destroy (cr4);
764 if (cr3 && (cairo_status (cr3) == CAIRO_STATUS_SUCCESS)) cairo_destroy (cr3);
765 if (cr2 && (cairo_status (cr2) == CAIRO_STATUS_SUCCESS)) cairo_destroy (cr2);
766 if (cr1 && (cairo_status (cr1) == CAIRO_STATUS_SUCCESS)) cairo_destroy (cr1);
767 if (surface && (cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS)) cairo_surface_destroy (surface);
768 }
769
add_monitor_data(BSlizrNotifications * notifications,uint32_t notificationsCount,uint32_t & end)770 void BSlizr_GUI::add_monitor_data (BSlizrNotifications* notifications, uint32_t notificationsCount, uint32_t& end)
771 {
772 for (uint32_t i = 0; i < notificationsCount; ++i)
773 {
774 int monitorpos = notifications[i].position;
775 if (monitorpos >= MONITORBUFFERSIZE) monitorpos = MONITORBUFFERSIZE;
776 if (monitorpos < 0) monitorpos = 0;
777
778 mainMonitor.data[monitorpos].inputMin = notifications[i].inputMin;
779 mainMonitor.data[monitorpos].inputMax = notifications[i].inputMax;
780 mainMonitor.data[monitorpos].outputMin = notifications[i].outputMin;
781 mainMonitor.data[monitorpos].outputMax = notifications[i].outputMax;
782 mainMonitor.horizonPos = monitorpos;
783 }
784 }
785
redrawMainMonitor()786 void BSlizr_GUI::redrawMainMonitor ()
787 {
788 double width = monitorDisplay.getEffectiveWidth ();
789 double height = monitorDisplay.getEffectiveHeight ();
790
791 cairo_t* cr = cairo_create (monitorDisplay.getDrawingSurface ());
792 if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) return;
793
794 // Draw background
795 cairo_set_source_rgba (cr, CAIRO_BG_COLOR);
796 cairo_rectangle (cr, 0, 0, width, height);
797 cairo_fill (cr);
798
799 cairo_set_source_rgba (cr, CAIRO_BG_COLOR2);
800 cairo_set_line_width (cr, 1);
801 cairo_move_to (cr, 0, 0.1 * height);
802 cairo_line_to (cr, width, 0.1 * height);
803 cairo_move_to (cr, 0, 0.5 * height);
804 cairo_line_to (cr, width, 0.5 * height);
805 cairo_move_to (cr, 0, 0.9 * height);
806 cairo_line_to (cr, width, 0.9 * height);
807
808 uint32_t steps = (uint32_t) nrSteps;
809 for (uint32_t i = 1; i < steps; ++i)
810 {
811 uint32_t x = uint32_t (i * width / steps);
812 cairo_move_to (cr, x, 0);
813 cairo_line_to (cr, x, height);
814 }
815 cairo_stroke (cr);
816
817 if (mainMonitor.record_on)
818 {
819 cairo_surface_clear (surface);
820
821 // Draw input (cr, cr3) and output (cr2, cr4) curves
822 cairo_move_to (cr1, 0, height * (0.5 - (0.4 * LIM ((mainMonitor.data[0].inputMax / scale), 1.0f))));
823 cairo_move_to (cr2, 0, height * (0.5 - (0.4 * LIM ((mainMonitor.data[0].outputMax / scale), 1.0f))));
824 cairo_move_to (cr3, 0, height * (0.5 + (0.4 * LIM (-(mainMonitor.data[0].inputMin / scale), 1.0f))));
825 cairo_move_to (cr4, 0, height * (0.5 + (0.4 * LIM (-(mainMonitor.data[0].outputMin / scale), 1.0f))));
826
827 for (int i = 0; i < MONITORBUFFERSIZE; ++i)
828 {
829 double pos = ((double) i) / (MONITORBUFFERSIZE - 1.0f);
830 cairo_line_to (cr1, pos * width, height * (0.5 - (0.4 * LIM ((mainMonitor.data[i].inputMax / scale), 1.0f))));
831 cairo_line_to (cr2, pos * width, height * (0.5 - (0.4 * LIM ((mainMonitor.data[i].outputMax / scale), 1.0f))));
832 cairo_line_to (cr3, pos * width, height * (0.5 + (0.4 * LIM (-(mainMonitor.data[i].inputMin / scale), 1.0f))));
833 cairo_line_to (cr4, pos * width, height * (0.5 + (0.4 * LIM (-(mainMonitor.data[i].outputMin / scale), 1.0f))));
834 }
835
836 // Visualize input (cr, cr3) and output (cr2, cr4) curves
837 cairo_set_source_rgba (cr1, CAIRO_INK1, 1.0);
838 cairo_set_line_width (cr1, 3);
839 cairo_set_source_rgba (cr2, CAIRO_INK2, 1.0);
840 cairo_set_line_width (cr2, 3);
841 cairo_stroke_preserve (cr1);
842 cairo_stroke_preserve (cr2);
843 cairo_set_source_rgba (cr3, CAIRO_INK1, 1.0);
844 cairo_set_line_width (cr3, 3);
845 cairo_set_source_rgba (cr4, CAIRO_INK2, 1.0);
846 cairo_set_line_width (cr4, 3);
847 cairo_stroke_preserve (cr3);
848 cairo_stroke_preserve (cr4);
849
850 // Visualize input (cr, cr3) and output (cr2, cr4) areas under the curves
851 cairo_line_to (cr1, width, height * 0.5);
852 cairo_line_to (cr1, 0, height * 0.5);
853 cairo_close_path (cr1);
854 cairo_line_to (cr2, width, height * 0.5);
855 cairo_line_to (cr2, 0, height * 0.5);
856 cairo_close_path (cr2);
857 cairo_set_source (cr1, pat1);
858 cairo_set_line_width (cr1, 0);
859 cairo_set_source (cr2, pat2);
860 cairo_set_line_width (cr2, 0);
861 cairo_fill (cr1);
862 cairo_fill (cr2);
863 cairo_line_to (cr3, width, height * 0.5);
864 cairo_line_to (cr3, 0, height * 0.5);
865 cairo_close_path (cr3);
866 cairo_line_to (cr4, width, height * 0.5);
867 cairo_line_to (cr4, 0, height * 0.5);
868 cairo_close_path (cr4);
869 cairo_set_source (cr3, pat3);
870 cairo_set_line_width (cr3, 0);
871 cairo_set_source (cr4, pat4);
872 cairo_set_line_width (cr4, 0);
873 cairo_fill (cr3);
874 cairo_fill (cr4);
875
876 // Draw fade out
877 double horizon = ((double) mainMonitor.horizonPos) / (MONITORBUFFERSIZE - 1.0f);
878 cairo_pattern_t* pat6 = cairo_pattern_create_linear (horizon * width, 0, horizon * width + 63, 0);
879 if (cairo_pattern_status (pat6) == CAIRO_STATUS_SUCCESS)
880 {
881 cairo_pattern_add_color_stop_rgba (pat6, 0.0, CAIRO_BG_COLOR);
882 cairo_pattern_add_color_stop_rgba (pat6, 1.0, CAIRO_TRANSPARENT);
883 cairo_set_line_width (cr1, 0.0);
884 cairo_set_source (cr1, pat6);
885 cairo_rectangle (cr1, horizon * width, 0, 63, height);
886 cairo_fill (cr1);
887 cairo_pattern_destroy (pat6);
888 }
889
890 if (horizon * width > width - 63)
891 {
892 cairo_pattern_t* pat6 = cairo_pattern_create_linear ((horizon - 1) * width, 0, (horizon - 1) * width + 63, 0);
893 if (cairo_pattern_status (pat6) == CAIRO_STATUS_SUCCESS)
894 {
895 cairo_pattern_add_color_stop_rgba (pat6, 0.0, CAIRO_BG_COLOR);
896 cairo_pattern_add_color_stop_rgba (pat6, 1.0, CAIRO_TRANSPARENT);
897 cairo_set_line_width (cr1, 0.0);
898 cairo_set_source (cr1, pat6);
899 cairo_rectangle (cr1, (horizon - 1) * width, 0, 63, height);
900 cairo_fill (cr1);
901 cairo_pattern_destroy (pat6);
902 }
903 }
904
905 // Draw horizon line
906 cairo_set_source_rgba (cr1, CAIRO_FG_COLOR);
907 cairo_set_line_width (cr1, 1);
908 cairo_move_to (cr1, horizon * width, 0);
909 cairo_line_to (cr1, horizon * width, height);
910 cairo_stroke (cr1);
911 }
912
913 cairo_set_source_surface (cr, surface, 0, 0);
914 cairo_paint (cr);
915
916 cairo_destroy (cr);
917
918 monitorDisplay.update ();
919 }
920
instantiate(const LV2UI_Descriptor * descriptor,const char * plugin_uri,const char * bundle_path,LV2UI_Write_Function write_function,LV2UI_Controller controller,LV2UI_Widget * widget,const LV2_Feature * const * features)921 static LV2UI_Handle instantiate (const LV2UI_Descriptor *descriptor, const char *plugin_uri, const char *bundle_path,
922 LV2UI_Write_Function write_function, LV2UI_Controller controller, LV2UI_Widget *widget,
923 const LV2_Feature *const *features)
924 {
925 PuglNativeView parentWindow = 0;
926 LV2UI_Resize* resize = NULL;
927
928 if (strcmp(plugin_uri, BSLIZR_URI) != 0)
929 {
930 std::cerr << "BSlizr.lv2#GUI: GUI does not support plugin with URI " << plugin_uri << std::endl;
931 return NULL;
932 }
933
934 for (int i = 0; features[i]; ++i)
935 {
936 if (!strcmp(features[i]->URI, LV2_UI__parent)) parentWindow = (PuglNativeView) features[i]->data;
937 else if (!strcmp(features[i]->URI, LV2_UI__resize)) resize = (LV2UI_Resize*)features[i]->data;
938 }
939 if (parentWindow == 0) std::cerr << "BSlizr.lv2#GUI: No parent window.\n";
940
941 // New instance
942 BSlizr_GUI* ui;
943 try {ui = new BSlizr_GUI (bundle_path, features, parentWindow);}
944 catch (std::exception& exc)
945 {
946 std::cerr << "BSlizr.lv2#GUI: Instantiation failed. " << exc.what () << std::endl;
947 return NULL;
948 }
949
950 ui->controller = controller;
951 ui->write_function = write_function;
952
953 // Reduce min GUI size for small displays
954 double sz = 1.0;
955 int screenWidth = getScreenWidth ();
956 int screenHeight = getScreenHeight ();
957 if ((screenWidth < 820) || (screenHeight < 600)) sz = 0.66;
958
959 /*
960 std::cerr << "BSlizr_GUI.lv2 screen size " << screenWidth << " x " << screenHeight <<
961 ". Set GUI size to " << 800 * sz << " x " << 560 * sz << ".\n";
962 */
963
964 if (resize) resize->ui_resize(resize->handle, 800 * sz, 560 * sz);
965
966 *widget = (LV2UI_Widget) puglGetNativeWindow (ui->getPuglView ());
967 ui->send_record_on();
968 return (LV2UI_Handle) ui;
969 }
970
cleanup(LV2UI_Handle ui)971 static void cleanup(LV2UI_Handle ui)
972 {
973 BSlizr_GUI* pluginGui = (BSlizr_GUI*) ui;
974 if (pluginGui) delete pluginGui;
975 }
976
portEvent(LV2UI_Handle ui,uint32_t port_index,uint32_t buffer_size,uint32_t format,const void * buffer)977 static void portEvent(LV2UI_Handle ui, uint32_t port_index, uint32_t buffer_size,
978 uint32_t format, const void* buffer)
979 {
980 BSlizr_GUI* pluginGui = (BSlizr_GUI*) ui;
981 if (pluginGui) pluginGui->portEvent(port_index, buffer_size, format, buffer);
982 }
983
callIdle(LV2UI_Handle ui)984 static int callIdle (LV2UI_Handle ui)
985 {
986 BSlizr_GUI* pluginGui = (BSlizr_GUI*) ui;
987 if (pluginGui) pluginGui->handleEvents ();
988 return 0;
989 }
990
callResize(LV2UI_Handle ui,int width,int height)991 static int callResize (LV2UI_Handle ui, int width, int height)
992 {
993 BSlizr_GUI* self = (BSlizr_GUI*) ui;
994 if (!self) return 0;
995
996 BEvents::ExposeEvent* ev = new BEvents::ExposeEvent (self, self, BEvents::CONFIGURE_REQUEST_EVENT, self->getPosition().x, self->getPosition().y, width, height);
997 self->addEventToQueue (ev);
998 return 0;
999 }
1000
1001 static const LV2UI_Idle_Interface idle = {callIdle};
1002 static const LV2UI_Resize resize = {nullptr, callResize};
1003
extensionData(const char * uri)1004 static const void* extensionData(const char* uri)
1005 {
1006 if (!strcmp(uri, LV2_UI__idleInterface)) return &idle;
1007 else if(!strcmp(uri, LV2_UI__resize)) return &resize;
1008 else return NULL;
1009 }
1010
1011 static const LV2UI_Descriptor guiDescriptor = {
1012 BSLIZR_GUI_URI,
1013 instantiate,
1014 cleanup,
1015 portEvent,
1016 extensionData
1017 };
1018
1019 // LV2 Symbol Export
lv2ui_descriptor(uint32_t index)1020 LV2_SYMBOL_EXPORT const LV2UI_Descriptor *lv2ui_descriptor(uint32_t index)
1021 {
1022 switch (index) {
1023 case 0: return &guiDescriptor;
1024 default:return NULL;
1025 }
1026 }
1027