1 /***************************************************************************
2  *   Copyright (C) 2009 by Pere Ràfols Soler                               *
3  *   sapista2@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 2 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, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 
21 #ifndef EQ_MAIN_WIN_H
22   #define EQ_MAIN_WIN_H
23 
24 #include <iostream>
25 #include <string>
26 
27 
28 #include <gtkmm/alignment.h>
29 #include <gtkmm/box.h>
30 #include <gtkmm/messagedialog.h>
31 #include <gtkmm/image.h>
32 
33 #include <cmath>
34 
35 //LV2 UI header
36 #include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
37 #include <lv2/lv2plug.in/ns/ext/atom/forge.h>
38 #include <lv2/lv2plug.in/ns/ext/atom/util.h>
39 #include <lv2/lv2plug.in/ns/ext/urid/urid.h>
40 #include "../../uris.h"
41 
42 #include "mainwidget.h"
43 #include "bandctl.h"
44 #include "vuwidget.h"
45 #include "knob2.h"
46 #include "eqparams.h"
47 #include "bodeplot.h"
48 #include "button.h"
49 #include "toggle_button.h"
50 #include "abbutton.h"
51 #include "sidechainbox.h"
52 
53 //Include eq definition
54 #include "../eq_defines.h"
55 
56 #define IMAGE_LOGO_PATH "icons/logoeq10q.png"
57 #define TIMER_VALUE_MS 100
58 
59 //Test print information, comment out for the final release
60 //#define PRINT_DEBUG_INFO
61 
62 using namespace sigc;
63 
64 class EqMainWindow : public MainWidget
65 {
66   public:
67     EqMainWindow(int iAudioChannels, int iNumBands, const char *uri, const char *bundlePath, const LV2_Feature *const *features);
68     virtual ~EqMainWindow();
69     void request_sample_rate();
70 
71     // Informing GUI about changes in the control ports
gui_port_event(LV2UI_Handle ui,uint32_t port,uint32_t buffer_size,uint32_t format,const void * buffer)72     void gui_port_event(LV2UI_Handle ui, uint32_t port, uint32_t buffer_size, uint32_t format, const void * buffer)
73     {
74       //Atom event from DSP
75       if((int)port == (PORT_OFFSET + 2*m_iNumOfChannels + 5*m_iNumOfBands + 2*m_iNumOfChannels))
76       {
77 
78           const LV2_Atom* atom = (const LV2_Atom*)buffer;
79 
80           if (format == uris.atom_eventTransfer && atom->type == uris.atom_Object)
81           {
82             const LV2_Atom_Object* obj = (const LV2_Atom_Object*)atom;
83 
84             if(obj->body.otype == uris.atom_sample_rate_response)
85             {
86                 const LV2_Atom* samplerate_val = NULL;
87                 const int n_props  = lv2_atom_object_get(obj, uris.atom_sample_rate_key, &samplerate_val, NULL);
88 
89               if (n_props != 1 ||   samplerate_val->type != uris.atom_Double)
90               {
91                 std::cout<<"Atom Object does not have the required properties (sample-rate) with correct types"<<std::endl;
92               }
93               else
94               {
95                 SampleRate = ((const LV2_Atom_Double*)samplerate_val)->body;
96                 m_Bode->setSampleRate(SampleRate);
97               }
98             }
99 
100             else if(obj->body.otype == uris.atom_fft_data_event)
101             {
102               const LV2_Atom* fftdata_val = NULL;
103               const int n_props  = lv2_atom_object_get(obj, uris.atom_fft_data_key, &fftdata_val, NULL);
104 
105               if (n_props != 1 || fftdata_val->type != uris.atom_Vector)
106               {
107                 std::cout<<"Atom Object does not have the required properties (fft-data) with correct types"<<std::endl;
108               }
109               else
110               {
111                 const LV2_Atom_Vector* vec = (const LV2_Atom_Vector*)fftdata_val;
112                 if (vec->body.child_type != uris.atom_Double)
113                 {
114                    std::cout<<"Atom fft Vector has incorrect element type"<<std::endl;
115                 }
116                 else
117                 {
118                   // Number of elements = (total size - header size) / element size
119                   const size_t n_elem = ((fftdata_val->size - sizeof(LV2_Atom_Vector_Body))/ sizeof(double));
120 
121                   //std::cout<<"N Elem "<<n_elem << std::endl;
122 
123                   //Copy data to bodeplot
124                   if(n_elem == ((FFT_N/2) + 1))
125                   {
126                     // Double elements immediately follow the vector body header
127                     m_Bode->setFftData((double*)(&vec->body + 1));
128                   }
129                 }
130               }
131             }
132           }
133       }//End of Atom ports reading
134 
135 
136       //Standard LV2 ports handling
137       float data = * static_cast<const float*>(buffer);
138 
139       #ifdef PRINT_DEBUG_INFO
140 	std::cout<<"gui_port_event Entring....... "<<std::endl;
141       #endif
142 
143         // Checking if params are the same as specified in the LV2 documentation for no-atom ports
144         if (format != 0) {
145 	    #ifdef PRINT_DEBUG_INFO
146 	      std::cout<<"\t-- Return Format != 0"<<std::endl;
147 	    #endif
148             return;
149         }
150         if (buffer_size != 4) {
151 	    #ifdef PRINT_DEBUG_INFO
152 	      std::cout<<"\t-- Return buffer_size != 4"<<std::endl;
153 	    #endif
154             return;
155         }
156 
157         // Updating values in GUI ========================================================
158 	switch (port)
159 	{
160 	  case EQ_BYPASS:
161 	    m_bypassValue = data > 0.5 ? 1 : 0;
162 	    m_port_event_Bypass = true; //Marck port even boolean
163 	    ///m_BypassButton.set_active(data > 0.5);
164 	    #ifdef PRINT_DEBUG_INFO
165 	      std::cout<<"\t-- BYPASS"<<std::endl;
166 	    #endif
167 	  break;
168 
169 	  case EQ_INGAIN:
170 	    //m_InGainValue = data;
171 	    m_CurParams->setInputGain(data);
172 	    m_port_event_InGain = true; //Marck port even boolean
173 	    ///m_InGain->setGain(data);
174 
175 	    #ifdef PRINT_DEBUG_INFO
176 	      std::cout<<"\t-- Input Gain"<<std::endl;
177 	    #endif
178 	  break;
179 
180 	  case EQ_OUTGAIN:
181 	    //m_OutGainValue = data;
182 	    m_CurParams->setOutputGain(data);
183 	    m_port_event_OutGain = true; //Marck port even boolean
184 	    ///m_OutGain->setGain(data);
185 	    #ifdef PRINT_DEBUG_INFO
186 	      std::cout<<"\t-- Out Gain"<<std::endl;
187 	    #endif
188 	  break;
189 
190 	  default:
191 	    //Connect BandGain ports
192 	    if((int)port >= (PORT_OFFSET + 2*m_iNumOfChannels) && (int)port < (PORT_OFFSET + 2*m_iNumOfChannels + m_iNumOfBands))
193 	    {
194 	      ///m_BandCtlArray[(int)port - PORT_OFFSET - 2*m_iNumOfChannels]->setGain(data);
195 	      ///m_Bode->setBandGain((int)port - PORT_OFFSET - 2*m_iNumOfChannels, data);
196 	      m_CurParams->setBandGain((int)port - PORT_OFFSET - 2*m_iNumOfChannels, data);
197 	      m_port_event_Curve = true; //Marck port even boolean
198 	      m_port_event_Curve_Gain[(int)port - PORT_OFFSET - 2*m_iNumOfChannels] = true;
199 	      #ifdef PRINT_DEBUG_INFO
200 		std::cout<<"\t-- Band Gain"<<std::endl;
201 	      #endif
202 	    }
203 
204 	    //Connect BandFreq ports
205 	    else if((int)port >= (PORT_OFFSET + 2*m_iNumOfChannels + m_iNumOfBands) && (int)port < (PORT_OFFSET + 2*m_iNumOfChannels + 2*m_iNumOfBands))
206 	    {
207 	      ///m_BandCtlArray[(int)port - PORT_OFFSET - 2*m_iNumOfChannels - m_iNumOfBands]->setFreq(data);
208 	      ///m_Bode->setBandFreq((int)port - PORT_OFFSET - 2*m_iNumOfChannels - m_iNumOfBands, data);
209 	      m_CurParams->setBandFreq((int)port - PORT_OFFSET - 2*m_iNumOfChannels - m_iNumOfBands, data);
210 	      m_port_event_Curve = true; //Marck port even boolean
211 	      m_port_event_Curve_Freq[(int)port - PORT_OFFSET - 2*m_iNumOfChannels - m_iNumOfBands] = true;
212 	      #ifdef PRINT_DEBUG_INFO
213 		std::cout<<"\t-- Band Freq"<<std::endl;
214 	      #endif
215 	    }
216 
217 	    //Connect BandParam ports
218 	    else if((int)port >= (PORT_OFFSET + 2*m_iNumOfChannels + 2*m_iNumOfBands) && (int)port < (PORT_OFFSET + 2*m_iNumOfChannels + 3*m_iNumOfBands))
219 	    {
220 	      ///m_BandCtlArray[(int)port - PORT_OFFSET - 2*m_iNumOfChannels - 2*m_iNumOfBands]->setQ(data);
221 	      ///m_Bode->setBandQ((int)port - PORT_OFFSET - 2*m_iNumOfChannels - 2*m_iNumOfBands, data);
222 	      m_CurParams->setBandQ((int)port - PORT_OFFSET - 2*m_iNumOfChannels - 2*m_iNumOfBands, data);
223 	      m_port_event_Curve = true; //Marck port even boolean
224 	      m_port_event_Curve_Q[(int)port - PORT_OFFSET - 2*m_iNumOfChannels - 2*m_iNumOfBands] = true;
225 	      #ifdef PRINT_DEBUG_INFO
226 		std::cout<<"\t-- Band Q"<<std::endl;
227 	      #endif
228 	    }
229 
230 	    //Connect BandType ports
231 	    else if((int)port >= (PORT_OFFSET + 2*m_iNumOfChannels + 3*m_iNumOfBands) && (int)port < (PORT_OFFSET + 2*m_iNumOfChannels + 4*m_iNumOfBands))
232 	    {
233 	      ///m_BandCtlArray[(int)port - PORT_OFFSET - 2*m_iNumOfChannels - 3*m_iNumOfBands]->setFilterType(data);
234 	      ///m_Bode->setBandType((int)port - PORT_OFFSET - 2*m_iNumOfChannels - 3*m_iNumOfBands, data);
235 	      m_CurParams->setBandType((int)port - PORT_OFFSET - 2*m_iNumOfChannels - 3*m_iNumOfBands, ((int)data) & 0xFF);
236 	      m_port_event_Curve = true; //Marck port even boolean
237 	      m_port_event_Curve_Type[(int)port - PORT_OFFSET - 2*m_iNumOfChannels - 3*m_iNumOfBands] = true;
238 	      #ifdef PRINT_DEBUG_INFO
239 		std::cout<<"\t-- Band Type"<<std::endl;
240 	      #endif
241 	    }
242 
243 	    //Connect BandEnabled ports
244 	    else if((int)port >= (PORT_OFFSET + 2*m_iNumOfChannels + 4*m_iNumOfBands) && (int)port < (PORT_OFFSET + 2*m_iNumOfChannels + 5*m_iNumOfBands))
245 	    {
246 	      ///m_BandCtlArray[(int)port - PORT_OFFSET - 2*m_iNumOfChannels - 4*m_iNumOfBands]->setEnabled(data > 0.5);
247 	      ///m_Bode->setBandEnable((int)port - PORT_OFFSET - 2*m_iNumOfChannels - 4*m_iNumOfBands, data > 0.5);
248 
249               int iMidSide = (int)data >> 1;
250               const int sel_band = (int)port - PORT_OFFSET - 2*m_iNumOfChannels - 4*m_iNumOfBands;
251               switch(iMidSide)
252               {
253                 case 0:
254 		  m_BandCtlArray[sel_band]->setStereoState(BandCtl::DUAL);
255 		  if(m_iNumOfChannels == 1)
256 		  {
257 		    m_Bode->setStereoState(sel_band, PlotEQCurve::MONO);
258 		  }
259 		  else
260 		  {
261 		    m_Bode->setStereoState(sel_band, PlotEQCurve::DUAL);
262 		  }
263                   break;
264 
265                 case 1:
266                   m_BandCtlArray[sel_band]->setStereoState(BandCtl::ML);
267                   m_Bode->setStereoState(sel_band, PlotEQCurve::ML);
268                   break;
269 
270                 case 2:
271                   m_BandCtlArray[sel_band]->setStereoState(BandCtl::SR);
272                   m_Bode->setStereoState(sel_band, PlotEQCurve::SR);
273                   break;
274               }
275 
276               int iEnable = (int)data & 0x01;
277 	      m_CurParams->setBandEnabled(sel_band, iEnable > 0);
278 	      m_port_event_Curve = true; //Marck port even boolean
279 	      m_port_event_Curve_Enable[sel_band] = true;
280 	      #ifdef PRINT_DEBUG_INFO
281 		std::cout<<"\t-- Band Enabled"<<std::endl;
282 	      #endif
283 	    }
284 
285 	    //Connect VuInput ports
286 	    else if((int)port >= (PORT_OFFSET + 2*m_iNumOfChannels + 5*m_iNumOfBands) && (int)port < (PORT_OFFSET + 2*m_iNumOfChannels + 5*m_iNumOfBands + m_iNumOfChannels))
287 	    {
288               m_VuMeterIn->setValue((int)port - PORT_OFFSET - 2*m_iNumOfChannels - 5*m_iNumOfBands,data);
289 	      #ifdef PRINT_DEBUG_INFO
290 		std::cout<<"\t-- Vu input"<<std::endl;
291 	      #endif
292 	    }
293 
294 	    //Connect VuOutput ports
295 	    else if((int)port >= (PORT_OFFSET + 2*m_iNumOfChannels + 5*m_iNumOfBands + m_iNumOfChannels) && (int)port < (PORT_OFFSET + 2*m_iNumOfChannels + 5*m_iNumOfBands + 2*m_iNumOfChannels))
296 	    {
297               m_VuMeterOut->setValue((int)port - PORT_OFFSET - 2*m_iNumOfChannels - 5*m_iNumOfBands - m_iNumOfChannels, data);
298 	      #ifdef PRINT_DEBUG_INFO
299 		std::cout<<"\t-- Vu output"<<std::endl;
300 	      #endif
301 	    }
302 
303 	    //Connect Stereo Mode port
304             else if((int)port == (PORT_OFFSET + 2*m_iNumOfChannels + 5*m_iNumOfBands + 2*m_iNumOfChannels + 2))
305             {
306               setStereoMode( data > 0.5);
307               #ifdef PRINT_DEBUG_INFO
308                 std::cout<<"\t-- Mid Side"<<std::endl;
309               #endif
310             }
311 
312 	    //No more ports here
313 	    else
314 	    {
315 	      #ifdef PRINT_DEBUG_INFO
316 		std::cout<<"\t--  Return port index is out of range"<<std::endl;
317 	      #endif
318 	      return;
319 	    }
320 	  break;
321 	}
322 
323 	#ifdef PRINT_DEBUG_INFO
324 	  std::cout<<"\t--  Return OK"<<std::endl;
325 	#endif
326 
327     }
328 
329     LV2UI_Controller controller;
330     LV2UI_Write_Function write_function;
331     Eq10qURIs uris;
332     LV2_URID_Map*  map;
333     LV2_Atom_Forge forge;
334 
335   protected:
336     EqParams *m_AParams, *m_BParams, *m_CurParams;
337     BandCtl **m_BandCtlArray;
338     Gtk::HBox m_BandBox, m_ABFlatBox, m_GainEqBox, m_PlotBox;
339     Gtk::VBox m_CurveBypassBandsBox, m_MainBox, m_InGainBox, m_OutGainBox, m_FftCtlVBox, m_dBScaleBox, m_FftdBBox, m_StereoBox;
340     ToggleButton m_BypassButton, m_FftRtaActive, m_FftSpecActive, m_dB10Scale, m_dB25Scale, m_dB50Scale, m_LRStereoMode, m_MSStereoMode;
341     AbButton m_AButton;
342     Gtk::Alignment m_FlatAlign, m_ABAlign, m_ButtonAAlign, m_BypassAlign, m_LoadAlign, m_SaveAlign, m_FftAlign, m_FftAlignInner, m_FftAlngGain, m_FftAlngRange, m_dBScaleAlign, m_dBScaleAlignInner, m_StereoInnerAlng, m_StereAlng;
343     Button m_FlatButton, m_SaveButton, m_LoadButton, m_FftHold;
344     Gtk::Alignment m_MainWidgetAlign;
345     PlotEQCurve *m_Bode;
346     Gtk::Image *image_logo_center;
347     KnobWidget2 *m_GainFaderIn, *m_GainFaderOut, *m_FftGain, *m_FftRange;
348     VUWidget *m_VuMeterIn, *m_VuMeterOut;
349     SideChainBox *m_FftBox, *m_dBScaleFrame, *m_MidSideBox;
350 
351     void loadEqParams();
352     void changeAB(EqParams *toBeCurrent);
353     void saveToFile();
354     void loadFromFile();
355     void sendAtomFftOn(bool fft_activated);
356     void setStereoMode(bool isMidSide);
357 
358     //Signal Handlers
359     void onButtonA();
360     void onButtonFlat();
361     void onButtonBypass();
362     void onBandChange(int iBand, int iField, float fValue);
363     void onInputGainChange();
364     void onOutputGainChange();
365     void onCurveChange(int band_ix, float Gain, float Freq, float Q);
366     void onCurveBandEnable(int band_ix, bool IsEnabled);
367     bool on_timeout();
368     void onButtonFftRta();
369     void onButtonFftSpc();
370     void onHoldFft_press();
371     void onHoldFft_release();
372     void onFftGainScale();
373     void onFftRangeScale();
374     void onBodeSelectBand(int band);
375     void onBodeUnselectBand();
376     void onBandCtlSelectBand(int band);
377     void onBandCtlUnselectBand();
378     void onBandCtlMidSideChanged(int band);
379 
380     void onDbScale10Changed();
381     void onDbScale25Changed();
382     void onDbScale50Changed();
383 
384     void onLeftRightModeSelected();
385     void onMidSideModeSelected();
386 
387 
388   private:
389     double SampleRate;
390     float m_bypassValue;
391     const int m_iNumOfChannels;
392     const int m_iNumOfBands;
393     bool m_bMutex, m_port_event_InGain, m_port_event_OutGain, m_port_event_Bypass, m_port_event_Curve;
394     bool *m_port_event_Curve_Gain, *m_port_event_Curve_Freq, *m_port_event_Curve_Q, *m_port_event_Curve_Type, *m_port_event_Curve_Enable;
395     std::string m_pluginUri;
396     std::string m_bundlePath;
397 };
398 
399 #endif
400