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