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 #include "filter.h"
22 #include "colors.h"
23 #include "guiconstants.h"
24 #include "bandctl.h"
25 #include "toggle_button.h" //To draw the LED using a static function
26 
27 #include <gdkmm.h>
28 #include <iostream>
29 #include <iomanip>
30 #include <cmath>
31 
32 #define OUTER_BORDER 1.5
33 #define FONT_SIZE 11
34 #define ACCELERATION 15.0
35 #define SCROLL_EVENT_PERCENT 0.005
36 #define LPF_ICON_FILE "combopix/lpf.png"
37 #define HPF_ICON_FILE "combopix/hpf.png"
38 #define LOSHEL_ICON_FILE "combopix/loshelf.png"
39 #define HISHEL_ICON_FILE "combopix/hishelf.png"
40 #define PEAK_ICON_FILE "combopix/peak.png"
41 #define NOTCH_ICON_FILE "combopix/notch.png"
42 
BandCtl(const int iBandNum,bool * bSemafor,const char * bundlepath,bool isStereo)43 BandCtl::BandCtl( const int iBandNum, bool *bSemafor, const char* bundlepath, bool isStereo):
44 m_bBtnInitialized(false),
45 m_TypePopUp(0),
46 m_iBandNum(iBandNum),
47 m_bBandIsEnabled(false),
48 m_budlepath(bundlepath),
49 m_iAntValueX(0),
50 m_iAntValueY(0),
51 m_HpfLpf_slope(0),
52 m_bGlowBand(false),
53 m_bIsStereoPlugin(isStereo)
54 {
55   //Init button values to something
56   m_GainBtn.value = 0.0f;
57   m_FreqBtn.value = 1e3f;
58   m_QBtn.value = 2.0f;
59   m_GainBtn.units = "dB";
60   m_FreqBtn.units = "Hz";
61   m_QBtn.units = "Q";
62 
63   m_FilterType = int2FilterType(0.0f);
64   m_BandTitle = Glib::ustring::compose("Band %1", m_iBandNum + 1);
65   m_Color  = Gdk::Color(bandColorLUT[m_iBandNum]);
66 
67   //Load ComboBox images
68   m_img_ptr_lpf =  Gdk::Pixbuf::create_from_file(m_budlepath + "/" + std::string(LPF_ICON_FILE));
69   m_img_ptr_hpf =  Gdk::Pixbuf::create_from_file(m_budlepath + "/" + std::string(HPF_ICON_FILE));
70   m_img_ptr_loshelf =  Gdk::Pixbuf::create_from_file(m_budlepath + "/" + std::string(LOSHEL_ICON_FILE));
71   m_img_ptr_hishelf =  Gdk::Pixbuf::create_from_file(m_budlepath + "/" + std::string(HISHEL_ICON_FILE));
72   m_img_ptr_peak =  Gdk::Pixbuf::create_from_file(m_budlepath + "/" + std::string(PEAK_ICON_FILE));
73   m_img_ptr_notch =  Gdk::Pixbuf::create_from_file(m_budlepath + "/" + std::string(NOTCH_ICON_FILE));
74 
75   m_FilterType = PEAK;
76   loadTypeImg();
77   set_size_request(46 + m_image_surface_ptr->get_width(), ( m_bIsStereoPlugin ? 80 : 65) + m_image_surface_ptr->get_height());
78 
79   //Fill Filter Type popup menu
80   m_TypePopUp = new Gtk::Menu();
81 
82   icon_lpf = new Gtk::Image(m_img_ptr_lpf);
83   icon_hpf = new Gtk::Image(m_img_ptr_hpf);
84   icon_loShel = new Gtk::Image(m_img_ptr_loshelf);
85   icon_hiShel = new Gtk::Image(m_img_ptr_hishelf);
86   icon_peak = new Gtk::Image(m_img_ptr_peak);
87   icon_notch = new Gtk::Image(m_img_ptr_notch);
88 
89   itm_lpf = new Gtk::ImageMenuItem(*icon_lpf,"Low pass");
90   itm_hpf = new Gtk::ImageMenuItem(*icon_hpf,"High pass");
91   itm_loShel = new Gtk::ImageMenuItem(*icon_loShel,"Low Shelf");
92   itm_hiShel = new Gtk::ImageMenuItem(*icon_hiShel,"High Shelf");
93   itm_peak = new Gtk::ImageMenuItem(*icon_peak,"Peak");
94   itm_notch = new Gtk::ImageMenuItem(*icon_notch,"Notch");
95 
96   //Allow this widget to get keyboard focus
97   set_flags(Gtk::CAN_FOCUS);
98   set_can_focus(true);
99 
100   itm_lpf->set_always_show_image(true);
101   itm_hpf->set_always_show_image(true);
102   itm_loShel->set_always_show_image(true);
103   itm_hiShel->set_always_show_image(true);
104   itm_peak->set_always_show_image(true);
105   itm_notch->set_always_show_image(true);
106 
107   itm_lpf->signal_activate().connect(sigc::mem_fun(*this, &BandCtl::on_menu_lpf));
108   itm_hpf->signal_activate().connect(sigc::mem_fun(*this, &BandCtl::on_menu_hpf));
109   itm_loShel->signal_activate().connect(sigc::mem_fun(*this, &BandCtl::on_menu_loshelf));
110   itm_hiShel->signal_activate().connect(sigc::mem_fun(*this, &BandCtl::on_menu_hishelf));
111   itm_peak->signal_activate().connect(sigc::mem_fun(*this, &BandCtl::on_menu_peak));
112   itm_notch->signal_activate().connect(sigc::mem_fun(*this, &BandCtl::on_menu_notch));
113   m_TypePopUp->signal_hide().connect(sigc::mem_fun(*this, &BandCtl::on_menu_hide));
114   signal_focus_out_event().connect(sigc::mem_fun(*this, &BandCtl::on_focus_out_event));
115 
116   m_TypePopUp->append(*itm_lpf);
117   m_TypePopUp->append(*itm_hpf);
118   m_TypePopUp->append(*itm_loShel);
119   m_TypePopUp->append(*itm_hiShel);
120   m_TypePopUp->append(*itm_peak);
121   m_TypePopUp->append(*itm_notch);
122   m_TypePopUp->set_size_request(110 ,-1);
123 
124   //Setup MidSide button
125   m_MidSideBtn.MidSideMode = false;
126   m_MidSideBtn.State = DUAL;
127 
128   show();
129 
130   //Connect mouse signals
131   add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::SCROLL_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::KEY_PRESS_MASK);
132   signal_button_press_event().connect(sigc::mem_fun(*this, &BandCtl::on_button_press_event),true);
133   signal_button_release_event().connect(sigc::mem_fun(*this, &BandCtl::on_button_release_event),true);
134   signal_scroll_event().connect(sigc::mem_fun(*this, &BandCtl::on_scrollwheel_event),true);
135   signal_motion_notify_event().connect(sigc::mem_fun(*this, &BandCtl::on_mouse_motion_event),true);
136   signal_leave_notify_event().connect(sigc::mem_fun(*this, &BandCtl::on_mouse_leave_widget),true);
137 
138   signal_key_press_event().connect(sigc::mem_fun(*this, &BandCtl::on_key_press_event)); //TODO
139 
140   Glib::RefPtr<Gtk::Style> sty =  Gtk::Style::create();
141   sty->set_font(Pango::FontDescription("sans 11px"));
142   sty->set_bg(Gtk::STATE_NORMAL, Gdk::Color("#3C3940"));
143   sty->set_bg(Gtk::STATE_PRELIGHT, Gdk::Color("#408FC0"));
144   sty->set_fg(Gtk::STATE_NORMAL, Gdk::Color("#CDCECE"));
145   sty->set_fg(Gtk::STATE_PRELIGHT, Gdk::Color("#161B17"));
146 
147 
148   m_TypePopUp->set_style(sty);
149 
150   itm_lpf->set_style(sty);
151   itm_hpf->set_style(sty);
152   itm_loShel->set_style(sty);
153   itm_hiShel->set_style(sty);
154   itm_peak->set_style(sty);
155   itm_notch->set_style(sty);
156 
157   itm_lpf->get_child()->set_style(sty);
158   itm_hpf->get_child()->set_style(sty);
159   itm_loShel->get_child()->set_style(sty);
160   itm_hiShel->get_child()->set_style(sty);
161   itm_peak->get_child()->set_style(sty);
162   itm_notch->get_child()->set_style(sty);
163 }
164 
~BandCtl()165 BandCtl::~BandCtl()
166 {
167     delete m_TypePopUp;
168 
169     delete icon_lpf;
170     delete icon_hpf;
171     delete icon_loShel;
172     delete icon_hiShel;
173     delete icon_peak;
174     delete icon_notch;
175 
176     delete itm_lpf;
177     delete itm_hpf;
178     delete itm_loShel;
179     delete itm_hiShel;
180     delete itm_peak;
181     delete itm_notch;
182 }
183 
glowBand(bool glow)184 void BandCtl::glowBand(bool glow)
185 {
186   m_bGlowBand = glow;
187   redraw();
188 }
189 
190 
loadTypeImg()191 void BandCtl::loadTypeImg()
192 {
193    Glib::RefPtr<Gdk::Pixbuf> img_ptr;
194 
195    switch(m_FilterType)
196    {
197      case HPF_ORDER_1:
198       img_ptr = m_img_ptr_hpf;
199       m_HpfLpf_slope = 20;
200       m_GainBtn.units = "dB/dec";
201      break;
202 
203      case HPF_ORDER_2:
204       img_ptr = m_img_ptr_hpf;
205       m_HpfLpf_slope = 40;
206       m_GainBtn.units = "dB/dec";
207      break;
208 
209      case HPF_ORDER_3:
210       img_ptr = m_img_ptr_hpf;
211       m_HpfLpf_slope = 60;
212       m_GainBtn.units = "dB/dec";
213      break;
214 
215      case HPF_ORDER_4:
216       img_ptr = m_img_ptr_hpf;
217       m_HpfLpf_slope = 80;
218       m_GainBtn.units = "dB/dec";
219      break;
220 
221      case LPF_ORDER_1:
222        img_ptr = m_img_ptr_lpf;
223        m_HpfLpf_slope = 20;
224        m_GainBtn.units = "dB/dec";
225     break;
226 
227      case LPF_ORDER_2:
228        img_ptr = m_img_ptr_lpf;
229        m_HpfLpf_slope = 40;
230        m_GainBtn.units = "dB/dec";
231     break;
232 
233      case LPF_ORDER_3:
234        img_ptr = m_img_ptr_lpf;
235        m_HpfLpf_slope = 60;
236        m_GainBtn.units = "dB/dec";
237     break;
238 
239      case LPF_ORDER_4:
240        img_ptr = m_img_ptr_lpf;
241        m_HpfLpf_slope = 80;
242        m_GainBtn.units = "dB/dec";
243      break;
244 
245      case HIGH_SHELF:
246        img_ptr = m_img_ptr_hishelf;
247        m_HpfLpf_slope = 0;
248        m_GainBtn.units = "dB";
249      break;
250 
251      case LOW_SHELF:
252        img_ptr = m_img_ptr_loshelf;
253        m_HpfLpf_slope = 0;
254        m_GainBtn.units = "dB";
255      break;
256 
257      case PEAK:
258        img_ptr = m_img_ptr_peak;
259        m_HpfLpf_slope = 0;
260        m_GainBtn.units = "dB";
261      break;
262 
263      case NOTCH:
264        img_ptr = m_img_ptr_notch;
265        m_HpfLpf_slope = 0;
266        m_GainBtn.units = "dB";
267      break;
268 
269      case NOT_SET:
270       return;
271      break;
272    }
273 
274    //Detect Format
275   Cairo::Format format = Cairo::FORMAT_RGB24;
276   if (img_ptr->get_has_alpha())
277   {
278     format = Cairo::FORMAT_ARGB32;
279   }
280 
281   // Create a new ImageSurface
282   m_image_surface_ptr = Cairo::ImageSurface::create  (format, img_ptr->get_width(), img_ptr->get_height());
283 
284   // Create the new Context for the ImageSurface
285   m_image_context_ptr = Cairo::Context::create (m_image_surface_ptr);
286 
287   // Draw the image on the new Context
288   Gdk::Cairo::set_source_pixbuf (m_image_context_ptr, img_ptr, 0.0, 0.0);
289   m_image_context_ptr->paint();
290 }
291 
292 
293 //Data accesors
getGain()294 float BandCtl::getGain(){
295   return m_GainBtn.value;
296 }
297 
getFreq()298 float BandCtl::getFreq(){
299   return m_FreqBtn.value;
300 }
301 
getQ()302 float BandCtl::getQ(){
303   return m_QBtn.value;
304 }
305 
getFilterType()306 float BandCtl::getFilterType(){
307   return (float)m_FilterType;
308 }
309 
getEnabled()310 bool BandCtl::getEnabled()
311 {
312   return m_bBandIsEnabled;
313 }
314 
setGain(float fGain)315 void BandCtl::setGain(float fGain){
316   m_GainBtn.value = fGain;
317   redraw();
318 }
319 
setFreq(float fFreq)320 void BandCtl::setFreq(float fFreq){
321   m_FreqBtn.value = fFreq;
322   redraw();
323 }
324 
setQ(float fQ)325 void BandCtl::setQ(float fQ){
326   m_QBtn.value = fQ;
327   redraw();
328 }
329 
setFilterType(float fType)330 void BandCtl::setFilterType(float fType)
331 {
332   m_FilterType = int2FilterType(fType);
333   loadTypeImg();
334   redraw();
335 }
336 
setEnabled(bool bIsEnabled)337 void BandCtl::setEnabled(bool bIsEnabled)
338 {
339   m_bBandIsEnabled = bIsEnabled;
340   redraw();
341 }
342 
signal_changed()343 BandCtl::signal_ctlBandChanged BandCtl::signal_changed()
344 {
345   return m_bandChangedSignal;
346 }
347 
signal_band_selected()348 BandCtl::signal_BandSelected BandCtl::signal_band_selected()
349 {
350   return m_bandSelectedSignal;
351 }
352 
signal_band_unselected()353 BandCtl::signal_BandUnSelected BandCtl::signal_band_unselected()
354 {
355   return m_bandUnSelectedSignal;
356 }
357 
signal_mid_side_changed()358 BandCtl::signal_MidSideChanged BandCtl::signal_mid_side_changed()
359 {
360   return m_midsideChangedSignal;
361 }
362 
363 
on_menu_lpf()364 void BandCtl::on_menu_lpf()
365 {
366   m_FilterType = LPF_ORDER_2;
367   loadTypeImg();
368   m_bandChangedSignal.emit(m_iBandNum, FILTER_TYPE, getFilterType());
369   m_bandChangedSignal.emit(m_iBandNum, GAIN_TYPE, m_GainBtn.value);
370   m_bandChangedSignal.emit(m_iBandNum, FREQ_TYPE, m_FreqBtn.value);
371   m_QBtn.value = HPF_LPF_Q_DEFAULT;
372   m_bandChangedSignal.emit(m_iBandNum, Q_TYPE, m_QBtn.value);
373   redraw();
374 }
375 
on_menu_hpf()376 void BandCtl::on_menu_hpf()
377 {
378   m_FilterType = HPF_ORDER_2;
379   loadTypeImg();
380   m_bandChangedSignal.emit(m_iBandNum, FILTER_TYPE, getFilterType());
381   m_bandChangedSignal.emit(m_iBandNum, GAIN_TYPE, m_GainBtn.value);
382   m_bandChangedSignal.emit(m_iBandNum, FREQ_TYPE, m_FreqBtn.value);
383   m_QBtn.value = HPF_LPF_Q_DEFAULT;
384   m_bandChangedSignal.emit(m_iBandNum, Q_TYPE, m_QBtn.value);
385   redraw();
386 }
387 
on_menu_loshelf()388 void BandCtl::on_menu_loshelf()
389 {
390   m_FilterType = LOW_SHELF;
391   loadTypeImg();
392   m_bandChangedSignal.emit(m_iBandNum, FILTER_TYPE, getFilterType());
393   m_bandChangedSignal.emit(m_iBandNum, GAIN_TYPE, m_GainBtn.value);
394   m_bandChangedSignal.emit(m_iBandNum, FREQ_TYPE, m_FreqBtn.value);
395   m_QBtn.value = HIGH_LOW_SHELF_Q_DEFAULT;
396   m_bandChangedSignal.emit(m_iBandNum, Q_TYPE, m_QBtn.value);
397   redraw();
398 }
399 
on_menu_hishelf()400 void BandCtl::on_menu_hishelf()
401 {
402   m_FilterType = HIGH_SHELF;
403   loadTypeImg();
404   m_bandChangedSignal.emit(m_iBandNum, FILTER_TYPE, getFilterType());
405   m_bandChangedSignal.emit(m_iBandNum, GAIN_TYPE, m_GainBtn.value);
406   m_bandChangedSignal.emit(m_iBandNum, FREQ_TYPE, m_FreqBtn.value);
407   m_QBtn.value = HIGH_LOW_SHELF_Q_DEFAULT;
408   m_bandChangedSignal.emit(m_iBandNum, Q_TYPE, m_QBtn.value);
409   redraw();
410 }
411 
on_menu_peak()412 void BandCtl::on_menu_peak()
413 {
414   m_FilterType = PEAK;
415   loadTypeImg();
416   m_bandChangedSignal.emit(m_iBandNum, FILTER_TYPE, getFilterType());
417   m_bandChangedSignal.emit(m_iBandNum, GAIN_TYPE, m_GainBtn.value);
418   m_bandChangedSignal.emit(m_iBandNum, FREQ_TYPE, m_FreqBtn.value);
419   m_QBtn.value = PEAK_Q_DEFAULT;
420   m_bandChangedSignal.emit(m_iBandNum, Q_TYPE, m_QBtn.value);
421   redraw();
422 }
423 
on_menu_notch()424 void BandCtl::on_menu_notch()
425 {
426   m_FilterType = NOTCH;
427   loadTypeImg();
428   m_bandChangedSignal.emit(m_iBandNum, FILTER_TYPE, getFilterType());
429   m_bandChangedSignal.emit(m_iBandNum, GAIN_TYPE, m_GainBtn.value);
430   m_bandChangedSignal.emit(m_iBandNum, FREQ_TYPE, m_FreqBtn.value);
431   m_QBtn.value = NOTCH_Q_DEFAULT;
432   m_bandChangedSignal.emit(m_iBandNum, Q_TYPE, m_QBtn.value);
433   redraw();
434 }
435 
on_menu_hide()436 void BandCtl::on_menu_hide()
437 {
438   m_TypeBtn.focus = false;
439   m_TypeBtn.pressed = false;
440   redraw();
441 }
442 
443 //TODO: En ardour4 event de tecla mai arriba
on_button_press_event(GdkEventButton * event)444 bool BandCtl::on_button_press_event(GdkEventButton* event)
445 {
446   //Notify band over
447   m_bandSelectedSignal.emit(m_iBandNum);
448 
449   //Check if is a double click or simple
450   if(event->button == 1)
451   {
452     if(event->type == GDK_2BUTTON_PRESS)
453     {
454       //Double click on the 1st button
455       m_GainBtn.text = (m_HpfLpf_slope == 0) & m_bBandIsEnabled & (event->x > m_GainBtn.x0 && event->x < m_GainBtn.x1 && event->y > m_GainBtn.y0 && event->y < m_GainBtn.y1);
456       m_FreqBtn.text = m_bBandIsEnabled & (event->x > m_FreqBtn.x0 && event->x < m_FreqBtn.x1 && event->y > m_FreqBtn.y0 && event->y < m_FreqBtn.y1);
457       m_QBtn.text = m_bBandIsEnabled & (event->x > m_QBtn.x0 && event->x < m_QBtn.x1 && event->y > m_QBtn.y0 && event->y < m_QBtn.y1);
458       if(m_GainBtn.text)
459       {
460         m_GainBtn.ss.str(""); //Clear stringstream
461         m_GainBtn.ss<<std::setprecision(2)<< std::fixed << m_GainBtn.value;
462 	grab_focus();
463         //keyPressEvent = signal_key_press_event().connect(sigc::mem_fun(*this, &BandCtl::on_key_press_event)); //TODO
464       }
465       else if(m_FreqBtn.text)
466       {
467         m_FreqBtn.ss.str(""); //Clear stringstream
468         m_FreqBtn.ss<<std::setprecision(2)<< std::fixed <<m_FreqBtn.value;
469         grab_focus();
470         //keyPressEvent = signal_key_press_event().connect(sigc::mem_fun(*this, &BandCtl::on_key_press_event)); //TODO
471       }
472       else if(m_QBtn.text)
473       {
474         m_QBtn.ss.str(""); //Clear stringstream
475         m_QBtn.ss<<std::setprecision(2)<< std::fixed <<m_QBtn.value;
476         grab_focus();
477         //keyPressEvent = signal_key_press_event().connect(sigc::mem_fun(*this, &BandCtl::on_key_press_event)); //TODO
478       }
479 
480     }
481     else
482     {
483       m_EnableBtn.pressed = (event->x > m_EnableBtn.x0 && event->x < m_EnableBtn.x1 && event->y > m_EnableBtn.y0 && event->y < m_EnableBtn.y1);
484 
485       //Simple click on the 1st button
486       m_TypeBtn.pressed = m_bBandIsEnabled & (event->x > m_TypeBtn.x0 && event->x < m_TypeBtn.x1 && event->y > m_TypeBtn.y0 && event->y < m_TypeBtn.y1);
487       if(m_TypeBtn.pressed)
488       {
489         m_TypePopUp->popup(event->button, event->time);
490         m_TypePopUp->show_all();
491       }
492 
493       m_iAntValueX = event->x;
494       m_iAntValueY = event->y;
495       m_GainBtn.pressed = m_bBandIsEnabled & (event->x > m_GainBtn.x0 && event->x < m_GainBtn.x1 && event->y > m_GainBtn.y0 && event->y < m_GainBtn.y1);
496       m_FreqBtn.pressed = m_bBandIsEnabled & (event->x > m_FreqBtn.x0 && event->x < m_FreqBtn.x1 && event->y > m_FreqBtn.y0 && event->y < m_FreqBtn.y1);
497       m_QBtn.pressed = m_bBandIsEnabled & (event->x > m_QBtn.x0 && event->x < m_QBtn.x1 && event->y > m_QBtn.y0 && event->y < m_QBtn.y1);
498 
499       if(m_bIsStereoPlugin)
500       {
501         m_MidSideBtn.ML_pressed = m_bBandIsEnabled & (event->x > m_MidSideBtn.Mx && event->x < m_MidSideBtn.Dx && event->y > m_MidSideBtn.y0 && event->y < m_MidSideBtn.y1);
502         m_MidSideBtn.Dual_pressed = m_bBandIsEnabled & (event->x > m_MidSideBtn.Dx && event->x < m_MidSideBtn.Sx && event->y > m_MidSideBtn.y0 && event->y < m_MidSideBtn.y1);
503         m_MidSideBtn.SR_pressed = m_bBandIsEnabled & (event->x > m_MidSideBtn.Sx && event->x < m_MidSideBtn.x1 && event->y > m_MidSideBtn.y0 && event->y < m_MidSideBtn.y1);
504         redraw_MidSide_widget();
505       }
506 
507       //Disable Q for LPF1 and LPF2
508       m_QBtn.pressed &= !(m_FilterType == LPF_ORDER_1);
509       m_QBtn.pressed &= !(m_FilterType == HPF_ORDER_1);
510 
511       //Disable Gain for NOTCH
512       m_GainBtn.pressed &= !(m_FilterType == NOTCH);
513     }
514   }
515   redraw();
516   return true;
517 }
518 
on_button_release_event(GdkEventButton * event)519 bool BandCtl::on_button_release_event(GdkEventButton* event)
520 {
521   //Check for enable button
522   if(m_EnableBtn.pressed && (event->x > m_EnableBtn.x0 && event->x < m_EnableBtn.x1 && event->y > m_EnableBtn.y0 && event->y < m_EnableBtn.y1))
523   {
524     m_bBandIsEnabled = !m_bBandIsEnabled;
525     m_bandChangedSignal.emit(m_iBandNum, ONOFF_TYPE, m_bBandIsEnabled);
526   }
527 
528   //Check MidSide buttons
529   if(m_bIsStereoPlugin && m_MidSideBtn.ML_pressed && (event->x > m_MidSideBtn.Mx && event->x < m_MidSideBtn.Dx && event->y > m_MidSideBtn.y0 && event->y < m_MidSideBtn.y1))
530   {
531     m_MidSideBtn.State = ML;
532     m_midsideChangedSignal.emit(m_iBandNum);
533   }
534   if(m_bIsStereoPlugin && m_MidSideBtn.Dual_pressed && (event->x > m_MidSideBtn.Dx && event->x < m_MidSideBtn.Sx && event->y > m_MidSideBtn.y0 && event->y < m_MidSideBtn.y1))
535   {
536     m_MidSideBtn.State = DUAL;
537     m_midsideChangedSignal.emit(m_iBandNum);
538   }
539   if(m_bIsStereoPlugin && m_MidSideBtn.SR_pressed &&  (event->x > m_MidSideBtn.Sx && event->x < m_MidSideBtn.x1 && event->y > m_MidSideBtn.y0 && event->y < m_MidSideBtn.y1))
540   {
541     m_MidSideBtn.State = SR;
542     m_midsideChangedSignal.emit(m_iBandNum);
543   }
544 
545   m_EnableBtn.pressed = false;
546   m_TypeBtn.pressed = false;
547   m_GainBtn.pressed = false;
548   m_FreqBtn.pressed = false;
549   m_QBtn.pressed    = false;
550 
551   if(m_bIsStereoPlugin)
552   {
553     m_MidSideBtn.Dual_pressed = false;
554     m_MidSideBtn.ML_pressed = false;
555     m_MidSideBtn.SR_pressed = false;
556     redraw_MidSide_widget();
557   }
558   //m_iAntValueX = m_iAntValueY = 0;
559 
560   //Inform bode plot
561   m_bandUnSelectedSignal.emit();
562 
563   redraw();
564   return true;
565 }
566 
on_mouse_motion_event(GdkEventMotion * event)567 bool BandCtl::on_mouse_motion_event(GdkEventMotion* event)
568 {
569   //If some gain, freq, q button is pressed compute new values
570   if(m_GainBtn.pressed)
571   {
572     if(m_HpfLpf_slope)
573     {
574       //HPF and LPF case
575       m_HpfLpf_slope += -1*(event->y - m_iAntValueY);
576       m_HpfLpf_slope = m_HpfLpf_slope < 20 ? 20 : m_HpfLpf_slope;
577       m_HpfLpf_slope = m_HpfLpf_slope > 80 ? 80: m_HpfLpf_slope;
578       setFilterTypeLPFHPFAcordSlope();
579     }
580     else
581     {
582       //Gain type
583       m_GainBtn.value += (float)(event->y - m_iAntValueY)/-ACCELERATION;
584       m_GainBtn.value = m_GainBtn.value > GAIN_MAX ? GAIN_MAX : m_GainBtn.value;
585       m_GainBtn.value = m_GainBtn.value < GAIN_MIN ? GAIN_MIN : m_GainBtn.value;
586       m_bandChangedSignal.emit(m_iBandNum, GAIN_TYPE, m_GainBtn.value);
587     }
588   }
589 
590   else if(m_FreqBtn.pressed)
591   {
592     m_FreqBtn.value  += (m_FreqBtn.value/7.0f)*((float)(event->x-m_iAntValueX)/ACCELERATION);
593     m_FreqBtn.value = m_FreqBtn.value > FREQ_MAX ? FREQ_MAX : m_FreqBtn.value;
594     m_FreqBtn.value = m_FreqBtn.value < FREQ_MIN ? FREQ_MIN : m_FreqBtn.value;
595     m_bandChangedSignal.emit(m_iBandNum, FREQ_TYPE, m_FreqBtn.value);
596   }
597 
598   else if(m_QBtn.pressed)
599   {
600     m_QBtn.value += (float)(event->x - m_iAntValueX)/(-ACCELERATION * 5.0);
601     m_QBtn.value = m_QBtn.value > PEAK_Q_MAX ? PEAK_Q_MAX : m_QBtn.value;
602     m_QBtn.value = m_QBtn.value < PEAK_Q_MIN ? PEAK_Q_MIN : m_QBtn.value;
603     m_bandChangedSignal.emit(m_iBandNum, Q_TYPE, m_QBtn.value);
604   }
605 
606   else
607   {
608     //Check if mouse over some button
609     m_EnableBtn.focus = (event->x > m_EnableBtn.x0 && event->x < m_EnableBtn.x1 && event->y > m_EnableBtn.y0 && event->y < m_EnableBtn.y1);
610     m_TypeBtn.focus   = (event->x > m_TypeBtn.x0 && event->x < m_TypeBtn.x1 && event->y > m_TypeBtn.y0 && event->y < m_TypeBtn.y1);
611     m_GainBtn.focus   = m_bBandIsEnabled & (event->x > m_GainBtn.x0 && event->x < m_GainBtn.x1 && event->y > m_GainBtn.y0 && event->y < m_GainBtn.y1);
612     m_FreqBtn.focus   = m_bBandIsEnabled & (event->x > m_FreqBtn.x0 && event->x < m_FreqBtn.x1 && event->y > m_FreqBtn.y0 && event->y < m_FreqBtn.y1);
613     m_QBtn.focus      = m_bBandIsEnabled & (event->x > m_QBtn.x0 && event->x < m_QBtn.x1 && event->y > m_QBtn.y0 && event->y < m_QBtn.y1);
614 
615     if(m_bIsStereoPlugin)
616     {
617       m_MidSideBtn.Dual_focus = m_bBandIsEnabled & (event->x > m_MidSideBtn.Dx && event->x < m_MidSideBtn.Sx && event->y > m_MidSideBtn.y0 && event->y < m_MidSideBtn.y1);
618       m_MidSideBtn.ML_focus = m_bBandIsEnabled & (event->x > m_MidSideBtn.Mx && event->x < m_MidSideBtn.Dx && event->y > m_MidSideBtn.y0 && event->y < m_MidSideBtn.y1);
619       m_MidSideBtn.SR_focus = m_bBandIsEnabled & (event->x > m_MidSideBtn.Sx && event->x < m_MidSideBtn.x1 && event->y > m_MidSideBtn.y0 && event->y < m_MidSideBtn.y1);
620       redraw_MidSide_widget();
621     }
622 
623     //Disable Q for LPF1 and LPF2
624     m_QBtn.focus &= !(m_FilterType == LPF_ORDER_1);
625     m_QBtn.focus &= !(m_FilterType == HPF_ORDER_1);
626 
627     //Disable Gain for NOTCH
628     m_GainBtn.focus &= !(m_FilterType == NOTCH);
629   }
630 
631   //Update ant values
632   m_iAntValueX = event->x;
633   m_iAntValueY = event->y;
634 
635   //Notify band over
636   if(m_GainBtn.focus || m_FreqBtn.focus || m_QBtn.focus || m_TypeBtn.focus || m_EnableBtn.focus || m_MidSideBtn.Dual_focus || m_MidSideBtn.ML_focus || m_MidSideBtn.SR_focus)
637   {
638     m_bandSelectedSignal.emit(m_iBandNum);
639   }
640   redraw();
641   return true;
642 }
643 
on_scrollwheel_event(GdkEventScroll * event)644 bool BandCtl::on_scrollwheel_event(GdkEventScroll* event)
645 {
646   double  increment = 0.0;
647 
648   if (event->direction == GDK_SCROLL_UP)
649   {
650     // up code
651     increment = 1.0;
652 
653   }
654   else if (event->direction == GDK_SCROLL_DOWN)
655   {
656     // down code
657     increment = -1.0;
658   }
659 
660   if ( m_bBandIsEnabled & (event->x > m_GainBtn.x0 && event->x < m_GainBtn.x1 && event->y > m_GainBtn.y0 && event->y < m_GainBtn.y1))
661   {
662     if(m_HpfLpf_slope)
663     {
664       //HPF and LPF case
665       increment *= 20.0;
666       m_HpfLpf_slope += increment;
667       m_HpfLpf_slope = m_HpfLpf_slope < 20 ? 20 : m_HpfLpf_slope;
668       m_HpfLpf_slope = m_HpfLpf_slope > 80 ? 80: m_HpfLpf_slope;
669       setFilterTypeLPFHPFAcordSlope();
670     }
671     else
672     {
673       //Gain type
674       increment *=  SCROLL_EVENT_PERCENT*(GAIN_MAX - GAIN_MIN);
675       m_GainBtn.value += increment;
676       m_GainBtn.value = m_GainBtn.value > GAIN_MAX ? GAIN_MAX : m_GainBtn.value;
677       m_GainBtn.value = m_GainBtn.value < GAIN_MIN ? GAIN_MIN : m_GainBtn.value;
678       m_bandChangedSignal.emit(m_iBandNum, GAIN_TYPE, m_GainBtn.value);
679     }
680   }
681   else if( m_bBandIsEnabled & (event->x > m_FreqBtn.x0 && event->x < m_FreqBtn.x1 && event->y > m_FreqBtn.y0 && event->y < m_FreqBtn.y1))
682   {
683     increment *=  SCROLL_EVENT_PERCENT*(FREQ_MAX - FREQ_MIN)*0.0001*m_FreqBtn.value;
684     m_FreqBtn.value += increment;
685     m_FreqBtn.value = m_FreqBtn.value > FREQ_MAX ? FREQ_MAX : m_FreqBtn.value;
686     m_FreqBtn.value = m_FreqBtn.value < FREQ_MIN ? FREQ_MIN : m_FreqBtn.value;
687     m_bandChangedSignal.emit(m_iBandNum, FREQ_TYPE, m_FreqBtn.value);
688   }
689   else if( m_bBandIsEnabled & (event->x > m_QBtn.x0 && event->x < m_QBtn.x1 && event->y > m_QBtn.y0 && event->y < m_QBtn.y1))
690   {
691     increment *=  SCROLL_EVENT_PERCENT*(PEAK_Q_MAX - PEAK_Q_MIN);
692     m_QBtn.value += increment;
693     m_QBtn.value = m_QBtn.value > PEAK_Q_MAX ? PEAK_Q_MAX : m_QBtn.value;
694     m_QBtn.value = m_QBtn.value < PEAK_Q_MIN ? PEAK_Q_MIN : m_QBtn.value;
695     m_bandChangedSignal.emit(m_iBandNum, Q_TYPE, m_QBtn.value);
696   }
697 
698   redraw();
699   return true;
700 }
701 
on_key_press_event(GdkEventKey * event)702 bool BandCtl::on_key_press_event(GdkEventKey* event)
703 {
704 
705   std::cout<<"BandCtl::on_key_press_event()"<<" event = "<<event->keyval<<std::endl; //TODO reomve
706 
707   switch(event->keyval)
708   {
709     case GDK_KEY_Return:
710     case GDK_KEY_KP_Enter:
711       //Parse the string to get new value
712       if(m_GainBtn.text)
713       {
714         if(parseBtnString(&m_GainBtn))
715         {
716           m_bandChangedSignal.emit(m_iBandNum, GAIN_TYPE, m_GainBtn.value);
717         }
718       }
719       else if(m_FreqBtn.text)
720       {
721         if(parseBtnString(&m_FreqBtn))
722         {
723           m_bandChangedSignal.emit(m_iBandNum, FREQ_TYPE, m_FreqBtn.value);
724         }
725       }
726       else if(m_QBtn.text)
727       {
728         if(parseBtnString(&m_QBtn))
729         {
730           m_bandChangedSignal.emit(m_iBandNum, Q_TYPE, m_QBtn.value);
731         }
732       }
733       break;
734 
735     case GDK_KEY_Escape:
736        m_GainBtn.text = false;
737        m_FreqBtn.text = false;
738        m_QBtn.text = false;
739        //keyPressEvent.disconnect(); //TODO
740       break;
741 
742     case GDK_KEY_BackSpace:
743       if(m_GainBtn.text)
744       {
745         if(m_GainBtn.ss.str().length() > 0)
746         {
747           std::string aux = m_GainBtn.ss.str().erase(m_GainBtn.ss.str().length() - 1);
748           m_GainBtn.ss.str("");
749           m_GainBtn.ss<<aux;
750         }
751       }
752       else if(m_FreqBtn.text)
753       {
754         if(m_FreqBtn.ss.str().length() > 0)
755         {
756           std::string aux = m_FreqBtn.ss.str().erase(m_FreqBtn.ss.str().length() - 1);
757           m_FreqBtn.ss.str("");
758           m_FreqBtn.ss<<aux;
759         }
760       }
761       else if(m_QBtn.text)
762       {
763         if(m_QBtn.ss.str().length() > 0)
764         {
765           std::string aux = m_QBtn.ss.str().erase(m_QBtn.ss.str().length() - 1);
766           m_QBtn.ss.str("");
767           m_QBtn.ss<<aux;
768         }
769       }
770       break;
771 
772     case GDK_KEY_KP_0: case GDK_KEY_0:
773     case GDK_KEY_KP_1: case GDK_KEY_1:
774     case GDK_KEY_KP_2: case GDK_KEY_2:
775     case GDK_KEY_KP_3: case GDK_KEY_3:
776     case GDK_KEY_KP_4: case GDK_KEY_4:
777     case GDK_KEY_KP_5: case GDK_KEY_5:
778     case GDK_KEY_KP_6: case GDK_KEY_6:
779     case GDK_KEY_KP_7: case GDK_KEY_7:
780     case GDK_KEY_KP_8: case GDK_KEY_8:
781     case GDK_KEY_KP_9: case GDK_KEY_9:
782     case GDK_KEY_KP_Subtract: case GDK_KEY_minus:
783       if(m_GainBtn.text)
784       {
785         m_GainBtn.ss << event->string;
786       }
787       else if(m_FreqBtn.text)
788       {
789         m_FreqBtn.ss << event->string;
790       }
791       else if(m_QBtn.text)
792       {
793         m_QBtn.ss << event->string;
794       }
795       break;
796 
797     case GDK_KEY_K: case GDK_KEY_k:
798       if(m_GainBtn.text)
799       {
800         m_GainBtn.ss << "k";
801       }
802       else if(m_FreqBtn.text)
803       {
804         m_FreqBtn.ss << "k";
805       }
806       else if(m_QBtn.text)
807       {
808         m_QBtn.ss << "k";
809       }
810       break;
811 
812     case GDK_KEY_comma: case GDK_KEY_decimalpoint: case GDK_KEY_KP_Decimal: case GDK_KEY_period:
813       if(m_GainBtn.text)
814       {
815         m_GainBtn.ss << ".";
816       }
817       else if(m_FreqBtn.text)
818       {
819         m_FreqBtn.ss << ".";
820       }
821       else if(m_QBtn.text)
822       {
823         m_QBtn.ss << ".";
824       }
825       break;
826   }
827 
828   redraw();
829   return true;
830 }
831 
832 
833 //TODO no estic segur de necessitar aquest senyal per a res.
on_focus_out_event(GdkEventFocus * event)834 bool BandCtl::on_focus_out_event(GdkEventFocus* event)
835 {
836   std::cout <<"on_focus_out_event"<<std::endl; //TODO Remove
837   m_GainBtn.text = false;
838   m_FreqBtn.text = false;
839   m_QBtn.text = false;
840   //keyPressEvent.disconnect(); //TODO
841   redraw();
842   return true;
843 }
844 
setFilterTypeLPFHPFAcordSlope()845 void BandCtl::setFilterTypeLPFHPFAcordSlope()
846 {
847   if(m_HpfLpf_slope < 40)
848   {
849     if(m_FilterType == LPF_ORDER_1 || m_FilterType == LPF_ORDER_2 || m_FilterType == LPF_ORDER_3 || m_FilterType == LPF_ORDER_4)
850     {
851       m_FilterType = LPF_ORDER_1;
852     }
853     else
854     {
855       m_FilterType = HPF_ORDER_1;
856     }
857   }
858   else if(m_HpfLpf_slope < 60)
859   {
860     if(m_FilterType == LPF_ORDER_1 || m_FilterType == LPF_ORDER_2 || m_FilterType == LPF_ORDER_3 || m_FilterType == LPF_ORDER_4)
861     {
862       m_FilterType = LPF_ORDER_2;
863     }
864     else
865     {
866       m_FilterType = HPF_ORDER_2;
867     }
868   }
869   else if(m_HpfLpf_slope < 80)
870   {
871     if(m_FilterType == LPF_ORDER_1 || m_FilterType == LPF_ORDER_2 || m_FilterType == LPF_ORDER_3 || m_FilterType == LPF_ORDER_4)
872     {
873       m_FilterType = LPF_ORDER_3;
874     }
875     else
876     {
877       m_FilterType = HPF_ORDER_3;
878     }
879   }
880   else
881   {
882     if(m_FilterType == LPF_ORDER_1 || m_FilterType == LPF_ORDER_2 || m_FilterType == LPF_ORDER_3 || m_FilterType == LPF_ORDER_4)
883     {
884       m_FilterType = LPF_ORDER_4;
885     }
886     else
887     {
888       m_FilterType = HPF_ORDER_4;
889     }
890   }
891   m_bandChangedSignal.emit(m_iBandNum, FILTER_TYPE, getFilterType());
892   m_bandChangedSignal.emit(m_iBandNum, GAIN_TYPE, m_GainBtn.value);
893   m_bandChangedSignal.emit(m_iBandNum, FREQ_TYPE, m_FreqBtn.value);
894   m_bandChangedSignal.emit(m_iBandNum, Q_TYPE, m_QBtn.value);
895 }
896 
parseBtnString(BandCtl::Button * btn)897 bool BandCtl::parseBtnString(BandCtl::Button* btn)
898 {
899   std::string str = btn->ss.str();
900   std::string str_k = "";
901   std::string str_d = "";
902 
903   unsigned int pos_d = str.find('.');
904   unsigned int pos_k = str.find('k');
905 
906   if(pos_k > pos_d && pos_k < str.length() && pos_d < str.length() )
907   {
908     //Found both, k and decimal but in inverse order, rise an error
909     btn->text = false;
910     //keyPressEvent.disconnect(); //TODO
911     return false;
912   }
913 
914   if(pos_d >= str.length())
915   {
916     if(pos_k >= str.length())
917     {
918       //Nor k neither d found so, use the whole string
919       str = str; //Do nothing!
920     }
921     else
922     {
923       //No d is found but k is found
924       str_k = str.substr(0, pos_k);
925       str = str.substr(pos_k + 1, str.length() - pos_k);
926     }
927   }
928   else
929   {
930     if(pos_k >= str.length())
931     {
932       //No k but d is found
933       str_d = str.substr(pos_d + 1, str.length() - pos_d - 1);
934       str = str.substr(0, pos_d);
935     }
936     else
937     {
938       //Both k and d are found
939       str_k = str.substr(0, pos_k);
940       str_d = str.substr(pos_d + 1, str.length() - pos_d - 1);
941       str = str.substr(pos_k + 1, pos_d - pos_k - 1);
942     }
943   }
944 
945   double val_k = 0.0;
946   double val_d = 0.0;
947   double val = atof(str.c_str());
948 
949   if(str_k.length() > 0)
950   {
951     val_k = atof(str_k.c_str()) * 1e3;
952     val *= pow(10,3.0 - str.length());
953     if(str.length() > 3)
954     {
955       //throw an error, imposible to match str > 3 with k
956       btn->text = false;
957       //keyPressEvent.disconnect(); //TODO
958       return false;
959     }
960   }
961   if(str_d.length() > 0)
962   {
963     val_d = atof(str_d.c_str())/ pow(10,(double)str_d.length());
964   }
965 
966   btn->value = val + val_k + val_d;
967 
968   //clip value to the widget limits!
969   btn->value = btn->value > btn->max ? btn->max : btn->value;
970   btn->value = btn->value < btn->min ? btn->min : btn->value;
971   btn->text = false;
972   //keyPressEvent.disconnect(); //TODO
973   return true;
974 }
975 
976 
on_mouse_leave_widget(GdkEventCrossing * event)977 bool BandCtl::on_mouse_leave_widget(GdkEventCrossing* event)
978 {
979   m_EnableBtn.focus = false;
980   m_TypeBtn.focus = false;
981   m_GainBtn.focus = m_GainBtn.pressed; //Lost focus only if is no pressed
982   m_FreqBtn.focus = m_FreqBtn.pressed; //Lost focus only if is no pressed
983   m_QBtn.focus = m_QBtn.pressed; //Lost focus only if is no pressed
984   //keyPressEvent.disconnect(); //TODO
985   if(m_bIsStereoPlugin)
986   {
987     m_MidSideBtn.Dual_focus = false;
988     m_MidSideBtn.ML_focus = false;
989     m_MidSideBtn.SR_focus = false;
990     redraw_MidSide_widget();
991   }
992   redraw();
993   m_bandUnSelectedSignal.emit();
994   return true;
995 }
996 
redraw()997 void BandCtl::redraw()
998 {
999   Glib::RefPtr<Gdk::Window> win = get_window();
1000   if(win)
1001   {
1002     Gdk::Rectangle r(0, 0, get_allocation().get_width(), get_allocation().get_height());
1003     win->invalidate_rect(r, false);
1004   }
1005 }
1006 
on_expose_event(GdkEventExpose * event)1007 bool BandCtl::on_expose_event(GdkEventExpose* event)
1008 {
1009  Glib::RefPtr<Gdk::Window> window = get_window();
1010   if(window)
1011   {
1012     Gtk::Allocation allocation = get_allocation();
1013     width = allocation.get_width();
1014     height = allocation.get_height();
1015 
1016     if(!m_midSide_surface_ptr && m_bIsStereoPlugin)
1017     {
1018       //The Mid Side button surface
1019       m_midSide_surface_ptr = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, width, (height - 4.0*OUTER_BORDER)/4.0);
1020     }
1021 
1022     if(!m_bBtnInitialized)
1023     {
1024       m_EnableBtn.focus = false;
1025       m_EnableBtn.pressed = false;
1026       m_EnableBtn.x0 = OUTER_BORDER + 5;
1027       m_EnableBtn.x1 = width - OUTER_BORDER - m_image_surface_ptr->get_width() - 2;
1028       m_EnableBtn.y0 = OUTER_BORDER + 2;
1029       m_EnableBtn.y1 = OUTER_BORDER + m_image_surface_ptr->get_height() - 1;
1030       m_EnableBtn.text = false;
1031 
1032       m_TypeBtn.focus = false;
1033       m_TypeBtn.pressed = false;
1034       m_TypeBtn.x0 = width - OUTER_BORDER - m_image_surface_ptr->get_width();
1035       m_TypeBtn.x1 = width - OUTER_BORDER;
1036       m_TypeBtn.y0 = OUTER_BORDER + 1;
1037       m_TypeBtn.y1 = OUTER_BORDER + m_image_surface_ptr->get_height();
1038       m_TypeBtn.text = false;
1039 
1040       m_GainBtn.focus = false;
1041       m_GainBtn.pressed = false;
1042       m_GainBtn.x0 = OUTER_BORDER + 1;
1043       m_GainBtn.x1 = width - OUTER_BORDER;
1044       m_GainBtn.y0 = m_EnableBtn.y1 + 1;
1045       m_GainBtn.y1 = m_EnableBtn.y1 + (height - 4.0*OUTER_BORDER - m_EnableBtn.y1)/ ( m_bIsStereoPlugin ? 4.0 : 3.0);
1046       m_GainBtn.text = false;
1047       m_GainBtn.min = GAIN_MIN;
1048       m_GainBtn.max = GAIN_MAX;
1049 
1050       m_FreqBtn.focus = false;
1051       m_FreqBtn.pressed = false;
1052       m_FreqBtn.x0 = OUTER_BORDER + 1;
1053       m_FreqBtn.x1 = width - OUTER_BORDER;
1054       m_FreqBtn.y0 = m_GainBtn.y1 + 1;
1055       m_FreqBtn.y1 = m_EnableBtn.y1 +  2.0*(height - 4.0*OUTER_BORDER - m_EnableBtn.y1)/ (m_bIsStereoPlugin ? 4.0 : 3.0);
1056       m_FreqBtn.text = false;
1057       m_FreqBtn.min = FREQ_MIN;
1058       m_FreqBtn.max = FREQ_MAX;
1059 
1060       m_QBtn.focus = false;
1061       m_QBtn.pressed = false;
1062       m_QBtn.x0 = OUTER_BORDER + 1;
1063       m_QBtn.x1 = width - OUTER_BORDER;
1064       m_QBtn.y0 = m_FreqBtn.y1 + 1;
1065       m_QBtn.y1 =  m_EnableBtn.y1 +  3.0*(height - 4.0*OUTER_BORDER - m_EnableBtn.y1)/ (m_bIsStereoPlugin ? 4.0 : 3.0);
1066       m_QBtn.text = false;
1067       m_QBtn.min = PEAK_Q_MIN;
1068       m_QBtn.max = PEAK_Q_MAX;
1069 
1070       if(m_bIsStereoPlugin)
1071       {
1072         m_MidSideBtn.Dual_focus = false;
1073         m_MidSideBtn.ML_focus = false;
1074         m_MidSideBtn.SR_focus = false;
1075         m_MidSideBtn.Dual_pressed = false;
1076         m_MidSideBtn.ML_pressed = false;
1077         m_MidSideBtn.SR_pressed = false;
1078         m_MidSideBtn.x0 = 4.0*OUTER_BORDER;
1079         m_MidSideBtn.x1 =  width - 4.0*OUTER_BORDER;
1080         m_MidSideBtn.y0 = round(m_QBtn.y1 + 2.0);
1081         m_MidSideBtn.y1 =  height - 2.0*OUTER_BORDER;
1082         m_MidSideBtn.Mx = m_MidSideBtn.x0;
1083         m_MidSideBtn.Dx = (m_MidSideBtn.x1 - m_MidSideBtn.x0)/3.0 + m_MidSideBtn.Mx;
1084         m_MidSideBtn.Sx = (m_MidSideBtn.x1 - m_MidSideBtn.x0)/3.0 + m_MidSideBtn.Dx;
1085         redraw_MidSide_widget();
1086       }
1087 
1088       m_bBtnInitialized = true;
1089     }
1090 
1091     Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
1092     int radius =  (int)round(((double)height) / 20.0);
1093     double degrees = M_PI / 180.0;
1094 
1095 
1096     //Paint backgroud
1097     cr->save();
1098     cr->set_source_rgb(BACKGROUND_R, BACKGROUND_G, BACKGROUND_B);
1099     cr->paint(); //Fill all with background color
1100     cr->restore();
1101 
1102     //Draw background box
1103     cr->save();
1104     cr->begin_new_sub_path();
1105     cr->arc ( OUTER_BORDER + radius, OUTER_BORDER + radius, radius, 180 * degrees, 270 * degrees);
1106     cr->arc (width - OUTER_BORDER - radius, OUTER_BORDER + radius, radius, -90 * degrees, 0 * degrees);
1107     cr->line_to(width - OUTER_BORDER, height - OUTER_BORDER);
1108     cr->line_to(OUTER_BORDER, height - OUTER_BORDER);
1109     cr->close_path();
1110 
1111     cr->set_line_width(1);
1112     if(m_bBandIsEnabled)
1113     {
1114       cr->set_source_rgba(m_Color.get_red_p(), m_Color.get_green_p(), m_Color.get_blue_p(), 0.5);
1115     }
1116     else
1117     {
1118       cr->set_source_rgba(0.3,0.3,0.3,0.6);
1119     }
1120     cr->stroke_preserve();
1121 
1122     if(m_bGlowBand)
1123     {
1124       cr->set_line_width(2.5);
1125       cr->set_source_rgba(0.0,1.0,1.0,0.5);
1126       cr->stroke_preserve();
1127     }
1128 
1129     Cairo::RefPtr<Cairo::LinearGradient> bkg_gradient_ptr = Cairo::LinearGradient::create(width/2, OUTER_BORDER, width/2, height - OUTER_BORDER);
1130     if(m_bBandIsEnabled)
1131     {
1132       bkg_gradient_ptr->add_color_stop_rgba (0.0, m_Color.get_red_p(), m_Color.get_green_p(), m_Color.get_blue_p(), 0.6 );
1133       bkg_gradient_ptr->add_color_stop_rgba (1.0, m_Color.get_red_p(), m_Color.get_green_p(), m_Color.get_blue_p(), 0.3 );
1134     }
1135     else
1136     {
1137       bkg_gradient_ptr->add_color_stop_rgba (0.0, 0.8, 0.8, 0.8, 0.4 );
1138       bkg_gradient_ptr->add_color_stop_rgba (1.0, 0.8, 0.8, 0.8, 0.2 );
1139     }
1140     bkg_gradient_ptr->add_color_stop_rgba (0.3, m_Color.get_red_p(), m_Color.get_green_p(), m_Color.get_blue_p(), 0.1 );
1141     bkg_gradient_ptr->add_color_stop_rgba (0.5, m_Color.get_red_p(), m_Color.get_green_p(), m_Color.get_blue_p(), 0.0 );
1142     bkg_gradient_ptr->add_color_stop_rgba (0.9, m_Color.get_red_p(), m_Color.get_green_p(), m_Color.get_blue_p(), 0.05 );
1143 
1144     cr->set_source(bkg_gradient_ptr);
1145     cr->fill();
1146     cr->restore();
1147 
1148     //Draw Enable LED
1149     cr->save();
1150     cr->translate(m_EnableBtn.x0 - 0.5, m_EnableBtn.y0 + 1.5);
1151     ToggleButton::drawLedBtn(cr, m_EnableBtn.focus, m_bBandIsEnabled, "On", 0, 3);
1152     cr->restore();
1153 
1154     //Draw Gan, Freq, Q Buttons
1155     drawBandButton(&m_GainBtn, cr);
1156     drawBandButton(&m_FreqBtn, cr);
1157     drawBandButton(&m_QBtn, cr);
1158 
1159     //Draw mid Side surface
1160     if(m_midSide_surface_ptr && m_bIsStereoPlugin)
1161     {
1162       cr->save();
1163       cr->set_source(m_midSide_surface_ptr, 0, m_MidSideBtn.y0);
1164       cr->paint();
1165       cr->restore();
1166     }
1167 
1168     //Draw ComboBox Filter Type icon
1169     cr->save();
1170     cr->set_source (m_image_surface_ptr, m_TypeBtn.x0 - 0.5, m_TypeBtn.y0 - 0.5);
1171     cr->rectangle (m_TypeBtn.x0 - 0.5, m_TypeBtn.y0 - 0.5, m_image_surface_ptr->get_width(), m_image_surface_ptr->get_height());
1172     cr->clip();
1173     cr->paint();
1174     cr->restore();
1175 
1176     //Draw FilterType Focus ComboBox
1177     if(m_bBandIsEnabled)
1178     {
1179       cr->save();
1180       cr->begin_new_sub_path();
1181       cr->arc (m_TypeBtn.x1 - radius - 1 - 0.5, m_TypeBtn.y0 + radius + 0.5, radius, -90 * degrees, 0 * degrees);
1182       cr->arc (m_TypeBtn.x1- radius -1 - 0.5, m_TypeBtn.y1 - radius - 0.5, radius, 0 * degrees, 90 * degrees);
1183       cr->arc (m_TypeBtn.x0 + radius + 0.5, m_TypeBtn.y1 - radius - 0.5, radius, 90 * degrees, 180 * degrees);
1184       cr->arc (m_TypeBtn.x0 + radius + 0.5, m_TypeBtn.y0 + radius + 0.5, radius, 180 * degrees, 270 * degrees);
1185       cr->close_path();
1186 
1187       cr->set_source_rgba(0.2, 0.2, 0.2, 0.9);
1188       cr->set_line_width(1);
1189       cr->stroke_preserve();
1190 
1191       if(m_TypeBtn.focus)
1192       {
1193         cr->set_source_rgba(0.0, 1.0, 1.0, 0.7);
1194         cr->set_line_width(2);
1195         cr->stroke();
1196       }
1197       cr->restore();
1198     }
1199 
1200   }
1201   return true;
1202 }
1203 
drawBandButton(BandCtl::Button * btn,Cairo::RefPtr<Cairo::Context> cr)1204 void BandCtl::drawBandButton(BandCtl::Button* btn, Cairo::RefPtr<Cairo::Context> cr)
1205 {
1206   //Avoid the drawig of button if it is notch filter gain button or LPF1/HPF1 Q button
1207   if(btn->units == "dB" && m_FilterType == NOTCH)
1208   {
1209     return;
1210   }
1211   if(btn->units == "Q" && ( m_FilterType == LPF_ORDER_1 || m_FilterType == HPF_ORDER_1 ))
1212   {
1213     return;
1214   }
1215 
1216   std::stringstream ss;
1217   ss<<"sans "<< FONT_SIZE << "px";
1218   Glib::RefPtr<Pango::Layout> pangoLayout = Pango::Layout::create(cr);
1219   Pango::FontDescription font_desc(ss.str());
1220   pangoLayout->set_font_description(font_desc);
1221   pangoLayout->set_alignment(Pango::ALIGN_CENTER);
1222   pangoLayout->set_width(Pango::SCALE * (btn->x1 - btn->x0));
1223 
1224   int radius =  (int)round(((double)height) / 20.0);
1225   double degrees = M_PI / 180.0;
1226 
1227   //Draw the button in text entry mode
1228   if(btn->text)
1229   {
1230     cr->save();
1231     cr->begin_new_sub_path();
1232     cr->arc (btn->x1 - radius - 3, btn->y0 + radius + 3, radius, -90 * degrees, 0 * degrees);
1233     cr->arc (btn->x1- radius -3 , btn->y1 - radius -3, radius, 0 * degrees, 90 * degrees);
1234     cr->arc (btn->x0 + radius + 3,btn->y1 - radius -3, radius, 90 * degrees, 180 * degrees);
1235     cr->arc (btn->x0 + radius + 3, btn->y0 + radius +3, radius, 180 * degrees, 270 * degrees);
1236     cr->close_path();
1237     cr->set_line_width(1.0);
1238     cr->set_source_rgba(0.0, 1.0, 1.0, 0.5);
1239     cr->stroke();
1240     cr->restore();
1241 
1242     cr->save();
1243     cr->move_to(btn->x0,  btn->y0 + 0.5*(btn->y1 - btn->y0) - FONT_SIZE/2 - 2);
1244     cr->set_source_rgb(m_Color.get_red_p(), m_Color.get_green_p(), m_Color.get_blue_p());
1245     pangoLayout->set_text(btn->ss.str() + "|");
1246     pangoLayout->show_in_cairo_context(cr);
1247     cr->stroke();
1248     cr->restore();
1249     return;
1250   }
1251 
1252   //Draw Btn Focus
1253   if(btn->focus)
1254   {
1255     Cairo::RefPtr<Cairo::LinearGradient> bkg_gradient_ptr = Cairo::LinearGradient::create(btn->x0 + 0.5*(btn->x1 - btn->x0), btn->y0, btn->x0 + 0.5*(btn->x1 - btn->x0), btn->y1);
1256     bkg_gradient_ptr->add_color_stop_rgba (0.1, m_Color.get_red_p() + 0.2, m_Color.get_green_p() + 0.2, m_Color.get_blue_p() + 0.2, 0.0 );
1257     bkg_gradient_ptr->add_color_stop_rgba (0.45, m_Color.get_red_p() + 0.2, m_Color.get_green_p() + 0.2, m_Color.get_blue_p() + 0.2, 0.3 );
1258     bkg_gradient_ptr->add_color_stop_rgba (0.55, m_Color.get_red_p() + 0.2, m_Color.get_green_p() + 0.2, m_Color.get_blue_p() + 0.2, 0.3 );
1259     bkg_gradient_ptr->add_color_stop_rgba (0.9, m_Color.get_red_p() + 0.2, m_Color.get_green_p() + 0.2, m_Color.get_blue_p() + 0.2, 0.0 );
1260     cr->save();
1261     cr->set_source(bkg_gradient_ptr);
1262     cr->rectangle(btn->x0, btn->y0, btn->x1 - btn->x0, btn->y1 - btn->y0);
1263     cr->fill();
1264     cr->restore();
1265   }
1266 
1267   //Draw Text
1268   cr->save();
1269 
1270   ss.str(""); //Clear stringstream
1271   if(btn->units != "dB/dec")
1272   {
1273     int precision = 1;
1274     if(btn->value < 100 || (btn->value >= 1e3 && btn->value < 1e4)) precision = 2;
1275     ss<< std::setprecision(precision)<< std::fixed <<(btn->value < 1e3 ? btn->value : (0.001*(btn->value))) << (btn->value < 1e3 ? " " : " k") << (btn->units);
1276   }
1277   else
1278   {
1279     int slope = m_HpfLpf_slope;
1280     if(m_HpfLpf_slope < 40) slope = 20;
1281     else if(m_HpfLpf_slope < 60) slope = 40;
1282     else if(m_HpfLpf_slope < 80) slope = 60;
1283     else slope = 80;
1284     ss<< std::setprecision(0)<< std::fixed << slope << " " << (btn->units);
1285   }
1286 
1287   pangoLayout->set_text(ss.str());
1288 
1289   //Shadow
1290   cr->move_to(btn->x0 + 1,  btn->y0 + 0.5*(btn->y1 - btn->y0) - FONT_SIZE/2 - 2 + 1);
1291   cr->set_source_rgba(0,0,0,0.5);
1292   pangoLayout->show_in_cairo_context(cr);
1293   cr->stroke();
1294 
1295   //Text
1296   cr->move_to(btn->x0,  btn->y0 + 0.5*(btn->y1 - btn->y0) - FONT_SIZE/2 - 2);
1297   if(!m_bBandIsEnabled)
1298   {
1299     cr->set_source_rgba(1.0, 1.0, 1.0, 0.4);
1300   }
1301   else if(btn->pressed)
1302   {
1303     cr->set_source_rgba(1.0, 1.0, 1.0, 1.0);
1304   }
1305   else
1306   {
1307     cr->set_source_rgba(1.0, 1.0, 1.0, 0.8);
1308   }
1309   pangoLayout->show_in_cairo_context(cr);
1310   cr->stroke();
1311 
1312 
1313 
1314   cr->restore();
1315 }
1316 
redraw_MidSide_widget()1317 void BandCtl::redraw_MidSide_widget()
1318 {
1319   if(m_midSide_surface_ptr && m_bIsStereoPlugin)
1320   {
1321     //Create cairo context using the buffer surface
1322     Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create(m_midSide_surface_ptr);
1323     const double btnH = round(m_midSide_surface_ptr->get_height() - 6.0*OUTER_BORDER);
1324 
1325     //Clear current context
1326     cr->save();
1327     cr->set_operator(Cairo::OPERATOR_CLEAR);
1328     cr->paint();
1329     cr->restore();
1330 
1331     //Draw Color background on selected button
1332     cr->save();
1333     Cairo::RefPtr<Cairo::LinearGradient> bkg_gradient_ptr = Cairo::LinearGradient::create(0, 0, 0, m_midSide_surface_ptr->get_height());
1334     switch(m_MidSideBtn.State)
1335     {
1336       case DUAL:
1337         cr->rectangle(m_MidSideBtn.Dx, 0, m_MidSideBtn.Sx - m_MidSideBtn.Dx, btnH);
1338         break;
1339 
1340       case ML:
1341         cr->begin_new_sub_path();
1342         cr->arc( m_MidSideBtn.x0 + btnH/2.0, btnH/2.0 + 0.5, btnH/2.0, M_PI/2.0, -M_PI/2.0);
1343         cr->line_to( m_MidSideBtn.Dx,  0);
1344         cr->line_to( m_MidSideBtn.Dx,  btnH);
1345         cr->close_path();
1346         break;
1347 
1348       case SR:
1349         cr->begin_new_sub_path();
1350         cr->arc( m_MidSideBtn.x1 - btnH/2.0, btnH/2.0 + 0.5, btnH/2.0 , -M_PI/2.0, M_PI/2.0);
1351         cr->line_to( m_MidSideBtn.Sx,  btnH);
1352         cr->line_to( m_MidSideBtn.Sx,  0);
1353         cr->close_path();
1354         break;
1355     }
1356 
1357     bkg_gradient_ptr->add_color_stop_rgba (0.1, 0.4, 0.4, 0.4, 0.5 );
1358     bkg_gradient_ptr->add_color_stop_rgba (0.7, m_Color.get_red_p(), m_Color.get_green_p(), m_Color.get_blue_p(), 0.6 );
1359     bkg_gradient_ptr->add_color_stop_rgba (0.9, 0.2, 0.2, 0.2, 0.3 );
1360     cr->set_source(bkg_gradient_ptr);
1361     cr->fill();
1362     cr->restore();
1363 
1364     //Draw a box
1365     cr->save();
1366     cr->begin_new_sub_path();
1367     cr->arc( m_MidSideBtn.x0 + btnH/2.0, btnH/2.0 + 0.5, btnH/2.0, M_PI/2.0, -M_PI/2.0);
1368     cr->arc( m_MidSideBtn.x1 - btnH/2.0, btnH/2.0 + 0.5, btnH/2.0 , -M_PI/2.0, M_PI/2.0);
1369     cr->close_path();
1370     cr->set_source_rgba(0.05,0.05,0.05,0.2);
1371     cr->fill_preserve();
1372     cr->set_line_width(1.0);
1373     if(m_bBandIsEnabled)
1374     {
1375       cr->set_source_rgba(m_Color.get_red_p(), m_Color.get_green_p(), m_Color.get_blue_p(), 0.7);
1376       cr->stroke_preserve();
1377     }
1378     cr->set_source_rgba(0.5, 0.5, 0.5, 0.7);
1379     cr->stroke();
1380     cr->move_to(m_MidSideBtn.Dx, 0);
1381     cr->line_to(m_MidSideBtn.Dx, btnH);
1382     cr->stroke();
1383     cr->move_to(m_MidSideBtn.Sx, 0);
1384     cr->line_to(m_MidSideBtn.Sx, btnH);
1385     cr->stroke();
1386     cr->restore();
1387 
1388     //Draw Text
1389     Glib::RefPtr<Pango::Layout> pangoLayout = Pango::Layout::create(cr);
1390     Pango::FontDescription font_desc("sans bold 10px");
1391     pangoLayout->set_font_description(font_desc);
1392     pangoLayout->set_alignment(Pango::ALIGN_CENTER);
1393 
1394     cr->save();
1395     if(m_MidSideBtn.ML_focus)
1396     {
1397       cr->set_source_rgba(0.0, 1.0, 1.0, 1.0);
1398     }
1399     else if(m_MidSideBtn.State == BandCtl::ML)
1400     {
1401       cr->set_source_rgba(0.0, 1.0, 1.0, 0.8);
1402     }
1403     else
1404     {
1405       cr->set_source_rgba(0.5, 0.5, 0.5, 0.6);
1406     }
1407     pangoLayout->set_width(Pango::SCALE * (m_MidSideBtn.Dx - m_MidSideBtn.Mx));
1408     cr->move_to(m_MidSideBtn.Mx,  btnH/2.0 - 5);
1409     if(m_MidSideBtn.MidSideMode)
1410     {
1411       pangoLayout->set_text("M");
1412     }
1413     else
1414     {
1415       pangoLayout->set_text("L");
1416     }
1417     pangoLayout->show_in_cairo_context(cr);
1418     cr->stroke();
1419 
1420     if(m_MidSideBtn.SR_focus)
1421     {
1422       cr->set_source_rgba(0.0, 1.0, 1.0, 1.0);
1423     }
1424     else if(m_MidSideBtn.State == BandCtl::SR)
1425     {
1426       cr->set_source_rgba(1.0, 1.0, 1.0, 0.8);
1427     }
1428     else
1429     {
1430       cr->set_source_rgba(0.5, 0.5, 0.5, 0.6);
1431     }
1432     pangoLayout->set_width(Pango::SCALE * (m_MidSideBtn.x1 - m_MidSideBtn.Sx));
1433     cr->move_to(m_MidSideBtn.Sx,  btnH/2.0 - 5);
1434     if(m_MidSideBtn.MidSideMode)
1435     {
1436       pangoLayout->set_text("S");
1437     }
1438     else
1439     {
1440       pangoLayout->set_text("R");
1441     }
1442     pangoLayout->show_in_cairo_context(cr);
1443     cr->stroke();
1444     cr->restore();
1445 
1446     //Draw circle in the center
1447     cr->save();
1448     cr->set_line_width(1.5);
1449     if(m_MidSideBtn.Dual_focus)
1450     {
1451       cr->set_source_rgba(0.0, 1.0, 1.0, 1.0);
1452     }
1453     else if( m_MidSideBtn.State == DUAL )
1454     {
1455       cr->set_source_rgba(0.0, 1.0, 1.0, 0.6);
1456     }
1457     else
1458     {
1459       cr->set_source_rgba(0.5, 0.5, 0.5, 0.6);
1460     }
1461     const double Xcenter = (m_midSide_surface_ptr->get_width()/2.0);
1462     cr->arc(Xcenter - btnH/4.0 + (btnH/10.0), (btnH/2.0) + 0.5, btnH/3.5, 0.0, 2.0*M_PI);
1463     cr->stroke();
1464 
1465     if(m_MidSideBtn.Dual_focus)
1466     {
1467       cr->set_source_rgba(0.0, 1.0, 1.0, 1.0);
1468     }
1469     else if( m_MidSideBtn.State == DUAL )
1470     {
1471       cr->set_source_rgba(1.0, 1.0, 1.0, 0.6);
1472     }
1473     else
1474     {
1475       cr->set_source_rgba(0.5, 0.5, 0.5, 0.6);
1476     }
1477     cr->arc(Xcenter + btnH/4.0 - (btnH/10.0), (btnH/2.0) + 0.5, btnH/3.5, 0.0, 2.0*M_PI);
1478     cr->stroke();
1479     cr->restore();
1480 
1481   }
1482 }
1483 
setStereoMode(bool bIsMidSide)1484 void BandCtl::setStereoMode(bool bIsMidSide)
1485 {
1486   if(m_bIsStereoPlugin)
1487   {
1488     m_MidSideBtn.MidSideMode = bIsMidSide;
1489     redraw_MidSide_widget();
1490     redraw();
1491   }
1492 }
1493 
getStereoState()1494 BandCtl::MSState BandCtl::getStereoState()
1495 {
1496   return m_MidSideBtn.State;
1497 }
1498 
setStereoState(BandCtl::MSState state)1499 void BandCtl::setStereoState(BandCtl::MSState state)
1500 {
1501   if(m_bIsStereoPlugin)
1502   {
1503     m_MidSideBtn.State = state;
1504     redraw_MidSide_widget();
1505     redraw();
1506   }
1507 }
1508 
1509