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"
29 #include "rotateframe.h"
36 BC_Pan::BC_Pan(int x, int y, int virtual_r,
37 float maxvalue, int total_values, int *value_positions,
38 int stick_x, int stick_y, float *values)
39 : BC_SubWindow(x, y, -1, -1, -1)
41 this->virtual_r = virtual_r;
42 this->maxvalue = maxvalue;
43 this->total_values = total_values;
44 this->values = new float[total_values];
45 memcpy(this->values, values, sizeof(float) * total_values);
46 this->value_positions = new int[total_values];
47 memcpy(this->value_positions, value_positions, sizeof(int) * total_values);
48 this->value_x = new int[total_values];
49 this->value_y = new int[total_values];
50 this->stick_x = stick_x;
51 this->stick_y = stick_y;
52 get_channel_positions(value_x,
57 if(stick_x < 0 || stick_y < 0)
58 calculate_stick_position(total_values,
70 memset(images, 0, sizeof(BC_Pixmap*) * PAN_IMAGES);
76 delete [] value_positions;
82 for( int i=0; i<PAN_IMAGES; ++i )
84 //printf("BC_Pan::~BC_Pan 2\n");
87 int BC_Pan::initialize()
89 set_images(get_resources()->pan_data);
91 BC_SubWindow::initialize();
92 temp_channel = new VFrame;
93 temp_channel->set_use_shm(0);
94 temp_channel->reallocate(0,
99 get_resources()->pan_data[PAN_CHANNEL]->get_w(),
100 get_resources()->pan_data[PAN_CHANNEL]->get_h(),
101 get_resources()->pan_data[PAN_CHANNEL]->get_color_model(),
107 void BC_Pan::set_images(VFrame **data)
109 for(int i = 0; i < PAN_IMAGES; i++)
111 if(images[i]) delete images[i];
112 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
114 w = images[PAN_UP]->get_w();
115 h = images[PAN_UP]->get_h();
118 int BC_Pan::button_press_event()
120 // there are two modes of operation...
122 { if (popup->is_event_win() && get_button_down() && get_buttonpress() == 1)
125 x_origin = popup->get_cursor_x();
126 y_origin = popup->get_cursor_y();
127 stick_x_origin = stick_x;
128 stick_y_origin = stick_y;
136 if(is_event_win() && get_button_down() && get_buttonpress() == 1)
141 x_origin = get_cursor_x();
142 y_origin = get_cursor_y();
143 stick_x_origin = stick_x;
144 stick_y_origin = stick_y;
151 int BC_Pan::cursor_motion_event()
153 if(popup && get_button_down() && get_buttonpress() == 1)
155 stick_x = stick_x_origin + get_cursor_x() - x_origin;
156 stick_y = stick_y_origin + get_cursor_y() - y_origin;
157 CLAMP(stick_x, 0, virtual_r * 2);
158 CLAMP(stick_y, 0, virtual_r * 2);
167 int BC_Pan::button_release_event()
179 int BC_Pan::repeat_event(int64_t duration)
181 if( highlighted && !active &&
182 tooltip_text && tooltip_text[0] != 0 &&
183 duration == top_level->get_resources()->tooltip_delay )
191 int BC_Pan::cursor_enter_event()
193 if(is_event_win() && !highlighted)
201 int BC_Pan::cursor_leave_event()
214 int BC_Pan::deactivate()
216 delete popup; popup = 0;
217 delete rotater; rotater = 0;
222 int BC_Pan::activate(int popup_x, int popup_y)
228 if (popup_x < 0 || popup_y < 0)
230 XTranslateCoordinates(top_level->display,
239 x -= (images[PAN_POPUP]->get_w() - get_w()) / 2;
240 y -= (images[PAN_POPUP]->get_h() - get_h()) / 2;
244 XTranslateCoordinates(top_level->display,
245 top_level->win, top_level->rootwin,
246 popup_x, popup_y, &x, &y, &tempwin);
247 x -= images[PAN_POPUP]->get_w() / 2;
248 y -= images[PAN_POPUP]->get_h() / 2;
252 rotater = new RotateFrame(1,
253 get_resources()->pan_data[PAN_CHANNEL]->get_w(),
254 get_resources()->pan_data[PAN_CHANNEL]->get_h());
257 popup = new BC_Popup(this, x, y,
258 images[PAN_POPUP]->get_w(),
259 images[PAN_POPUP]->get_h(),
260 0, 0, images[PAN_POPUP]);
266 int BC_Pan::update(int x, int y)
268 if(x != stick_x || y != stick_y)
278 void BC_Pan::draw_popup()
280 popup->draw_background(0, 0, popup->get_w(), popup->get_h());
284 float scale = (float)(popup->get_w() -
285 get_resources()->pan_data[PAN_CHANNEL]->get_w()) /
287 set_color(get_resources()->pan_text_color);
290 for(int i = 0; i < total_values; i++)
292 x1 = (int)(value_x[i] * scale);
293 y1 = (int)(value_y[i] * scale);
294 rotate_angle = value_positions[i];
295 rotate_angle = -rotate_angle;
296 while(rotate_angle < 0) rotate_angle += 360;
297 rotater->rotate(temp_channel,
298 get_resources()->pan_data[PAN_CHANNEL],
301 BC_Pixmap *temp_pixmap = new BC_Pixmap(popup,
304 popup->draw_pixmap(temp_pixmap, x1, y1);
307 char string[BCTEXTLEN];
308 float value = values[i] + 0.005;
309 sprintf(string, "%.1f", value);
310 popup->draw_text(x1, y1 + get_text_height(SMALLFONT), string);
313 x1 = (int)(stick_x * scale);
314 y1 = (int)(stick_y * scale);
315 popup->draw_pixmap(images[PAN_STICK], x1, y1);
322 void BC_Pan::draw(int flash, int flush)
324 draw_top_background(parent_window, 0, 0, w, h);
326 draw_pixmap(images[highlighted ? PAN_HI : PAN_UP]);
327 get_channel_positions(value_x,
335 float scale = (float)(get_w() - PICON_W) / (virtual_r * 2);
338 for(int i = 0; i < total_values; i++)
340 // printf("BC_Pan::draw 1 %d %d %d %d\n",
342 // value_positions[i],
345 x1 = (int)(value_x[i] * scale);
346 y1 = (int)(value_y[i] * scale);
347 //printf("BC_Pan::draw 2 %d %d\n", x1, y1);
348 CLAMP(x1, 0, get_w() - PICON_W);
349 CLAMP(y1, 0, get_h() - PICON_H);
350 draw_pixmap(images[PAN_CHANNEL_SMALL], x1, y1);
351 // draw_box(x1, y1, PICON_W, PICON_H);
356 x1 = (int)(stick_x * scale);
357 y1 = (int)(stick_y * scale);
359 //printf("BC_Pan::draw 2 %d %d\n", x1, y1);
360 CLAMP(x1, 0, get_w() - PICON_W);
361 CLAMP(y1, 0, get_h() - PICON_H);
363 draw_pixmap(images[PAN_STICK_SMALL], x1, y1);
364 // x2 = x1 + PICON_W;
365 // y2 = y1 + PICON_H;
366 // draw_line(x1, y1, x2, y2);
367 // draw_line(x2, y1, x1, y2);
369 if(flash) this->flash(0);
370 if(flush) this->flush();
373 int BC_Pan::stick_to_values()
375 return stick_to_values(values,
384 int BC_Pan::stick_to_values(float *values,
386 int *value_positions,
392 // find shortest distance to a channel
393 float shortest = 2 * virtual_r, test_distance;
395 int *value_x = new int[total_values];
396 int *value_y = new int[total_values];
398 get_channel_positions(value_x, value_y, value_positions, virtual_r, total_values);
399 for(i = 0; i < total_values; i++)
401 if((test_distance = distance(stick_x,
404 value_y[i])) < shortest)
405 shortest = test_distance;
408 // get values for channels
411 for(i = 0; i < total_values; i++)
413 if(distance(stick_x, value_x[i], stick_y, value_y[i]) == shortest)
414 values[i] = maxvalue;
421 for(i = 0; i < total_values; i++)
423 values[i] = shortest;
424 values[i] -= (float)(distance(stick_x,
427 value_y[i]) - shortest);
428 if(values[i] < 0) values[i] = 0;
429 values[i] = values[i] / shortest * maxvalue;
433 for(i = 0; i < total_values; i++)
435 values[i] = Units::quantize10(values[i]);
444 float BC_Pan::distance(int x1, int x2, int y1, int y2)
446 return hypot(x2 - x1, y2 - y1);
449 int BC_Pan::change_channels(int new_channels, int *value_positions)
452 delete this->value_positions;
456 values = new float[new_channels];
457 this->value_positions = new int[new_channels];
458 value_x = new int[new_channels];
459 value_y = new int[new_channels];
460 total_values = new_channels;
461 for(int i = 0; i < new_channels; i++)
463 this->value_positions[i] = value_positions[i];
465 get_channel_positions(value_x,
475 int BC_Pan::get_channel_positions(int *value_x,
477 int *value_positions,
481 for(int i = 0; i < total_values; i++)
483 rdtoxy(value_x[i], value_y[i], value_positions[i], virtual_r);
488 int BC_Pan::get_total_values()
493 float BC_Pan::get_value(int channel)
495 return values[channel];
498 int BC_Pan::get_stick_x()
503 int BC_Pan::get_stick_y()
508 float* BC_Pan::get_values()
513 int BC_Pan::rdtoxy(int &x, int &y, int a, int virtual_r)
515 float radians = (float)a / 360 * 2 * M_PI;
517 y = (int)(sin(radians) * virtual_r);
518 x = (int)(cos(radians) * virtual_r);
524 void BC_Pan::calculate_stick_position(int total_values,
525 int *value_positions,
532 // If 2 channels have positive values, use weighted average
536 for(int i = 0; i < total_values; i++)
538 if(values[i] > 0.001)
540 if(channel1 < 0) channel1 = i;
542 if(channel2 < 0) channel2 = i;
548 if(channel1 >= 0 && channel2 >= 0)
551 rdtoxy(x1, y1, value_positions[channel1], virtual_r);
552 rdtoxy(x2, y2, value_positions[channel2], virtual_r);
553 stick_x = (x1 + x2) / 2;
554 stick_y = (y1 + y2) / 2;
559 // use highest value as location of stick
560 float highest_value = 0;
563 for(int i = 0; i < total_values; i++)
565 if(values[i] > highest_value)
567 highest_value = values[i];
568 angle = value_positions[i];
571 rdtoxy(stick_x, stick_y, angle, virtual_r);