1 /*
2  * Author: Harry van Haaren 2013
3  *         harryhaaren@gmail.com
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
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.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <string>
20 #include <iostream>
21 
22 #include <FL/x.H>
23 
24 // include the URI and global data of this plugin
25 #include "ports.h"
26 
27 // this is our custom widget include
28 #include "sorcer_widget.h"
29 
30 // core spec include
31 #include "lv2/lv2plug.in/ns/lv2core/lv2.h"
32 
33 // GUI
34 #include "lv2/lv2plug.in/ns/extensions/ui/ui.h"
35 
36 using namespace std;
37 
38 typedef struct {
39   SorcerUI* widget;
40 
41   float sidechainAmp;
42 
43   LV2UI_Write_Function write_function;
44   LV2UI_Controller controller;
45 } SorcerGUI;
46 
instantiate(const struct 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)47 static LV2UI_Handle instantiate(const struct LV2UI_Descriptor * descriptor,
48                 const char * plugin_uri,
49                 const char * bundle_path,
50                 LV2UI_Write_Function write_function,
51                 LV2UI_Controller controller,
52                 LV2UI_Widget * widget,
53                 const LV2_Feature * const * features)
54 {
55   if (strcmp(plugin_uri, SORCER_URI) != 0) {
56       fprintf(stderr, "SORCER_URI error: this GUI does not support plugin with URI %s\n", plugin_uri);
57       return NULL;
58   }
59 
60   SorcerGUI* self = (SorcerGUI*)malloc(sizeof(SorcerGUI));
61   if (self == NULL) return NULL;
62 
63   self->controller     = controller;
64   self->write_function = write_function;
65 
66   void* parentXwindow = 0;
67   LV2UI_Resize* resize = NULL;
68 
69   for (int i = 0; features[i]; ++i) {
70     if (!strcmp(features[i]->URI, LV2_UI__parent)) {
71       parentXwindow = features[i]->data;
72     } else if (!strcmp(features[i]->URI, LV2_UI__resize)) {
73       resize = (LV2UI_Resize*)features[i]->data;
74     }
75   }
76 
77   // in case FLTK hasn't opened it yet
78   fl_open_display();
79 
80   self->widget = new SorcerUI();
81 
82   self->widget->window->border(0);
83   self->widget->subbass->X(0.5);
84 
85   // write functions into the widget
86   self->widget->controller = controller;
87   self->widget->write_function = write_function;
88 
89   // set host to change size of the window
90   if (resize)
91   {
92     resize->ui_resize(resize->handle, self->widget->getWidth(), self->widget->getHeight());
93   }
94   else
95   {
96     cout << "SorcerUI: Warning, host doesn't support resize extension.\n\
97     Please ask the developers of the host to support this extension. "<< endl;
98   }
99 
100   fl_embed( self->widget->window, (Window)parentXwindow );
101 
102 
103   return (LV2UI_Handle)self;
104 }
105 
106 
107 
cleanup(LV2UI_Handle ui)108 static void cleanup(LV2UI_Handle ui) {
109   SorcerGUI *pluginGui = (SorcerGUI *) ui;
110   delete pluginGui->widget;
111   free( pluginGui);
112 }
113 
port_event(LV2UI_Handle ui,uint32_t port_index,uint32_t buffer_size,uint32_t format,const void * buffer)114 static void port_event(LV2UI_Handle ui,
115                uint32_t port_index,
116                uint32_t buffer_size,
117                uint32_t format,
118                const void * buffer)
119 {
120   SorcerGUI *self = (SorcerGUI *) ui;
121 
122   if ( format == 0 )
123   {
124     float value =  *(float *)buffer;
125     switch ( port_index )
126     {
127 
128       case ADSR_ATTACK: {
129             self->widget->adsr->attack( value );
130             self->widget->attack->value( value );
131             } break;
132       case ADSR_DECAY: {
133             self->widget->adsr->decay( value );
134             self->widget->decay->value( value );
135             } break;
136       case ADSR_SUSTAIN: {
137             self->widget->adsr->sustain( value );
138             self->widget->sustain->value( value );
139             } break;
140       case ADSR_RELEASE: {
141             self->widget->adsr->release( value );
142             self->widget->release->value( value );
143             } break;
144 
145       case VOLUME: {
146             self->widget->volume->value( value );
147             } break;
148       case OUTPUT_DB: {
149             float tmp = (1-(value / -96.f));
150             self->widget->volume->amplitude( tmp, tmp );
151             } break;
152 
153       case COMPRESSOR_ATTACK: {
154             self->widget->compAttack->value( value );
155             } break;
156       case COMPRESSOR_RELEASE: {
157             self->widget->compRelease->value( value );
158             } break;
159       case COMPRESSOR_MAKEUP: {
160             self->widget->compMakeup->value( value );
161             } break;
162       case COMPRESSOR_THRESHOLD: {
163             self->widget->compThres->value( value );
164             } break;
165       case COMPRESSOR_ENABLE: {
166 
167             self->widget->comp->set_active( value > 0.5 ? true : false );
168             } break;
169 
170       case FILTER_CUTOFF: {
171             self->widget->filter->value( value );
172             self->widget->filterCutoff->value( value );
173             } break;
174       case LFO_TO_FILTER_RANGE: {
175             self->widget->filter->modulation( value );
176             self->widget->filterLfoMod->value( value );
177             } break;
178 
179       case LFO_TO_WAVETABLE_1: {
180             self->widget->wave1->modulation( value );
181             self->widget->lfoToW1->value( value );
182             } break;
183       case LFO_TO_WAVETABLE_2: {
184             self->widget->wave2->modulation( value );
185             self->widget->lfoToW2->value( value );
186             } break;
187 
188       case LFO_AMPLITUDE: {
189             self->widget->lfo->value( value );
190             self->widget->lfoAmp->value( value );
191             } break;
192       case LFO_FREQUENCY: {
193             self->widget->lfo->modulation( value );
194             self->widget->lfoSpeed->value( value );
195             } break;
196 
197       case OSC_1_VOLUME: {
198             self->widget->wave1->Y( value );
199             } break;
200       case OSC_2_VOLUME: {
201             self->widget->wave2->Y( value );
202             } break;
203       case OSC_3_VOLUME: {
204             self->widget->subbass->Y( value );
205             } break;
206 
207 
208       case WAVETABLE_1_POS: {
209             self->widget->wave1->X( value );
210             } break;
211       case WAVETABLE_2_POS: {
212             self->widget->wave2->X( value );
213             } break;
214     }
215   }
216 
217   return;
218 }
219 
220 
ui_show(LV2UI_Handle handle)221 static int ui_show(LV2UI_Handle handle)
222 {
223   SorcerGUI *self = (SorcerGUI *) handle;
224   self->widget->window->show();
225 
226   return 0;
227 }
228 
ui_hide(LV2UI_Handle handle)229 static int ui_hide(LV2UI_Handle handle)
230 {
231   SorcerGUI *self = (SorcerGUI *) handle;
232   self->widget->window->hide();
233 
234   return 0;
235 }
236 
237 static int
idle(LV2UI_Handle handle)238 idle(LV2UI_Handle handle)
239 {
240   SorcerGUI* self = (SorcerGUI*)handle;
241 
242   self->widget->idle();
243 
244   return 0;
245 }
246 
247 static const void*
extension_data(const char * uri)248 extension_data(const char* uri)
249 {
250   static const LV2UI_Show_Interface show = { ui_show, ui_hide };
251   static const LV2UI_Idle_Interface idle_iface = { idle };
252 
253   if (!strcmp(uri, LV2_UI__showInterface))
254   {
255     return (void*)&show;
256   }
257   else if (!strcmp(uri, LV2_UI__idleInterface))
258   {
259     return (void*)&idle_iface;
260   }
261   return NULL;
262 }
263 
264 static LV2UI_Descriptor descriptors[] = {
265     {SORCER_UI_URI, instantiate, cleanup, port_event, extension_data}
266 };
267 
lv2ui_descriptor(uint32_t index)268 const LV2UI_Descriptor * lv2ui_descriptor(uint32_t index)
269 {
270   if (index >= sizeof(descriptors) / sizeof(descriptors[0]))
271   {
272       return NULL;
273   }
274   return descriptors + index;
275 }
276