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, -1, 0, 0, 0,
95 get_resources()->pan_data[PAN_CHANNEL]->get_w(),
96 get_resources()->pan_data[PAN_CHANNEL]->get_h(),
97 get_resources()->pan_data[PAN_CHANNEL]->get_color_model(),
103 void BC_Pan::set_images(VFrame **data)
105 for(int i = 0; i < PAN_IMAGES; i++)
107 if(images[i]) delete images[i];
108 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
110 w = images[PAN_UP]->get_w();
111 h = images[PAN_UP]->get_h();
114 int BC_Pan::button_press_event()
116 // there are two modes of operation...
118 { if (popup->is_event_win() && get_button_down() && get_buttonpress() == 1)
121 x_origin = popup->get_cursor_x();
122 y_origin = popup->get_cursor_y();
123 stick_x_origin = stick_x;
124 stick_y_origin = stick_y;
132 if(is_event_win() && get_button_down() && get_buttonpress() == 1)
137 x_origin = get_cursor_x();
138 y_origin = get_cursor_y();
139 stick_x_origin = stick_x;
140 stick_y_origin = stick_y;
147 int BC_Pan::cursor_motion_event()
149 if(popup && get_button_down() && get_buttonpress() == 1)
151 stick_x = stick_x_origin + get_cursor_x() - x_origin;
152 stick_y = stick_y_origin + get_cursor_y() - y_origin;
153 CLAMP(stick_x, 0, virtual_r * 2);
154 CLAMP(stick_y, 0, virtual_r * 2);
163 int BC_Pan::button_release_event()
175 int BC_Pan::repeat_event(int64_t duration)
177 if( highlighted && !active &&
178 tooltip_text && tooltip_text[0] != 0 &&
179 duration == top_level->get_resources()->tooltip_delay )
187 int BC_Pan::cursor_enter_event()
189 if(is_event_win() && !highlighted)
197 int BC_Pan::cursor_leave_event()
210 int BC_Pan::deactivate()
212 delete popup; popup = 0;
213 delete rotater; rotater = 0;
218 int BC_Pan::activate(int popup_x, int popup_y)
224 if (popup_x < 0 || popup_y < 0)
226 XTranslateCoordinates(top_level->display, win,
227 top_level->rootwin, 0, 0, &x, &y, &tempwin);
229 x -= (images[PAN_POPUP]->get_w() - get_w()) / 2;
230 y -= (images[PAN_POPUP]->get_h() - get_h()) / 2;
234 XTranslateCoordinates(top_level->display,
235 top_level->win, top_level->rootwin,
236 popup_x, popup_y, &x, &y, &tempwin);
237 x -= images[PAN_POPUP]->get_w() / 2;
238 y -= images[PAN_POPUP]->get_h() / 2;
242 rotater = new RotateFrame(1,
243 get_resources()->pan_data[PAN_CHANNEL]->get_w(),
244 get_resources()->pan_data[PAN_CHANNEL]->get_h());
247 popup = new BC_Popup(this, x, y,
248 images[PAN_POPUP]->get_w(),
249 images[PAN_POPUP]->get_h(),
250 0, 0, images[PAN_POPUP]);
256 int BC_Pan::update(int x, int y)
258 if(x != stick_x || y != stick_y)
268 void BC_Pan::draw_popup()
270 popup->draw_background(0, 0, popup->get_w(), popup->get_h());
274 float scale = (float)(popup->get_w() -
275 get_resources()->pan_data[PAN_CHANNEL]->get_w()) /
277 set_color(get_resources()->pan_text_color);
280 for(int i = 0; i < total_values; i++)
282 x1 = (int)(value_x[i] * scale);
283 y1 = (int)(value_y[i] * scale);
284 rotate_angle = value_positions[i];
285 rotate_angle = -rotate_angle;
286 while(rotate_angle < 0) rotate_angle += 360;
287 rotater->rotate(temp_channel,
288 get_resources()->pan_data[PAN_CHANNEL],
291 BC_Pixmap *temp_pixmap = new BC_Pixmap(popup,
294 popup->draw_pixmap(temp_pixmap, x1, y1);
297 char string[BCTEXTLEN];
298 float value = values[i] + 0.005;
299 sprintf(string, "%.1f", value);
300 popup->draw_text(x1, y1 + get_text_height(SMALLFONT), string);
303 x1 = (int)(stick_x * scale);
304 y1 = (int)(stick_y * scale);
305 popup->draw_pixmap(images[PAN_STICK], x1, y1);
309 #define PICON_W xS(6)
310 #define PICON_H yS(6)
312 void BC_Pan::draw(int flash, int flush)
314 draw_top_background(parent_window, 0, 0, w, h);
316 draw_pixmap(images[highlighted ? PAN_HI : PAN_UP]);
317 get_channel_positions(value_x,
325 float scale = (float)(get_w() - PICON_W) / (virtual_r * 2);
328 for(int i = 0; i < total_values; i++)
330 // printf("BC_Pan::draw 1 %d %d %d %d\n",
332 // value_positions[i],
335 x1 = (int)(value_x[i] * scale);
336 y1 = (int)(value_y[i] * scale);
337 //printf("BC_Pan::draw 2 %d %d\n", x1, y1);
338 CLAMP(x1, 0, get_w() - PICON_W);
339 CLAMP(y1, 0, get_h() - PICON_H);
340 draw_pixmap(images[PAN_CHANNEL_SMALL], x1, y1);
341 // draw_box(x1, y1, PICON_W, PICON_H);
346 x1 = (int)(stick_x * scale);
347 y1 = (int)(stick_y * scale);
349 //printf("BC_Pan::draw 2 %d %d\n", x1, y1);
350 CLAMP(x1, 0, get_w() - PICON_W);
351 CLAMP(y1, 0, get_h() - PICON_H);
353 draw_pixmap(images[PAN_STICK_SMALL], x1, y1);
354 // x2 = x1 + PICON_W;
355 // y2 = y1 + PICON_H;
356 // draw_line(x1, y1, x2, y2);
357 // draw_line(x2, y1, x1, y2);
359 if(flash) this->flash(0);
360 if(flush) this->flush();
363 int BC_Pan::stick_to_values()
365 return stick_to_values(values,
374 int BC_Pan::stick_to_values(float *values,
376 int *value_positions,
382 // find shortest distance to a channel
383 float shortest = 2 * virtual_r, test_distance;
385 int *value_x = new int[total_values];
386 int *value_y = new int[total_values];
388 get_channel_positions(value_x, value_y, value_positions, virtual_r, total_values);
389 for(i = 0; i < total_values; i++)
391 if((test_distance = distance(stick_x,
394 value_y[i])) < shortest)
395 shortest = test_distance;
398 // get values for channels
401 for(i = 0; i < total_values; i++)
403 if(distance(stick_x, value_x[i], stick_y, value_y[i]) == shortest)
404 values[i] = maxvalue;
411 for(i = 0; i < total_values; i++)
413 values[i] = shortest;
414 values[i] -= (float)(distance(stick_x,
417 value_y[i]) - shortest);
418 if(values[i] < 0) values[i] = 0;
419 values[i] = values[i] / shortest * maxvalue;
423 for(i = 0; i < total_values; i++)
425 values[i] = Units::quantize10(values[i]);
434 float BC_Pan::distance(int x1, int x2, int y1, int y2)
436 return hypot(x2 - x1, y2 - y1);
439 int BC_Pan::change_channels(int new_channels, int *value_positions)
442 delete this->value_positions;
446 values = new float[new_channels];
447 this->value_positions = new int[new_channels];
448 value_x = new int[new_channels];
449 value_y = new int[new_channels];
450 total_values = new_channels;
451 for(int i = 0; i < new_channels; i++)
453 this->value_positions[i] = value_positions[i];
455 get_channel_positions(value_x,
465 int BC_Pan::get_channel_positions(int *value_x,
467 int *value_positions,
471 for(int i = 0; i < total_values; i++)
473 rdtoxy(value_x[i], value_y[i], value_positions[i], virtual_r);
478 int BC_Pan::get_total_values()
483 float BC_Pan::get_value(int channel)
485 return values[channel];
488 int BC_Pan::get_stick_x()
493 int BC_Pan::get_stick_y()
498 float* BC_Pan::get_values()
503 int BC_Pan::rdtoxy(int &x, int &y, int a, int virtual_r)
505 float radians = (float)a / 360 * 2 * M_PI;
507 y = (int)(sin(radians) * virtual_r);
508 x = (int)(cos(radians) * virtual_r);
514 void BC_Pan::calculate_stick_position(int total_values,
515 int *value_positions,
522 // If 2 channels have positive values, use weighted average
526 for(int i = 0; i < total_values; i++)
528 if(values[i] > 0.001)
530 if(channel1 < 0) channel1 = i;
532 if(channel2 < 0) channel2 = i;
538 if(channel1 >= 0 && channel2 >= 0)
541 rdtoxy(x1, y1, value_positions[channel1], virtual_r);
542 rdtoxy(x2, y2, value_positions[channel2], virtual_r);
543 stick_x = (x1 + x2) / 2;
544 stick_y = (y1 + y2) / 2;
549 // use highest value as location of stick
550 float highest_value = 0;
553 for(int i = 0; i < total_values; i++)
555 if(values[i] > highest_value)
557 highest_value = values[i];
558 angle = value_positions[i];
561 rdtoxy(stick_x, stick_y, angle, virtual_r);