4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "bcresources.h"
32 // Which source image to replicate
33 #define METER_NORMAL 0
36 #define METER_YELLOW 3
39 #define METER_DOWNMIX 6
41 // Region of source image to replicate
47 BC_Meter::BC_Meter(int x,
57 : BC_SubWindow(x, y, -1, -1)
59 this->over_delay = 150;
60 this->peak_delay = 15;
61 this->use_titles = use_titles;
65 this->orientation = orientation;
66 this->pixels = pixels;
68 this->downmix = downmix;
70 //printf("BC_Meter::draw_face %d w=%d pixels=%d\n", __LINE__, w, pixels);
71 for(int i = 0; i < TOTAL_METER_IMAGES; i++) images[i] = 0;
72 db_titles.set_array_delete();
77 db_titles.remove_all_objects();
78 title_pixels.remove_all();
79 tick_pixels.remove_all();
80 for(int i = 0; i < TOTAL_METER_IMAGES; i++) delete images[i];
83 int BC_Meter::get_title_w()
85 return get_resources()->meter_title_w;
88 int BC_Meter::get_meter_w()
90 return get_resources()->ymeter_images[0]->get_w();
94 int BC_Meter::set_delays(int over_delay, int peak_delay)
96 this->over_delay = over_delay;
97 this->peak_delay = peak_delay;
101 int BC_Meter::initialize()
104 level_pixel = peak_pixel = 0;
109 if(orientation == METER_VERT)
111 set_images(get_resources()->ymeter_images);
115 w = images[0]->get_w();
116 if(use_titles) w += get_title_w();
123 set_images(get_resources()->xmeter_images);
124 h = images[0]->get_h();
126 if(use_titles) h += get_title_w();
129 // calibrate the db titles
132 BC_SubWindow::initialize();
139 void BC_Meter::set_images(VFrame **data)
141 for(int i = 0; i < TOTAL_METER_IMAGES; i++) delete images[i];
142 for(int i = 0; i < TOTAL_METER_IMAGES; i++)
143 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
146 int BC_Meter::reposition_window(int x, int y, int span, int pixels)
148 if(pixels < 0) pixels = this->pixels;
150 this->pixels = pixels;
151 if(orientation == METER_VERT)
152 BC_SubWindow::reposition_window(x,
154 this->span < 0 ? w : span,
157 BC_SubWindow::reposition_window(x, y, pixels, get_h());
159 //printf("BC_Meter::reposition_window 1 %d %d %d %d\n", x, y, w, h);
163 //draw_box(0, 0, w, h);
171 int BC_Meter::reset(int dmix)
175 level_pixel = peak_pixel = 0;
179 if(dmix >= 0) downmix = dmix;
184 int BC_Meter::button_press_event()
186 if(cursor_inside() && is_event_win())
195 int BC_Meter::reset_over()
201 int BC_Meter::change_format(int mode, int min, int max)
206 reposition_window(get_x(), get_y(), w, pixels);
210 int BC_Meter::level_to_pixel(float level)
215 result = (int)(pixels *
218 if(level <= min) result = 0;
222 // Not implemented anymore
230 void BC_Meter::get_divisions()
232 char string[BCTEXTLEN];
236 db_titles.remove_all_objects();
237 title_pixels.remove_all();
238 tick_pixels.remove_all();
242 high_division = pixels;
245 // Create tick marks and titles in one pass
246 for(int current = min; current <= max; current++)
248 if(orientation == METER_VERT)
251 current_pixel = (pixels - METER_MARGIN * 2 - 2) *
252 (current - min) / (max - min) + 2;
253 tick_pixels.append(current_pixel);
255 // Create titles in selected positions
259 (current - min > 4 && max - current > 4 && !(current % 5)))
261 int title_pixel = (pixels -
262 METER_MARGIN * 2) * (current - min) / (max - min);
263 sprintf(string, "%ld", labs(current));
264 new_string = new char[strlen(string) + 1];
265 strcpy(new_string, string);
266 db_titles.append(new_string);
267 title_pixels.append(title_pixel);
272 current_pixel = (pixels - METER_MARGIN * 2) *
275 tick_pixels.append(current_pixel);
276 // Titles not supported for horizontal
279 // Create color divisions
282 low_division = current_pixel;
287 medium_division = current_pixel;
292 high_division = current_pixel;
295 // if(orientation == METER_VERT)
296 // printf("BC_Meter::get_divisions %d %d %d %d\n",
297 // low_division, medium_division, high_division, pixels);
300 void BC_Meter::draw_titles(int flush)
302 if(!use_titles) return;
304 set_font(get_resources()->meter_font);
306 if(orientation == METER_HORIZ)
308 draw_top_background(parent_window, 0, 0, get_w(), get_title_w());
310 for(int i = 0; i < db_titles.total; i++)
312 draw_text(0, title_pixels.values[i], db_titles.values[i]);
315 flash(0, 0, get_w(), get_title_w(), flush);
318 if(orientation == METER_VERT)
320 draw_top_background(parent_window, 0, 0, get_title_w(), get_h());
323 for(int i = 0; i < db_titles.total; i++)
325 int title_y = pixels -
326 title_pixels.values[i];
328 title_y -= get_text_descent(SMALLFONT_3D);
330 if(i == db_titles.total - 1)
331 title_y += get_text_ascent(SMALLFONT_3D);
333 title_y += get_text_ascent(SMALLFONT_3D) / 2;
335 set_color(get_resources()->meter_font_color);
338 db_titles.values[i]);
341 for(int i = 0; i < tick_pixels.total; i++)
344 int tick_y = pixels - tick_pixels.values[i] - METER_MARGIN;
345 set_color(get_resources()->meter_font_color);
346 draw_line(get_title_w() - xS(10) - 1, tick_y, get_title_w() - 1, tick_y);
347 if(get_resources()->meter_3d)
350 draw_line(get_title_w() - xS(10), tick_y + 1, get_title_w(), tick_y + 1);
354 flash(0, 0, get_title_w(), get_h(), flush);
358 int BC_Meter::region_pixel(int region)
360 VFrame **reference_images = get_resources()->xmeter_images;
363 if(region == METER_RIGHT)
364 result = region * reference_images[0]->get_w() / 4;
366 result = region * reference_images[0]->get_w() / 4;
371 int BC_Meter::region_pixels(int region)
376 VFrame **reference_images = get_resources()->xmeter_images;
378 x1 = region * reference_images[0]->get_w() / 4;
379 x2 = (region + 1) * reference_images[0]->get_w() / 4;
380 if(region == METER_MID)
381 result = (x2 - x1) * 2;
387 void BC_Meter::draw_face(int flush)
389 int level_pixel = level_to_pixel(level);
390 int peak_pixel2 = level_to_pixel(peak);
391 int peak_pixel1 = peak_pixel2 - 2;
392 int left_pixel = region_pixel(METER_MID);
393 int right_pixel = pixels - region_pixels(METER_RIGHT);
395 int image_number = 0, region = 0;
396 int in_span, in_start;
397 int x = use_titles ? get_title_w() : 0;
398 int w = use_titles ? (this->w - get_title_w()) : this->w;
400 draw_top_background(parent_window, x, 0, w, h);
402 // printf("BC_Meter::draw_face %d span=%d this->w=%d get_title_w()=%d %d %d\n",
410 while(pixel < pixels)
412 // Select image to draw
413 if(pixel < level_pixel ||
414 (pixel >= peak_pixel1 && pixel < peak_pixel2))
416 if(pixel < low_division)
417 image_number = METER_GREEN;
419 if(pixel < medium_division)
420 image_number = METER_YELLOW;
422 if(pixel < high_division)
423 image_number = METER_RED;
425 image_number = METER_WHITE;
429 image_number = METER_NORMAL;
432 // Select region of image to duplicate
433 if(pixel < left_pixel)
436 in_start = pixel + region_pixel(region);
437 in_span = region_pixels(region) - (in_start - region_pixel(region));
440 if(pixel < right_pixel)
443 in_start = region_pixel(region);
444 in_span = region_pixels(region);
448 region = METER_RIGHT;
449 in_start = (pixel - right_pixel) + region_pixel(region);
450 in_span = region_pixels(region) - (in_start - region_pixel(region));;
453 //printf("BC_Meter::draw_face region %d pixel %d pixels %d in_start %d in_span %d\n", region, pixel, pixels, in_start, in_span);
456 // Clip length to peaks
457 if(pixel < level_pixel && pixel + in_span > level_pixel)
458 in_span = level_pixel - pixel;
460 if(pixel < peak_pixel1 && pixel + in_span > peak_pixel1)
461 in_span = peak_pixel1 - pixel;
463 if(pixel < peak_pixel2 && pixel + in_span > peak_pixel2)
464 in_span = peak_pixel2 - pixel;
466 // Clip length to color changes
467 if(image_number == METER_GREEN && pixel + in_span > low_division)
468 in_span = low_division - pixel;
470 if(image_number == METER_YELLOW && pixel + in_span > medium_division)
471 in_span = medium_division - pixel;
473 if(image_number == METER_RED && pixel + in_span > high_division)
474 in_span = high_division - pixel;
476 // Clip length to regions
477 if(pixel < left_pixel && pixel + in_span > left_pixel)
478 in_span = left_pixel - pixel;
480 if(pixel < right_pixel && pixel + in_span > right_pixel)
481 in_span = right_pixel - pixel;
483 //printf("BC_Meter::draw_face image_number %d pixel %d pixels %d in_start %d in_span %d\n", image_number, pixel, pixels, in_start, in_span);
484 //printf("BC_Meter::draw_face %d %d %d %d\n", orientation, region, images[image_number]->get_h() - in_start - in_span);
485 if(orientation == METER_HORIZ)
487 draw_pixmap(images[image_number],
497 //printf("BC_Meter::draw_face %d %d\n", __LINE__, span);
500 draw_pixmap(images[image_number],
502 get_h() - pixel - in_span,
506 images[image_number]->get_h() - in_start - in_span);
510 int total_w = get_w() - x;
511 int third = images[image_number]->get_w() / 3 + 1;
514 for(int x1 = 0; x1 < total_w; x1 += third)
518 if(x1 >= third) in_x = third;
519 if(x1 >= total_w - third)
521 in_x = images[image_number]->get_w() -
526 int in_y = images[image_number]->get_h() - in_start - in_span;
527 //printf("BC_Meter::draw_face %d %d %d\n", __LINE__, get_w(), x + x1 + in_w, in_x, in_y, in_w, span);
530 draw_pixmap(images[image_number],
531 x + x1, get_h() - pixel - in_span,
532 in_w, in_span + 1, in_x, in_y);
547 if(orientation == METER_HORIZ)
548 draw_pixmap(images[METER_DOWNMIX], 0, 0);
550 draw_pixmap(images[METER_DOWNMIX], x,
551 get_h() - images[METER_DOWNMIX]->get_h()-1);
556 if(orientation == METER_HORIZ)
557 draw_pixmap(images[METER_OVER], xS(20), yS(2));
559 draw_pixmap(images[METER_OVER], x, get_h() - yS(100));
564 if(orientation == METER_HORIZ)
565 flash(0, 0, pixels, get_h(), flush);
567 flash(x, 0, w, pixels, flush);
570 int BC_Meter::update(float new_value, int over, int dmix)
579 level = db.todb(new_value); // db value
582 if(level > peak || peak_timer > peak_delay)
588 // if(orientation == METER_HORIZ)
589 // printf("BC_Meter::update %f\n", level);
590 if(over) over_timer = over_delay;
591 // only draw if window is visible
592 if(dmix >= 0) downmix = dmix;