1 /***************************************************************************
2 * Copyright (C) 2011 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 <iostream>
22 #include <cmath>
23 #include <cstdio>
24
25 #include "colors.h"
26 #include "vuwidget.h"
27
28 #define TEXT_OFFSET 12
29 #define MARGIN 6.5
30 #define CHANNEL_WIDTH 9
31 #define MICROFADER_WIDTH 30
32 #define SCROLL_EVENT_PERCENT 0.02
33 #define WIDGET_HEIGHT 150
34 #define TOP_OFFSET 24
35 #define AUTO_REFRESH_TIMEOUT_MS 20
36
VUWidget(int iChannels,float fMin,float fMax,std::string title,bool IsGainReduction,bool DrawThreshold)37 VUWidget::VUWidget(int iChannels, float fMin, float fMax, std::string title, bool IsGainReduction, bool DrawThreshold)
38 :m_iChannels(iChannels),
39 m_fMin(fMin),
40 m_fMax(fMax),
41 m_bIsGainReduction(IsGainReduction),
42 bMotionIsConnected(false),
43 m_fValues(new float[m_iChannels]),
44 m_fPeaks(new float[m_iChannels]),
45 m_iBuffCnt(new int[m_iChannels]),
46 m_ThFaderValue(0.0),
47 m_iThFaderPositon(0),
48 m_bDrawThreshold(DrawThreshold),
49 m_start(new timeval[m_iChannels]),
50 m_end(new timeval[m_iChannels]),
51 m_Title(title),
52 m_redraw_fader(true),
53 m_redraw_Vu(true),
54 m_FaderFocus(false)
55 {
56
57 m_textdBseparation = (int)round((m_fMax - m_fMin)/18.0);
58
59 for (int i = 0; i < m_iChannels; i++)
60 {
61 m_fValues[i] = -100.0;
62 m_fPeaks[i] = -100.0;
63 m_iBuffCnt[i] = 0;
64 }
65
66 int widget_witdh;
67 if(m_bDrawThreshold)
68 {
69 widget_witdh = MARGIN + TEXT_OFFSET + (MARGIN + CHANNEL_WIDTH)* m_iChannels + MICROFADER_WIDTH/2 + MARGIN + 2;
70 }
71 else
72 {
73 widget_witdh = MARGIN + TEXT_OFFSET + (MARGIN + CHANNEL_WIDTH)* m_iChannels;
74 }
75 set_size_request(widget_witdh, WIDGET_HEIGHT);
76
77
78 //Initialize peak time counters
79 for (int i = 0; i < m_iChannels; i++)
80 {
81 gettimeofday(&m_start[i], NULL);
82 gettimeofday(&m_end[i], NULL);
83 }
84
85 //The micro fader for threshold
86 if(m_bDrawThreshold)
87 {
88 add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::SCROLL_MASK | Gdk::LEAVE_NOTIFY_MASK);
89 signal_button_press_event().connect(sigc::mem_fun(*this, &VUWidget::on_button_press_event),true);
90 signal_button_release_event().connect(sigc::mem_fun(*this, &VUWidget::on_button_release_event),true);
91 signal_scroll_event().connect(sigc::mem_fun(*this, &VUWidget::on_scrollwheel_event),true);
92 signal_motion_notify_event().connect(sigc::mem_fun(*this, &VUWidget::on_mouse_motion_event),true);
93 signal_leave_notify_event().connect(sigc::mem_fun(*this, &VUWidget::on_mouse_leave_widget),true);
94 }
95
96 Glib::signal_timeout().connect( sigc::mem_fun(*this, &VUWidget::on_timeout_redraw), AUTO_REFRESH_TIMEOUT_MS );
97 }
98
~VUWidget()99 VUWidget::~VUWidget()
100 {
101 delete [] m_fValues;
102 delete [] m_fPeaks;
103 delete [] m_start;
104 delete [] m_end;
105 delete [] m_iBuffCnt;
106 }
107
on_mouse_leave_widget(GdkEventCrossing * event)108 bool VUWidget::on_mouse_leave_widget(GdkEventCrossing* event)
109 {
110 if(!bMotionIsConnected)
111 {
112 m_FaderFocus = false;
113 m_redraw_fader = true;
114 }
115 return true;
116 }
117
setValue(int iChannel,float fValue)118 void VUWidget::setValue(int iChannel, float fValue)
119 {
120 if (fValue > 0)
121 {
122 if(m_iBuffCnt[iChannel] > 0)
123 {
124 m_fValues[iChannel] = ((((double)m_iBuffCnt[iChannel])*m_fValues[iChannel]) + 20.0*log10(fValue))/((double)(m_iBuffCnt[iChannel] + 1));
125 }
126 else
127 {
128 m_fValues[iChannel] = 20.0*log10(fValue);
129 }
130 m_iBuffCnt[iChannel]++;
131 }
132 else
133 {
134 m_fValues[iChannel] = -100.0;
135 }
136
137 m_redraw_Vu = true;
138 }
139
clearPeak(int iChannel)140 void VUWidget::clearPeak(int iChannel)
141 {
142 m_fPeaks[iChannel] = 0.0;
143 }
144
dB2Pixels(double dB_in)145 double VUWidget::dB2Pixels(double dB_in)
146 {
147 double m, n;
148 if(m_bIsGainReduction)
149 {
150 m = ((double)(height - 3.0*MARGIN - TOP_OFFSET))/(m_fMax - m_fMin);
151 n = (double)(MARGIN + TOP_OFFSET) - m_fMin*m;
152 }
153 else
154 {
155 m = ((double)(3.0*MARGIN + TOP_OFFSET - height ))/(m_fMax - m_fMin);
156 n = (double)(height - 2.0*MARGIN) - m_fMin*m;
157 }
158 return m*dB_in + n;
159 }
160
161
on_expose_event(GdkEventExpose * event)162 bool VUWidget::on_expose_event(GdkEventExpose* event)
163 {
164 Glib::RefPtr<Gdk::Window> window = get_window();
165 if(window)
166 {
167 Gtk::Allocation allocation = get_allocation();
168 width = allocation.get_width();
169 height = allocation.get_height();
170
171 if(!(m_background_surface_ptr || m_foreground_surface_ptr || m_fader_surface_ptr ))
172 {
173 m_background_surface_ptr = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, width, height);
174 redraw_background();
175 m_foreground_surface_ptr = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, width, height);
176 redraw_foreground();
177 m_vu_surface_ptr = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, width, height);
178 redraw_vuwidget();
179 if(m_bDrawThreshold)
180 {
181 m_fader_surface_ptr = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, width, height);
182 redraw_faderwidget();
183 }
184 }
185
186 Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
187
188 //Draw the background
189 if(m_background_surface_ptr)
190 {
191 cr->save();
192 cr->set_source(m_background_surface_ptr, 0, 0);
193 cr->paint();
194 cr->restore();
195 }
196
197 //Draw the VU
198 if(m_vu_surface_ptr)
199 {
200 cr->save();
201 cr->set_source(m_vu_surface_ptr, 0, 0);
202 cr->paint();
203 cr->restore();
204 }
205
206 //Draw the foreground
207 if(m_foreground_surface_ptr)
208 {
209 cr->save();
210 cr->set_source(m_foreground_surface_ptr, 0, 0);
211 cr->paint();
212 cr->restore();
213 }
214
215 //Draw the fader widget
216 if(m_fader_surface_ptr)
217 {
218 cr->save();
219 cr->set_source(m_fader_surface_ptr, 0, 0);
220 cr->paint();
221 cr->restore();
222 }
223 }
224 return true;
225 }
226
set_value_th(double value)227 void VUWidget::set_value_th(double value)
228 {
229 m_ThFaderValue = value;
230 m_ThFaderValue = m_ThFaderValue < m_fMin + 2.0 ? m_fMin + 2.0 : m_ThFaderValue;
231 m_ThFaderValue = m_ThFaderValue > m_fMax - 2.0 ? m_fMax - 2.0 : m_ThFaderValue; //Limit threshols 2dB less than VU
232 m_redraw_fader = true;
233 }
234
get_value_th()235 double VUWidget::get_value_th()
236 {
237 return m_ThFaderValue;
238 }
239
240 //Mouse grab signal handlers
on_button_press_event(GdkEventButton * event)241 bool VUWidget::on_button_press_event(GdkEventButton* event)
242 {
243 int x,y;
244 get_pointer(x,y);
245 if( y > m_iThFaderPositon - MICROFADER_WIDTH/2 &&
246 y < m_iThFaderPositon + MICROFADER_WIDTH/2)
247 {
248 bMotionIsConnected = true;
249 }
250 return true;
251 }
252
on_button_release_event(GdkEventButton * event)253 bool VUWidget::on_button_release_event(GdkEventButton* event)
254 {
255 bMotionIsConnected = false;
256 return true;
257 }
258
on_scrollwheel_event(GdkEventScroll * event)259 bool VUWidget::on_scrollwheel_event(GdkEventScroll* event)
260 {
261 double increment;
262
263 increment = SCROLL_EVENT_PERCENT*(m_fMax - m_fMin);
264 if (event->direction == GDK_SCROLL_UP)
265 {
266 // up code
267 set_value_th(m_ThFaderValue + increment);
268
269 }
270 else if (event->direction == GDK_SCROLL_DOWN)
271 {
272 // down code
273 set_value_th(m_ThFaderValue - increment);
274 }
275 m_FaderChangedSignal.emit();
276 return true;
277 }
278
on_mouse_motion_event(GdkEventMotion * event)279 bool VUWidget::on_mouse_motion_event(GdkEventMotion* event)
280 {
281 if (bMotionIsConnected)
282 {
283 double m = ((double)(3.0*MARGIN + TOP_OFFSET - height ))/(m_fMax - m_fMin);
284 double n = (double)(height - 2.0*MARGIN) - m_fMin*m;
285 double faderPos = (event->y - n)/m;
286 set_value_th(faderPos);
287 m_FaderChangedSignal.emit();
288 }
289 else
290 {
291 //Check focus on fader widget
292 m_FaderFocus = event->y > m_iThFaderPositon - MICROFADER_WIDTH/2 && event->y < m_iThFaderPositon + MICROFADER_WIDTH/2 &&
293 event->x > width - MICROFADER_WIDTH && event->x < width ;
294 m_redraw_fader = true;
295 }
296 return true;
297 }
298
signal_changed()299 VUWidget::signal_FaderChanged VUWidget::signal_changed()
300 {
301 return m_FaderChangedSignal;
302 }
303
redraw_background()304 void VUWidget::redraw_background()
305 {
306 if(m_background_surface_ptr)
307 {
308 //Create cairo context using the buffer surface
309 Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create(m_background_surface_ptr);
310
311 //Paint background
312 cr->save();
313 cr->set_source_rgb(BACKGROUND_R, BACKGROUND_G, BACKGROUND_B);
314 cr->paint(); //Fill all with background color
315 cr->restore();
316
317 //Draw text with pango
318 cr->save();
319 Glib::RefPtr<Pango::Layout> pangoLayout = Pango::Layout::create(cr);
320 Pango::FontDescription font_desc("mono 9px");
321 pangoLayout->set_font_description(font_desc);
322 cr->set_source_rgba(0.9, 0.9, 0.9, 0.5);
323
324 cr->move_to(MARGIN + TEXT_OFFSET - 3, TOP_OFFSET/2);//4 is to get the text centered in VU
325 pangoLayout->set_text(m_Title.c_str());
326 pangoLayout->set_width(Pango::SCALE * (CHANNEL_WIDTH * m_iChannels + (m_iChannels - 1)*MARGIN));
327 pangoLayout->set_alignment(Pango::ALIGN_CENTER);
328 pangoLayout->show_in_cairo_context(cr);
329 cr->stroke();
330
331 for(float fdb = m_fMin; fdb <= m_fMax; fdb = fdb + m_textdBseparation)
332 {
333 std::stringstream ss;
334 ss<<abs(round(fdb));
335 cr->move_to(MARGIN, dB2Pixels(fdb) - 4);//4 is to get the text centered in VU
336 pangoLayout->set_text(ss.str());
337 pangoLayout->set_width(Pango::SCALE * (TEXT_OFFSET - MARGIN));
338 pangoLayout->set_alignment(Pango::ALIGN_RIGHT);
339 pangoLayout->show_in_cairo_context(cr);
340 cr->stroke();
341 }
342 cr->restore();
343
344 //Draw VU rectangle
345 double radius = height / 100.0;
346 double degrees = M_PI / 180.0;
347 for(int i = 0; i < m_iChannels; i++)
348 {
349 cr->save();
350 cr->begin_new_sub_path();
351 cr->arc (MARGIN + TEXT_OFFSET + CHANNEL_WIDTH + i*(MARGIN + CHANNEL_WIDTH + 0.5) - radius, MARGIN + TOP_OFFSET - 4 + radius, radius, -90 * degrees, 0 * degrees);
352 cr->arc (MARGIN + TEXT_OFFSET + CHANNEL_WIDTH + i*(MARGIN + CHANNEL_WIDTH + 0.5) - radius, height - 1 - MARGIN - radius, radius, 0 * degrees, 90 * degrees);
353 cr->arc (MARGIN + TEXT_OFFSET + i*(MARGIN + CHANNEL_WIDTH + 0.5) + radius, height - 1 - MARGIN - radius, radius, 90 * degrees, 180 * degrees);
354 cr->arc (MARGIN + TEXT_OFFSET + i*(MARGIN + CHANNEL_WIDTH + 0.5) + radius, MARGIN + TOP_OFFSET - 4 + radius, radius, 180 * degrees, 270 * degrees);
355 cr->close_path();
356 cr->set_source_rgb(0.15, 0.15, 0.15);
357 cr->fill_preserve();
358 cr->set_line_width(1.0);
359 cr->set_source_rgb(0.5, 0.5, 0.5);
360 cr->stroke();
361 cr->restore();
362 }
363 }
364 }
365
redraw_foreground()366 void VUWidget::redraw_foreground()
367 {
368 if(m_foreground_surface_ptr)
369 {
370 //Create cairo context using the buffer surface
371 Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create(m_foreground_surface_ptr);
372
373 //Draw some horitzontal lines to show dB scale over Vu
374 cr->save();
375 cr->set_line_width(1.0);
376 cr->set_source_rgba(0.8, 0.8, 0.8, 0.4);
377 for(float fdb = m_fMin; fdb <= m_fMax; fdb = fdb + m_textdBseparation)
378 {
379 cr->move_to(MARGIN + TEXT_OFFSET - 2, round(dB2Pixels(fdb)) + 0.5);
380 cr->line_to(MARGIN + TEXT_OFFSET + CHANNEL_WIDTH + (m_iChannels - 1 ) * (CHANNEL_WIDTH + MARGIN ) + 2, round(dB2Pixels(fdb)) + 0.5);
381 cr->stroke();
382 }
383 cr->restore();
384 }
385 }
386
redraw_faderwidget()387 void VUWidget::redraw_faderwidget()
388 {
389 if(m_fader_surface_ptr)
390 {
391 //Create cairo context using the buffer surface
392 Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create(m_fader_surface_ptr);
393
394 //Clear current context
395 cr->save();
396 cr->set_operator(Cairo::OPERATOR_CLEAR);
397 cr->paint();
398 cr->restore();
399
400 //Draw vertical line
401 cr->save();
402 cr->move_to(width - MICROFADER_WIDTH/2 + 0.5, dB2Pixels(m_fMin + 2.0));
403 cr->line_to(width - MICROFADER_WIDTH/2 + 0.5, dB2Pixels(m_fMax - 2.0));
404
405 cr->set_line_cap(Cairo::LINE_CAP_ROUND);
406 cr->set_line_width(3.0);
407 cr->set_source_rgba(0.7, 0.7, 0.7, 0.5);
408 cr->stroke_preserve();
409 cr->set_source_rgba(0.15, 0.15, 0.15, 1.0);
410 cr->set_line_width(1);
411 cr->stroke();
412
413 //Draw threshold text with pango
414 Glib::RefPtr<Pango::Layout> pangoLayout_th = Pango::Layout::create(cr);
415 Pango::FontDescription font_desc_th("sans bold 8px");
416 font_desc_th.set_gravity(Pango::GRAVITY_EAST);
417 pangoLayout_th->set_font_description(font_desc_th);
418 pangoLayout_th->set_alignment(Pango::ALIGN_LEFT);
419 cr->move_to(width - MICROFADER_WIDTH/2 - 10, height - MICROFADER_WIDTH/2 - 85);
420 cr->set_source_rgba(0.9, 0.9, 0.9, 0.7);
421 pangoLayout_th->update_from_cairo_context(cr); //gets cairo cursor position
422 pangoLayout_th->set_text("d\r\nl\r\no\r\nh\r\ns\r\ne\r\nr\r\nh\r\nT");
423 pangoLayout_th->show_in_cairo_context(cr);
424 cr->stroke();
425
426 //Calc coords for mini fader
427 m_iThFaderPositon = (int) dB2Pixels(m_ThFaderValue);
428
429 //Draw the fader drop down shadow
430 cr->save();
431 cr->translate(width - MICROFADER_WIDTH/2 + 2, m_iThFaderPositon + 4);
432 cr->scale(MICROFADER_WIDTH/2, MICROFADER_WIDTH/4);
433 Cairo::RefPtr<Cairo::RadialGradient> bkg_gradient_rad_ptr = Cairo::RadialGradient::create(0, 0, 0, 0, 0, 1);
434 bkg_gradient_rad_ptr->add_color_stop_rgba (0.3, 0.2, 0.2, 0.2, 1.0);
435 bkg_gradient_rad_ptr->add_color_stop_rgba (1.0, 0.1, 0.1, 0.2, 0.0);
436 cr->set_source(bkg_gradient_rad_ptr);
437 cr->arc(0.0, 0.0, 1.0, 0.0, 2.0*M_PI);
438 cr->fill();
439 cr->restore();
440
441 //Draw Threshold fader
442 double degrees = M_PI / 180.0;
443 cr->begin_new_sub_path();
444 cr->arc(width - 2 - MICROFADER_WIDTH/4, m_iThFaderPositon + 0.5, MICROFADER_WIDTH/4, -90 * degrees, 90 * degrees);
445 cr->line_to( width - 2 - MICROFADER_WIDTH/2, m_iThFaderPositon + MICROFADER_WIDTH/4 + 0.5);
446 cr->line_to( width - 2 - MICROFADER_WIDTH, m_iThFaderPositon + 0.5);
447 cr->line_to( width - 2 - MICROFADER_WIDTH/2, m_iThFaderPositon - MICROFADER_WIDTH/4 + 0.5);
448 cr->close_path();
449 Cairo::RefPtr<Cairo::LinearGradient> bkg_gradient_ptr = Cairo::LinearGradient::create(width - 2 - MICROFADER_WIDTH/2, m_iThFaderPositon - MICROFADER_WIDTH/4, width - 2 - MICROFADER_WIDTH/2, m_iThFaderPositon + MICROFADER_WIDTH/4);
450 bkg_gradient_ptr->add_color_stop_rgba (0.3, 0.8, 0.8, 0.85, 1.0);
451 bkg_gradient_ptr->add_color_stop_rgba (1.0, 0.2, 0.2, 0.25, 1.0);
452 cr->set_source(bkg_gradient_ptr);
453 cr->fill_preserve();
454
455 //Draw focus glow
456 if(m_FaderFocus)
457 {
458 Cairo::RefPtr<Cairo::RadialGradient> glow_gradient_rad_ptr = Cairo::RadialGradient::create(width - MICROFADER_WIDTH/2, m_iThFaderPositon, MICROFADER_WIDTH/2, width - MICROFADER_WIDTH/2, m_iThFaderPositon, MICROFADER_WIDTH);
459 glow_gradient_rad_ptr->add_color_stop_rgba (0.0, 0.0, 1.0, 1.0, 0.1);
460 glow_gradient_rad_ptr->add_color_stop_rgba (0.05, 1.0, 1.0, 1.0, 0.3);
461 cr->set_source(glow_gradient_rad_ptr);
462 cr->fill_preserve();
463 }
464 cr->set_source_rgba(0.1, 0.1, 0.1, 0.7);
465 cr->set_line_width(1.0);
466 cr->stroke();
467
468 cr->move_to(width - 2 - 5*MICROFADER_WIDTH/8, m_iThFaderPositon + 0.5);
469 cr->line_to(width - 4 - MICROFADER_WIDTH/8, m_iThFaderPositon + 0.5);
470 cr->move_to(width - 2 - 5*MICROFADER_WIDTH/8, m_iThFaderPositon + 0.5 - 2);
471 cr->line_to(width - 4 - MICROFADER_WIDTH/8, m_iThFaderPositon + 0.5 - 2);
472 cr->move_to(width - 2 - 5*MICROFADER_WIDTH/8, m_iThFaderPositon + 0.5 + 2);
473 cr->line_to(width - 4 - MICROFADER_WIDTH/8, m_iThFaderPositon + 0.5 + 2);
474 cr->set_source_rgba(0.0, 0.0, 0.0, 0.2);
475 cr->set_line_width(1.0);
476 cr->stroke();
477 }
478 }
479
redraw_vuwidget()480 void VUWidget::redraw_vuwidget()
481 {
482 if(m_vu_surface_ptr)
483 {
484 //Create cairo context using the buffer surface
485 Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create(m_vu_surface_ptr);
486
487 //Clear current context
488 cr->save();
489 cr->set_operator(Cairo::OPERATOR_CLEAR);
490 cr->paint();
491 cr->restore();
492 //Draw the VU
493 Cairo::RefPtr<Cairo::LinearGradient> bkg_gradient_ptr;
494 for(int i = 0; i < m_iChannels; i++)
495 {
496 //Reset mean buffer
497 m_iBuffCnt[i] = 0;
498 long mtime, seconds, useconds;
499 gettimeofday(&m_end[i], NULL);
500
501 seconds = m_end[i].tv_sec - m_start[i].tv_sec;
502 useconds = m_end[i].tv_usec - m_start[i].tv_usec;
503 mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5;
504
505 //Clip max
506 m_fValues[i] = m_fValues[i] > m_fMax ? m_fMax : m_fValues[i];
507
508 if (m_fValues[i] >= m_fPeaks[i])
509 {
510 m_fPeaks[i] = m_fValues[i];
511 gettimeofday(&m_start[i] , NULL);
512 }
513
514 else if (mtime > PEAK_CLEAR_TIMEOUT)
515 {
516 m_fPeaks[i] = -100.0;
517 }
518
519
520 cr->save();
521 cr->set_line_width(CHANNEL_WIDTH - 4);
522 cr->set_line_cap(Cairo::LINE_CAP_ROUND);
523 bkg_gradient_ptr = Cairo::LinearGradient::create(MARGIN + TEXT_OFFSET + CHANNEL_WIDTH/2.0 + i*(MARGIN + CHANNEL_WIDTH + 0.5), dB2Pixels(m_fMin), MARGIN + TEXT_OFFSET + CHANNEL_WIDTH/2.0 + i*(MARGIN + CHANNEL_WIDTH + 0.5), dB2Pixels(m_fMax));
524 if(m_bIsGainReduction)
525 {
526 bkg_gradient_ptr->add_color_stop_rgba (0.0, 1.0, 0.5, 0.0, 0.0);
527 bkg_gradient_ptr->add_color_stop_rgba (0.01, 1.0, 0.5, 0.0, 1.0);
528 bkg_gradient_ptr->add_color_stop_rgba (1.0, 1.0, 0.0, 0.0, 1.0);
529 }
530 else
531 {
532 bkg_gradient_ptr->add_color_stop_rgba (0.0, 0.0, 1.0, 0.0, 0.0);
533 bkg_gradient_ptr->add_color_stop_rgba (0.01, 0.0, 1.0, 0.0, 1.0);
534 bkg_gradient_ptr->add_color_stop_rgba (0.5, 1.0, 1.0, 0.0, 1.0);
535 bkg_gradient_ptr->add_color_stop_rgba (1.0, 1.0, 0.0, 0.0, 1.0);
536 }
537 cr->set_source(bkg_gradient_ptr);
538
539 //The VU
540 if(m_fValues[i] >= m_fMin)
541 {
542 cr->move_to(MARGIN + TEXT_OFFSET + CHANNEL_WIDTH/2.0 + i*(MARGIN + CHANNEL_WIDTH + 0.5), dB2Pixels(m_fMin));
543 cr->line_to(MARGIN + TEXT_OFFSET + CHANNEL_WIDTH/2.0 + i*(MARGIN + CHANNEL_WIDTH + 0.5), dB2Pixels(m_fValues[i]));
544 cr->stroke();
545 }
546
547 //The peak
548 if(m_fPeaks[i] >= m_fMin)
549 {
550 cr->move_to(MARGIN + TEXT_OFFSET + CHANNEL_WIDTH/2.0 + i*(MARGIN + CHANNEL_WIDTH + 0.5), dB2Pixels(m_fPeaks[i]));
551 cr->line_to(MARGIN + TEXT_OFFSET + CHANNEL_WIDTH/2.0 + i*(MARGIN + CHANNEL_WIDTH + 0.5), dB2Pixels(m_fPeaks[i]));
552 cr->stroke();
553 cr->restore();
554 }
555 }
556 }
557 }
558
on_timeout_redraw()559 bool VUWidget::on_timeout_redraw()
560 {
561 bool redraw = false;
562 if(m_redraw_fader)
563 {
564 m_redraw_fader = false;
565 redraw = true;
566 redraw_faderwidget();
567 }
568
569 if(m_redraw_Vu)
570 {
571 m_redraw_Vu = false;
572 redraw = true;
573 redraw_vuwidget();
574 }
575
576 if(redraw)
577 {
578 Glib::RefPtr<Gdk::Window> win = get_window();
579 if(win)
580 {
581 Gdk::Rectangle r(0, 0, get_allocation().get_width(), get_allocation().get_height());
582 win->invalidate_rect(r, false);
583 }
584 }
585 return true;
586 }
587
588