3 * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
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.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "bcsignals.h"
26 #include "scopewindow.h"
31 ScopePackage::ScopePackage()
36 ScopeUnit::ScopeUnit(ScopeGUI *gui,
43 void ScopeUnit::draw_point(unsigned char **rows,
44 int x, int y, int r, int g, int b)
46 unsigned char *pixel = rows[y] + x * 4;
52 #define PROCESS_PIXEL(column) { \
53 /* Calculate histogram */ \
55 int v_i = (intensity - FLOAT_MIN) * (TOTAL_BINS / (FLOAT_MAX - FLOAT_MIN)); \
56 CLAMP(v_i, 0, TOTAL_BINS - 1); \
59 else if(use_hist_parade) { \
60 int r_i = (r - FLOAT_MIN) * (TOTAL_BINS / (FLOAT_MAX - FLOAT_MIN)); \
61 int g_i = (g - FLOAT_MIN) * (TOTAL_BINS / (FLOAT_MAX - FLOAT_MIN)); \
62 int b_i = (b - FLOAT_MIN) * (TOTAL_BINS / (FLOAT_MAX - FLOAT_MIN)); \
63 CLAMP(r_i, 0, TOTAL_BINS - 1); \
64 CLAMP(g_i, 0, TOTAL_BINS - 1); \
65 CLAMP(b_i, 0, TOTAL_BINS - 1); \
70 /* Calculate waveform */ \
71 if(use_wave || use_wave_parade) { \
72 int ix = (column) * wave_w / w; \
73 if(ix >= 0 && ix < wave_w) { \
74 if(use_wave_parade) { \
75 int iy = wave_h - (int)((r - FLOAT_MIN) / \
76 (FLOAT_MAX - FLOAT_MIN) * wave_h); \
77 if(iy >= 0 && iy < wave_h) \
78 draw_point(waveform_rows, ix / 3, iy, 0xff, 0x0, 0x0); \
79 iy = wave_h - (int)((g - FLOAT_MIN) / \
80 (FLOAT_MAX - FLOAT_MIN) * wave_h); \
81 if(iy >= 0 && iy < wave_h) \
82 draw_point(waveform_rows, ix / 3 + wave_w / 3, iy, 0x0, 0xff, 0x0); \
83 iy = wave_h - (int)((b - FLOAT_MIN) / \
84 (FLOAT_MAX - FLOAT_MIN) * wave_h); \
85 if(iy >= 0 && iy < wave_h) \
86 draw_point(waveform_rows, ix / 3 + wave_w / 3 * 2, iy, 0x0, 0x0, 0xff); \
89 int iy = wave_h - (int)((intensity - FLOAT_MIN) / \
90 (FLOAT_MAX - FLOAT_MIN) * wave_h); \
91 if(iy >= 0 && iy < wave_h) \
92 draw_point(waveform_rows, ix, iy, 0xff, 0xff, 0xff); \
96 /* Calculate vectorscope */ \
98 float adjacent = cos((h + 90) / 360 * 2 * M_PI); \
99 float opposite = sin((h + 90) / 360 * 2 * M_PI); \
100 int ix = vector_w / 2 + adjacent * (s) / (FLOAT_MAX) * radius; \
101 int y = vector_h / 2 - opposite * (s) / (FLOAT_MAX) * radius; \
102 CLAMP(ix, 0, vector_w - 1); \
103 CLAMP(y, 0, vector_h - 1); \
104 /* Get color with full saturation & value */ \
105 float r_f, g_f, b_f; \
106 HSV::hsv_to_rgb(r_f, g_f, b_f, h, s, 1); \
107 draw_point(vector_rows, ix, y, \
108 (int)(CLIP(r_f, 0, 1) * 255), \
109 (int)(CLIP(g_f, 0, 1) * 255), \
110 (int)(CLIP(b_f, 0, 1) * 255)); \
114 #define PROCESS_RGB_PIXEL(column, max) { \
115 r = (float)*row++ / max; \
116 g = (float)*row++ / max; \
117 b = (float)*row++ / max; \
118 HSV::rgb_to_hsv(r, g, b, h, s, v); \
120 PROCESS_PIXEL(column) \
123 #define PROCESS_BGR_PIXEL(column, max) { \
124 b = (float)*row++ / max; \
125 g = (float)*row++ / max; \
126 r = (float)*row++ / max; \
127 HSV::rgb_to_hsv(r, g, b, h, s, v); \
129 PROCESS_PIXEL(column) \
132 #define PROCESS_YUV_PIXEL(column, y_in, u_in, v_in) { \
133 YUV::yuv.yuv_to_rgb_f(r, g, b, (float)y_in / 255, (float)(u_in - 0x80) / 255, (float)(v_in - 0x80) / 255); \
134 HSV::rgb_to_hsv(r, g, b, h, s, v); \
136 PROCESS_PIXEL(column) \
139 void ScopeUnit::process_package(LoadPackage *package)
141 ScopePackage *pkg = (ScopePackage*)package;
146 int use_hist = gui->use_hist;
147 int use_hist_parade = gui->use_hist_parade;
148 int use_vector = gui->use_vector;
149 int use_wave = gui->use_wave;
150 int use_wave_parade = gui->use_wave_parade;
151 BC_Bitmap *waveform_bitmap = gui->waveform_bitmap;
152 BC_Bitmap *vector_bitmap = gui->vector_bitmap;
153 int wave_h = waveform_bitmap->get_h();
154 int wave_w = waveform_bitmap->get_w();
155 int vector_h = vector_bitmap->get_h();
156 int vector_w = vector_bitmap->get_w();
158 int w = gui->output_frame->get_w();
159 float radius = MIN(gui->vector_w / 2, gui->vector_h / 2);
160 unsigned char **waveform_rows = waveform_bitmap->get_row_pointers();
161 unsigned char **vector_rows = vector_bitmap->get_row_pointers();
162 unsigned char **rows = gui->output_frame->get_rows();
164 switch( gui->output_frame->get_color_model() ) {
166 for( int y=pkg->row1; y<pkg->row2; ++y ) {
167 unsigned char *row = rows[y];
168 for( int x=0; x<w; ++x ) {
169 PROCESS_RGB_PIXEL(x, 255)
174 for( int y=pkg->row1; y<pkg->row2; ++y ) {
175 unsigned char *row = rows[y];
176 for( int x=0; x<w; ++x ) {
177 PROCESS_RGB_PIXEL(x, 255)
183 for( int y=pkg->row1; y<pkg->row2; ++y ) {
184 unsigned char *row = rows[y];
185 for( int x=0; x<w; ++x ) {
186 PROCESS_BGR_PIXEL(x, 255)
191 for( int y=pkg->row1; y<pkg->row2; ++y ) {
192 unsigned char *row = rows[y];
193 for( int x=0; x<w; ++x ) {
194 PROCESS_BGR_PIXEL(x, 255)
200 for( int y=pkg->row1; y<pkg->row2; ++y ) {
201 float *row = (float*)rows[y];
202 for( int x=0; x<w; ++x ) {
203 PROCESS_RGB_PIXEL(x, 1.0)
208 for( int y=pkg->row1; y<pkg->row2; ++y ) {
209 float *row = (float*)rows[y];
210 for( int x=0; x<w; ++x ) {
211 PROCESS_RGB_PIXEL(x, 1.0)
217 for( int y=pkg->row1; y<pkg->row2; ++y ) {
218 unsigned char *row = rows[y];
219 for( int x=0; x<w; ++x ) {
220 PROCESS_YUV_PIXEL(x, row[0], row[1], row[2])
227 for( int y=pkg->row1; y<pkg->row2; ++y ) {
228 unsigned char *row = rows[y];
229 for( int x=0; x<w; ++x ) {
230 PROCESS_YUV_PIXEL(x, row[0], row[1], row[2])
236 unsigned char *yp = gui->output_frame->get_y();
237 unsigned char *up = gui->output_frame->get_u();
238 unsigned char *vp = gui->output_frame->get_v();
239 for( int y=pkg->row1; y<pkg->row2; ++y ) {
240 unsigned char *y_row = yp + y * w;
241 unsigned char *u_row = up + (y / 2) * (w / 2);
242 unsigned char *v_row = vp + (y / 2) * (w / 2);
243 for( int x=0; x<w; x+=2 ) {
244 PROCESS_YUV_PIXEL(x, *y_row, *u_row, *v_row); ++y_row;
245 PROCESS_YUV_PIXEL(x + 1, *y_row, *u_row, *v_row); ++y_row;
251 for( int y=pkg->row1; y<pkg->row2; ++y ) {
252 unsigned char *row = rows[y];
253 for( int x=0; x<w; x+=2 ) {
254 PROCESS_YUV_PIXEL(x, row[0], row[1], row[3]);
255 PROCESS_YUV_PIXEL(x + 1, row[2], row[1], row[3]);
262 printf("ScopeUnit::process_package %d: color_model=%d unrecognized\n",
263 __LINE__, gui->output_frame->get_color_model());
269 ScopeEngine::ScopeEngine(ScopeGUI *gui, int cpus)
270 : LoadServer(cpus, cpus)
272 //printf("ScopeEngine::ScopeEngine %d cpus=%d\n", __LINE__, cpus);
276 ScopeEngine::~ScopeEngine()
280 void ScopeEngine::init_packages()
282 int y = 0, h = gui->output_frame->get_h();
283 for( int i=0,n=LoadServer::get_total_packages(); i<n; ) {
284 ScopePackage *pkg = (ScopePackage*)get_package(i);
286 pkg->row2 = y = (++i * h) / n;
289 for( int i=0,n=LoadServer::get_total_packages(); i<n; ++i ) {
290 ScopeUnit *unit = (ScopeUnit*)get_client(i);
291 for( int j=0; j<HIST_SECTIONS; ++j )
292 bzero(unit->bins[j], sizeof(int) * TOTAL_BINS);
297 LoadClient* ScopeEngine::new_client()
299 return new ScopeUnit(gui, this);
302 LoadPackage* ScopeEngine::new_package()
304 return new ScopePackage;
307 void ScopeEngine::process()
311 for(int i = 0; i < HIST_SECTIONS; i++)
312 bzero(gui->bins[i], sizeof(int) * TOTAL_BINS);
314 for(int i=0,n=get_total_clients(); i<n; ++i ) {
315 ScopeUnit *unit = (ScopeUnit*)get_client(i);
316 for( int j=0; j<HIST_SECTIONS; ++j ) {
317 for( int k=0; k<TOTAL_BINS; ++k ) {
318 gui->bins[j][k] += unit->bins[j][k];
325 ScopeGUI::ScopeGUI(Theme *theme,
326 int x, int y, int w, int h, int cpus)
327 : PluginClientWindow(_(PROGRAM_NAME ": Scopes"),
328 x, y, w, h, MIN_SCOPE_W, MIN_SCOPE_H, 1)
339 ScopeGUI::ScopeGUI(PluginClient *plugin, int w, int h)
340 : PluginClientWindow(plugin, w, h, MIN_SCOPE_W, MIN_SCOPE_H, 1)
346 this->theme = plugin->get_theme();
347 this->cpus = plugin->PluginClient::smp + 1;
351 ScopeGUI::~ScopeGUI()
353 delete waveform_bitmap;
354 delete vector_bitmap;
358 void ScopeGUI::reset()
372 wave_w = wave_h = vector_w = vector_h = 0;
376 void ScopeGUI::create_objects()
378 if( use_hist && use_hist_parade )
380 if( use_wave && use_wave_parade )
382 if( !engine ) engine = new ScopeEngine(this, cpus);
384 lock_window("ScopeGUI::create_objects");
385 int x = theme->widget_border;
386 int y = theme->widget_border;
387 add_subwindow(hist_on = new ScopeToggle(this, x, y, &use_hist));
388 x += hist_on->get_w() + theme->widget_border;
390 add_subwindow(hist_parade_on = new ScopeToggle(this, x, y, &use_hist_parade));
391 x += hist_parade_on->get_w() + theme->widget_border;
393 add_subwindow(waveform_on = new ScopeToggle(this, x, y, &use_wave));
394 x += waveform_on->get_w() + theme->widget_border;
395 add_subwindow(waveform_parade_on = new ScopeToggle(this, x, y, &use_wave_parade));
396 x += waveform_parade_on->get_w() + theme->widget_border;
398 add_subwindow(vector_on = new ScopeToggle(this, x, y, &use_vector));
399 x += vector_on->get_w() + theme->widget_border;
401 add_subwindow(value_text = new BC_Title(x, y, ""));
402 x += value_text->get_w() + theme->widget_border;
404 y += vector_on->get_h() + theme->widget_border;
413 void ScopeGUI::create_panels()
415 calculate_sizes(get_w(), get_h());
416 if( (use_wave || use_wave_parade) ) {
418 add_subwindow(waveform = new ScopeWaveform(this,
419 wave_x, wave_y, wave_w, wave_h));
420 waveform->create_objects();
423 waveform->reposition_window(
424 wave_x, wave_y, wave_w, wave_h);
425 waveform->clear_box(0, 0, wave_w, wave_h);
428 else if( !(use_wave || use_wave_parade) && waveform ) {
429 delete waveform; waveform = 0;
434 add_subwindow(vectorscope = new ScopeVectorscope(this,
435 vector_x, vector_y, vector_w, vector_h));
436 vectorscope->create_objects();
439 vectorscope->reposition_window(
440 vector_x, vector_y, vector_w, vector_h);
441 vectorscope->clear_box(0, 0, vector_w, vector_h);
444 else if( !use_vector && vectorscope ) {
445 delete vectorscope; vectorscope = 0;
448 if( (use_hist || use_hist_parade) ) {
450 // printf("ScopeGUI::create_panels %d %d %d %d %d\n", __LINE__,
451 // hist_x, hist_y, hist_w, hist_h);
452 add_subwindow(histogram = new ScopeHistogram(this,
453 hist_x, hist_y, hist_w, hist_h));
454 histogram->create_objects();
457 histogram->reposition_window(
458 hist_x, hist_y, hist_w, hist_h);
459 histogram->clear_box(0, 0, hist_w, hist_h);
462 else if( !(use_hist || use_hist_parade) ) {
463 delete histogram; histogram = 0;
468 draw_overlays(1, 1, 0);
471 void ScopeGUI::clear_points(int flash)
474 histogram->clear_point();
476 waveform->clear_point();
478 vectorscope->clear_point();
479 if( histogram && flash )
481 if( waveform && flash )
483 if( vectorscope && flash )
484 vectorscope->flash(0);
487 void ScopeGUI::toggle_event()
491 void ScopeGUI::calculate_sizes(int w, int h)
493 int margin = theme->widget_border;
494 int text_w = get_text_width(SMALLFONT, "000") + margin * 2;
495 int total_panels = ((use_hist || use_hist_parade) ? 1 : 0) +
496 ((use_wave || use_wave_parade) ? 1 : 0) +
497 (use_vector ? 1 : 0);
500 int panel_w = (w - margin) / (total_panels > 0 ? total_panels : 1);
501 // Vectorscope determines the size of everything else
505 vector_x = w - panel_w + text_w;
506 vector_w = w - margin - vector_x;
507 vector_y = vector_on->get_h() + margin * 2;
508 vector_h = h - vector_y - margin;
510 if( vector_w > vector_h ) {
512 vector_x = w - theme->widget_border - vector_w;
516 panel_w = (vector_x - text_w - margin) / total_panels;
519 // Histogram is always 1st panel
520 if( use_hist || use_hist_parade ) {
522 hist_y = vector_on->get_h() + margin * 2;
523 hist_w = panel_w - margin;
524 hist_h = h - hist_y - margin;
530 if( use_wave || use_wave_parade ) {
532 wave_y = vector_on->get_h() + margin * 2;
533 wave_w = panel_w - margin - text_w;
534 wave_h = h - wave_y - margin;
540 void ScopeGUI::allocate_bitmaps()
542 if(waveform_bitmap) delete waveform_bitmap;
543 if(vector_bitmap) delete vector_bitmap;
546 //printf("ScopeGUI::allocate_bitmaps %d %d %d %d %d\n", __LINE__,
547 // wave_w, wave_h, vector_w, vector_h);
548 int xs16 = xS(16), ys16 = yS(16);
549 w = MAX(wave_w, xs16);
550 h = MAX(wave_h, ys16);
551 waveform_bitmap = new_bitmap(w, h);
552 w = MAX(vector_w, xs16);
553 h = MAX(vector_h, ys16);
554 vector_bitmap = new_bitmap(w, h);
558 int ScopeGUI::resize_event(int w, int h)
560 clear_box(0, 0, w, h);
563 calculate_sizes(w, h);
566 waveform->reposition_window(wave_x, wave_y, wave_w, wave_h);
567 waveform->clear_box(0, 0, wave_w, wave_h);
571 histogram->reposition_window(hist_x, hist_y, hist_w, hist_h);
572 histogram->clear_box(0, 0, hist_w, hist_h);
576 vectorscope->reposition_window(vector_x, vector_y, vector_w, vector_h);
577 vectorscope->clear_box(0, 0, vector_w, vector_h);
582 draw_overlays(1, 1, 1);
586 int ScopeGUI::translation_event()
590 PluginClientWindow::translation_event();
595 void ScopeGUI::draw_overlays(int overlays, int borders, int flush)
597 BC_Resources *resources = BC_WindowBase::get_resources();
598 int text_color = GREEN;
599 if( resources->bg_color == 0xffffff ) {
603 if( overlays && borders ) {
604 clear_box(0, 0, get_w(), get_h());
609 set_color(text_color);
612 if( histogram && (use_hist || use_hist_parade) ) {
613 histogram->draw_line(hist_w * -FLOAT_MIN / (FLOAT_MAX - FLOAT_MIN), 0,
614 hist_w * -FLOAT_MIN / (FLOAT_MAX - FLOAT_MIN), hist_h);
615 histogram->draw_line(hist_w * (1.0 - FLOAT_MIN) / (FLOAT_MAX - FLOAT_MIN), 0,
616 hist_w * (1.0 - FLOAT_MIN) / (FLOAT_MAX - FLOAT_MIN), hist_h);
618 histogram->draw_point();
624 if( waveform && (use_wave || use_wave_parade) ) {
625 set_color(text_color);
626 for( int i=0; i<=WAVEFORM_DIVISIONS; ++i ) {
627 int y = wave_h * i / WAVEFORM_DIVISIONS;
628 int text_y = y + wave_y + get_text_ascent(SMALLFONT) / 2;
629 CLAMP(text_y, waveform->get_y() + get_text_ascent(SMALLFONT), waveform->get_y() + waveform->get_h() - 1);
630 char string[BCTEXTLEN];
631 sprintf(string, "%d", (int)((FLOAT_MAX -
632 i * (FLOAT_MAX - FLOAT_MIN) / WAVEFORM_DIVISIONS) * 100));
633 int text_x = wave_x - get_text_width(SMALLFONT, string) - theme->widget_border;
634 draw_text(text_x, text_y, string);
636 CLAMP(y, 0, waveform->get_h() - 1);
637 waveform->draw_line(0, y, wave_w, y);
638 //waveform->draw_rectangle(0, 0, wave_w, wave_h);
641 waveform->draw_point();
647 // Vectorscope overlay
648 if( vectorscope && use_vector ) {
649 set_color(text_color);
650 int radius = MIN(vector_w / 2, vector_h / 2);
651 for( int i=1; i<=VECTORSCOPE_DIVISIONS; i+=2 ) {
652 int x = vector_w / 2 - radius * i / VECTORSCOPE_DIVISIONS;
653 int y = vector_h / 2 - radius * i / VECTORSCOPE_DIVISIONS;
654 int text_y = y + vector_y + get_text_ascent(SMALLFONT) / 2;
655 int w = radius * i / VECTORSCOPE_DIVISIONS * 2;
656 int h = radius * i / VECTORSCOPE_DIVISIONS * 2;
657 char string[BCTEXTLEN];
659 sprintf(string, "%d",
660 (int)((FLOAT_MAX / VECTORSCOPE_DIVISIONS * i) * 100));
661 int text_x = vector_x - get_text_width(SMALLFONT, string) - theme->widget_border;
662 draw_text(text_x, text_y, string);
663 //printf("ScopeGUI::draw_overlays %d %d %d %s\n", __LINE__, text_x, text_y, string);
665 vectorscope->draw_circle(x, y, w, h);
666 //vectorscope->draw_rectangle(0, 0, vector_w, vector_h);
668 // vectorscope->draw_circle(vector_w / 2 - radius,
669 // vector_h / 2 - radius,
674 vectorscope->draw_point();
676 vectorscope->flash(0);
679 set_font(MEDIUMFONT);
684 if( use_hist || use_hist_parade ) {
685 draw_3d_border(hist_x - 2, hist_y - 2, hist_w + 4, hist_h + 4,
686 get_bg_color(), BLACK, MDGREY, get_bg_color());
688 if( use_wave || use_wave_parade ) {
689 draw_3d_border(wave_x - 2, wave_y - 2, wave_w + 4, wave_h + 4,
690 get_bg_color(), BLACK, MDGREY, get_bg_color());
693 draw_3d_border(vector_x - 2, vector_y - 2, vector_w + 4, vector_h + 4,
694 get_bg_color(), BLACK, MDGREY, get_bg_color());
699 if(flush) this->flush();
704 void ScopeGUI::process(VFrame *output_frame)
706 lock_window("ScopeGUI::process");
707 this->output_frame = output_frame;
708 frame_w = output_frame->get_w();
709 //float radius = MIN(vector_w / 2, vector_h / 2);
710 bzero(waveform_bitmap->get_data(), waveform_bitmap->get_data_size());
711 bzero(vector_bitmap->get_data(), vector_bitmap->get_data_size());
715 histogram->draw(0, 0);
717 waveform->draw_bitmap(waveform_bitmap, 1, 0, 0);
719 vectorscope->draw_bitmap(vector_bitmap, 1, 0, 0);
721 draw_overlays(1, 0, 1);
726 void ScopeGUI::update_toggles()
728 hist_parade_on->update(use_hist_parade);
729 hist_on->update(use_hist);
730 waveform_parade_on->update(use_wave_parade);
731 waveform_on->update(use_wave);
732 vector_on->update(use_vector);
736 ScopePanel::ScopePanel(ScopeGUI *gui, int x, int y, int w, int h)
737 : BC_SubWindow(x, y, w, h, BLACK)
743 void ScopePanel::create_objects()
745 set_cursor(CROSS_CURSOR, 0, 0);
746 clear_box(0, 0, get_w(), get_h());
749 void ScopePanel::update_point(int x, int y)
753 void ScopePanel::draw_point()
757 void ScopePanel::clear_point()
761 int ScopePanel::button_press_event()
763 if( is_event_win() && cursor_inside() ) {
764 gui->clear_points(1);
766 int x = get_cursor_x();
767 int y = get_cursor_y();
768 CLAMP(x, 0, get_w() - 1);
769 CLAMP(y, 0, get_h() - 1);
777 int ScopePanel::cursor_motion_event()
780 int x = get_cursor_x();
781 int y = get_cursor_y();
782 CLAMP(x, 0, get_w() - 1);
783 CLAMP(y, 0, get_h() - 1);
791 int ScopePanel::button_release_event()
801 ScopeWaveform::ScopeWaveform(ScopeGUI *gui,
802 int x, int y, int w, int h)
803 : ScopePanel(gui, x, y, w, h)
809 void ScopeWaveform::update_point(int x, int y)
814 int frame_x = x * gui->frame_w / get_w();
816 if( gui->use_wave_parade ) {
817 if( x > get_w() / 3 * 2 )
818 frame_x = (x - get_w() / 3 * 2) * gui->frame_w / (get_w() / 3);
819 else if( x > get_w() / 3 )
820 frame_x = (x - get_w() / 3) * gui->frame_w / (get_w() / 3);
822 frame_x = x * gui->frame_w / (get_w() / 3);
825 float value = ((float)get_h() - y) / get_h() * (FLOAT_MAX - FLOAT_MIN) + FLOAT_MIN;
827 char string[BCTEXTLEN];
828 sprintf(string, "X: %d Value: %.3f", frame_x, value);
829 gui->value_text->update(string, 0);
835 void ScopeWaveform::draw_point()
841 draw_line(0, drag_y, get_w(), drag_y);
842 draw_line(drag_x, 0, drag_x, get_h());
848 void ScopeWaveform::clear_point()
855 ScopeVectorscope::ScopeVectorscope(ScopeGUI *gui,
856 int x, int y, int w, int h)
857 : ScopePanel(gui, x, y, w, h)
863 void ScopeVectorscope::clear_point()
871 void ScopeVectorscope::update_point(int x, int y)
876 int radius = MIN(get_w() / 2, get_h() / 2);
877 drag_radius = sqrt(SQR(x - get_w() / 2) + SQR(y - get_h() / 2));
878 drag_angle = atan2(y - get_h() / 2, x - get_w() / 2);
880 drag_radius = MIN(drag_radius, radius);
882 float saturation = (float)drag_radius / radius * FLOAT_MAX;
883 float hue = -drag_angle * 360 / 2 / M_PI - 90;
884 if( hue < 0 ) hue += 360;
886 char string[BCTEXTLEN];
887 sprintf(string, "Hue: %.3f Sat: %.3f", hue, saturation);
888 gui->value_text->update(string, 0);
895 void ScopeVectorscope::draw_point()
897 if( drag_radius > 0 ) {
898 int radius = MIN(get_w() / 2, get_h() / 2);
902 draw_circle(get_w() / 2 - drag_radius, get_h() / 2 - drag_radius,
903 drag_radius * 2, drag_radius * 2);
904 draw_line(get_w() / 2, get_h() / 2,
905 get_w() / 2 + radius * cos(drag_angle),
906 get_h() / 2 + radius * sin(drag_angle));
914 ScopeHistogram::ScopeHistogram(ScopeGUI *gui,
915 int x, int y, int w, int h)
916 : ScopePanel(gui, x, y, w, h)
921 void ScopeHistogram::clear_point()
928 void ScopeHistogram::draw_point()
934 draw_line(drag_x, 0, drag_x, get_h());
940 void ScopeHistogram::update_point(int x, int y)
944 float value = (float)x / get_w() * (FLOAT_MAX - FLOAT_MIN) + FLOAT_MIN;
946 char string[BCTEXTLEN];
947 sprintf(string, "Value: %.3f", value);
948 gui->value_text->update(string, 0);
956 void ScopeHistogram::draw_mode(int mode, int color, int y, int h)
958 // Highest of all bins
960 for( int i=0; i<TOTAL_BINS; ++i ) {
961 if(gui->bins[mode][i] > normalize) normalize = gui->bins[mode][i];
964 for( int i=0; i<get_w(); ++i ) {
965 int accum_start = (int)(i * TOTAL_BINS / get_w());
966 int accum_end = (int)((i + 1) * TOTAL_BINS / get_w());
967 CLAMP(accum_start, 0, TOTAL_BINS);
968 CLAMP(accum_end, 0, TOTAL_BINS);
970 for(int k=accum_start; k<accum_end; ++k ) {
971 max = MAX(gui->bins[mode][k], max);
973 // max = max * h / normalize;
974 max = (int)(log(max) / log(normalize) * h);
975 draw_line(i, y + h - max, i, y + h);
979 void ScopeHistogram::draw(int flash, int flush)
981 clear_box(0, 0, get_w(), get_h());
983 if( gui->use_hist_parade ) {
984 draw_mode(0, 0xff0000, 0, get_h() / 3);
985 draw_mode(1, 0x00ff00, get_h() / 3, get_h() / 3);
986 draw_mode(2, 0x0000ff, get_h() / 3 * 2, get_h() / 3);
989 draw_mode(3, LTGREY, 0, get_h());
992 if(flash) this->flash(0);
993 if(flush) this->flush();
996 ScopeToggle::ScopeToggle(ScopeGUI *gui, int x, int y, int *value)
997 : BC_Toggle(x, y, get_image_set(gui, value), *value)
1000 this->value = value;
1001 if( value == &gui->use_hist_parade ) {
1002 set_tooltip(_("Histogram Parade"));
1004 else if( value == &gui->use_hist )
1006 set_tooltip(_("Histogram"));
1008 else if( value == &gui->use_wave_parade ) {
1009 set_tooltip(_("Waveform Parade"));
1011 else if( value == &gui->use_wave ) {
1012 set_tooltip(_("Waveform"));
1015 set_tooltip(_("Vectorscope"));
1019 VFrame** ScopeToggle::get_image_set(ScopeGUI *gui, int *value)
1021 if( value == &gui->use_hist_parade ) {
1022 return gui->theme->get_image_set("histogram_rgb_toggle");
1024 else if( value == &gui->use_hist ) {
1025 return gui->theme->get_image_set("histogram_toggle");
1027 else if( value == &gui->use_wave_parade ) {
1028 return gui->theme->get_image_set("waveform_rgb_toggle");
1030 else if( value == &gui->use_wave ) {
1031 return gui->theme->get_image_set("waveform_toggle");
1034 return gui->theme->get_image_set("scope_toggle");
1038 int ScopeToggle::handle_event()
1040 *value = get_value();
1041 if( value == &gui->use_hist_parade ) {
1042 if( get_value() ) gui->use_hist = 0;
1044 else if( value == &gui->use_hist )
1046 if( get_value() ) gui->use_hist_parade = 0;
1048 else if( value == &gui->use_wave_parade ) {
1049 if( get_value() ) gui->use_wave = 0;
1051 else if( value == &gui->use_wave ) {
1052 if( get_value() ) gui->use_wave_parade = 0;
1054 gui->toggle_event();
1055 gui->update_toggles();
1056 gui->create_panels();