no longer need ffmpeg patch0 which was for Termux
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcpot.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "bcpot.h"
23 #include "bcresources.h"
24 #include "bccolors.h"
25 #include "keys.h"
26 #include "units.h"
27 #include "vframe.h"
28
29 #include <ctype.h>
30 #include <math.h>
31 #include <string.h>
32 #define MIN_ANGLE 225
33 #define MAX_ANGLE -45
34
35 BC_Pot::BC_Pot(int x, int y, VFrame **data)
36  : BC_SubWindow(x, y, -1, -1, -1)
37 {
38         this->data = data;
39         for(int i = 0; i < POT_STATES; i++)
40                 images[i] = 0;
41         use_caption = 1;
42         enabled = 1;
43 }
44
45 BC_Pot::~BC_Pot()
46 {
47         for(int i = 0; i < POT_STATES; i++)
48                 if(images[i]) delete images[i];
49 }
50
51 int BC_Pot::calculate_h()
52 {
53         return BC_WindowBase::get_resources()->pot_images[0]->get_h();
54 }
55
56 int BC_Pot::calculate_w()
57 {
58         return BC_WindowBase::get_resources()->pot_images[0]->get_w();
59 }
60
61 int BC_Pot::initialize()
62 {
63         if(!data)
64         {
65                 data = get_resources()->pot_images;
66         }
67
68         status = POT_UP;
69         set_data(data);
70         w = data[0]->get_w();
71         h = data[0]->get_h();
72         BC_SubWindow::initialize();
73         draw(0);
74         return 0;
75 }
76
77 int BC_Pot::reposition_window(int x, int y)
78 {
79         BC_WindowBase::reposition_window(x, y);
80         draw(0);
81         return 0;
82 }
83
84 int BC_Pot::set_data(VFrame **data)
85 {
86         for(int i = 0; i < POT_STATES; i++)
87                 if(images[i]) delete images[i];
88
89         for(int i = 0; i < POT_STATES; i++)
90                 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
91         return 0;
92 }
93
94
95 void BC_Pot::set_use_caption(int value)
96 {
97         use_caption = value;
98 }
99
100
101 void BC_Pot::enable()
102 {
103         enabled = 1;
104         draw(1);
105 }
106
107 void BC_Pot::disable()
108 {
109         enabled = 0;
110         draw(1);
111 }
112
113
114 int BC_Pot::draw(int flush)
115 {
116         int x1, y1, x2, y2;
117         draw_top_background(parent_window, 0, 0, get_w(), get_h());
118         draw_pixmap(images[status]);
119         set_color(get_resources()->pot_needle_color);
120
121         angle_to_coords(x1, y1, x2, y2, percentage_to_angle(get_percentage()));
122         draw_line(x1, y1, x2, y2);
123
124         flash(flush);
125         return 0;
126 }
127
128 float BC_Pot::percentage_to_angle(float percentage)
129 {
130         return percentage * (MAX_ANGLE - MIN_ANGLE) + MIN_ANGLE;
131 }
132
133 float BC_Pot::angle_to_percentage(float angle)
134 {
135         return (angle - MIN_ANGLE) / (MAX_ANGLE - MIN_ANGLE);
136 }
137
138
139 int BC_Pot::angle_to_coords(int &x1, int &y1, int &x2, int &y2, float angle)
140 {
141         BC_Resources *resources = get_resources();
142         x1 = resources->pot_x1;
143         y1 = resources->pot_y1;
144         if(status == POT_DN)
145         {
146                 x1 += xS(resources->pot_offset);
147                 y1 += yS(resources->pot_offset);
148         }
149
150         while(angle < 0) angle += 360;
151
152         x2 = (int)(cos(angle / 360 * (2 * M_PI)) * resources->pot_r + x1);
153         y2 = (int)(-sin(angle / 360 * (2 * M_PI)) * resources->pot_r + y1);
154         return 0;
155 }
156
157 float BC_Pot::coords_to_angle(int x2, int y2)
158 {
159         int x1, y1, x, y;
160         float angle = 0.;
161
162         x1 = get_resources()->pot_x1;
163         y1 = get_resources()->pot_y1;
164         if(status == POT_DN)
165         {
166                 x1 += 2;
167                 y1 += 2;
168         }
169
170         x = x2 - x1;
171         y = y2 - y1;
172
173         if(x > 0 && y <= 0)
174         {
175                 angle = atan((float)-y / x) / (2 * M_PI) * 360;
176         }
177         else
178         if(x < 0 && y <= 0)
179         {
180                 angle = 180 - atan((float)-y / -x) / (2 * M_PI) * 360;
181         }
182         else
183         if(x < 0 && y > 0)
184         {
185                 angle = 180 - atan((float)-y / -x) / (2 * M_PI) * 360;
186         }
187         else
188         if(x > 0 && y > 0)
189         {
190                 angle = 360 + atan((float)-y / x) / (2 * M_PI) * 360;
191         }
192         else
193         if(x == 0 && y < 0)
194         {
195                 angle = 90;
196         }
197         else
198         if(x == 0 && y > 0)
199         {
200                 angle = 270;
201         }
202         else
203         if(x == 0 && y == 0)
204         {
205                 angle = 0;
206         }
207
208         return angle;
209 }
210
211
212
213
214 void BC_Pot::show_value_tooltip()
215 {
216         if(use_caption)
217         {
218                 set_tooltip(get_caption());
219                 show_tooltip(50);
220                 keypress_tooltip_timer = 2000;
221         }
222 }
223
224 int BC_Pot::repeat_event(int64_t duration)
225 {
226         if(duration == top_level->get_resources()->tooltip_delay)
227         {
228                 if(tooltip_on)
229                 {
230                         if(keypress_tooltip_timer > 0)
231                         {
232                                 keypress_tooltip_timer -= get_resources()->tooltip_delay;
233                         }
234                         else
235                         if(status != POT_HIGH && status != POT_DN)
236                         {
237                                 hide_tooltip();
238                         }
239                 }
240                 else
241                 if(status == POT_HIGH)
242                 {
243                         if(use_caption && tooltip_text)
244                         {
245                                 if(!tooltip_text[0] || isdigit(tooltip_text[0]))
246                                 {
247                                         set_tooltip(get_caption());
248                                         show_tooltip(50);
249                                 }
250                                 else
251                                         show_tooltip();
252                         }
253                         return 1;
254                 }
255         }
256         return 0;
257 }
258
259 int BC_Pot::keypress_event()
260 {
261         int result = 0;
262         switch(get_keypress())
263         {
264                 case UP:
265                         increase_value();
266                         result = 1;
267                         break;
268                 case DOWN:
269                         decrease_value();
270                         result = 1;
271                         break;
272                 case LEFT:
273                         decrease_value();
274                         result = 1;
275                         break;
276                 case RIGHT:
277                         increase_value();
278                         result = 1;
279                         break;
280         }
281
282         if(result)
283         {
284                 show_value_tooltip();
285                 draw(1);
286                 handle_event();
287         }
288         return result;
289 }
290
291 int BC_Pot::cursor_enter_event()
292 {
293         if(top_level->event_win == win && enabled)
294         {
295                 if(!top_level->button_down && status == POT_UP)
296                 {
297                         status = POT_HIGH;
298                 }
299                 draw(1);
300         }
301         return 0;
302 }
303
304 int BC_Pot::cursor_leave_event()
305 {
306         if(status == POT_HIGH)
307         {
308                 status = POT_UP;
309                 draw(1);
310                 hide_tooltip();
311         }
312         return 0;
313 }
314
315 int BC_Pot::button_press_event()
316 {
317         if(!tooltip_on) top_level->hide_tooltip();
318         if(top_level->event_win == win && enabled)
319         {
320                 if(status == POT_HIGH || status == POT_UP)
321                 {
322                         if(get_buttonpress() == 4)
323                         {
324                                 increase_value();
325                                 show_value_tooltip();
326                                 draw(1);
327                                 handle_event();
328                         }
329                         else
330                         if(get_buttonpress() == 5)
331                         {
332                                 decrease_value();
333                                 show_value_tooltip();
334                                 draw(1);
335                                 handle_event();
336                         }
337                         else
338                         {
339                                 status = POT_DN;
340                                 start_cursor_angle = coords_to_angle(get_cursor_x(), get_cursor_y());
341                                 start_needle_angle = percentage_to_angle(get_percentage());
342                                 angle_offset = start_cursor_angle - start_needle_angle;
343                                 prev_angle = start_cursor_angle;
344                                 angle_correction = 0;
345                                 draw(1);
346                                 top_level->deactivate();
347                                 top_level->active_subwindow = this;
348                                 show_value_tooltip();
349                         }
350                         return 1;
351                 }
352         }
353         return 0;
354 }
355
356 int BC_Pot::button_release_event()
357 {
358         if(top_level->event_win == win)
359         {
360                 if(status == POT_DN)
361                 {
362                         if(cursor_inside())
363                                 status = POT_HIGH;
364                         else
365                         {
366                                 status = POT_UP;
367                                 top_level->hide_tooltip();
368                         }
369                 }
370                 draw(1);
371                 return 1;
372         }
373         return 0;
374 }
375
376 int BC_Pot::cursor_motion_event()
377 {
378         if(top_level->button_down &&
379                 top_level->event_win == win &&
380                 status == POT_DN)
381         {
382                 float angle = coords_to_angle(get_cursor_x(), get_cursor_y());
383
384                 if(prev_angle >= 0 && prev_angle < 90 &&
385                         angle >= 270 && angle < 360)
386                 {
387                         angle_correction -= 360;
388                 }
389                 else
390                 if(prev_angle >= 270 && prev_angle < 360 &&
391                         angle >= 0 && angle < 90)
392                 {
393                         angle_correction += 360;
394                 }
395
396                 prev_angle = angle;
397
398                 if(percentage_to_value(
399                         angle_to_percentage(angle + angle_correction - angle_offset)))
400                 {
401                         set_tooltip(get_caption());
402                         draw(1);
403                         handle_event();
404                 }
405                 return 1;
406         }
407         return 0;
408 }
409
410
411 BC_FPot::BC_FPot(int x, int y,
412         float value, float minvalue, float maxvalue, VFrame **data)
413  : BC_Pot(x, y, data)
414 {
415         this->value = value;
416         this->minvalue = minvalue;
417         this->maxvalue = maxvalue;
418         precision = 0.1;
419 }
420
421 BC_FPot::~BC_FPot()
422 {
423 }
424
425 int BC_FPot::increase_value()
426 {
427         value += precision;
428         if(value > maxvalue) value = maxvalue;
429         return 0;
430 }
431
432 int BC_FPot::decrease_value()
433 {
434         value -= precision;
435         if(value < minvalue) value = minvalue;
436         return 0;
437 }
438
439 void BC_FPot::set_precision(float value)
440 {
441         this->precision = value;
442 }
443
444 const char*  BC_FPot::get_caption()
445 {
446         sprintf(caption, "%.2f", value);
447         return caption;
448 }
449
450 float BC_FPot::get_percentage()
451 {
452         float range = maxvalue - minvalue;
453         return range > 0 ? (value - minvalue) / range : minvalue;
454 }
455
456 int BC_FPot::percentage_to_value(float percentage)
457 {
458         float old_value = value;
459         value = percentage * (maxvalue - minvalue) + minvalue;
460         value = Units::quantize(value, precision);
461         if(value < minvalue) value = minvalue;
462         if(value > maxvalue) value = maxvalue;
463         if(value != old_value) return 1;
464         return 0;
465 }
466
467 float BC_FPot::get_value()
468 {
469         return value;
470 }
471
472 void BC_FPot::update(float value)
473 {
474         if(value < minvalue) value= minvalue;
475         if(value > maxvalue) value= maxvalue;
476         if(value != this->value)
477         {
478                 this->value = value;
479                 draw(1);
480         }
481 }
482
483 void BC_FPot::update(float value, float minvalue, float maxvalue)
484 {
485         if(value != this->value ||
486                 minvalue != this->minvalue ||
487                 maxvalue != this->maxvalue)
488         {
489                 this->value = value;
490                 this->minvalue = minvalue;
491                 this->maxvalue = maxvalue;
492                 draw(1);
493         }
494 }
495
496
497 BC_IPot::BC_IPot(int x, int y,
498         int64_t value, int64_t minvalue, int64_t maxvalue, VFrame **data)
499  : BC_Pot(x, y, data)
500 {
501         this->value = value;
502         this->minvalue = minvalue;
503         this->maxvalue = maxvalue;
504 }
505
506 BC_IPot::~BC_IPot()
507 {
508 }
509
510 int BC_IPot::increase_value()
511 {
512         value++;
513         if(value > maxvalue) value = maxvalue;
514         return 0;
515 }
516
517 int BC_IPot::decrease_value()
518 {
519         value--;
520         if(value < minvalue) value = minvalue;
521         return 0;
522 }
523
524 const char* BC_IPot::get_caption()
525 {
526         sprintf(caption, "%jd", value);
527         return caption;
528 }
529
530 float BC_IPot::get_percentage()
531 {
532         float range = maxvalue - minvalue;
533         return range > 0 ? ((float)value - minvalue) / range : minvalue;
534 }
535
536 int BC_IPot::percentage_to_value(float percentage)
537 {
538         int64_t old_value = value;
539         value = (int64_t)(percentage * (maxvalue - minvalue) + minvalue);
540         if(value < minvalue) value = minvalue;
541         if(value > maxvalue) value = maxvalue;
542         if(value != old_value) return 1;
543         return 0;
544 }
545
546 int64_t BC_IPot::get_value()
547 {
548         return value;
549 }
550
551 void BC_IPot::update(int64_t value)
552 {
553         if(value < minvalue) value= minvalue;
554         if(value > maxvalue) value= maxvalue;
555         if(this->value != value)
556         {
557                 this->value = value;
558                 draw(1);
559         }
560 }
561
562 void BC_IPot::update(int64_t value, int64_t minvalue, int64_t maxvalue)
563 {
564         if(this->value != value ||
565                 this->minvalue != minvalue ||
566                 this->maxvalue != maxvalue)
567         {
568                 this->value = value;
569                 this->minvalue = minvalue;
570                 this->maxvalue = maxvalue;
571                 draw(1);
572         }
573 }
574
575
576 BC_QPot::BC_QPot(int x, int y, int64_t value, VFrame **data)
577  : BC_Pot(x, y, data)
578 {
579         this->value = Freq::fromfreq(value);
580         this->minvalue = 0;
581         this->maxvalue = TOTALFREQS;
582 }
583
584 BC_QPot::~BC_QPot()
585 {
586 }
587
588 int BC_QPot::increase_value()
589 {
590         value++;
591         if(value > maxvalue) value = maxvalue;
592         return 0;
593 }
594
595 int BC_QPot::decrease_value()
596 {
597         value--;
598         if(value < minvalue) value = minvalue;
599         return 0;
600 }
601
602 const char* BC_QPot::get_caption()
603 {
604         sprintf(caption, "%d", Freq::tofreq(value));
605         return caption;
606 }
607
608 float BC_QPot::get_percentage()
609 {
610         float range = maxvalue - minvalue;
611         return range > 0 ? ((float)value - minvalue) / range : 0;
612 }
613
614 int BC_QPot::percentage_to_value(float percentage)
615 {
616         int64_t old_value = value;
617         value = (int64_t)(percentage * (maxvalue - minvalue) + minvalue);
618         if(value < minvalue) value = minvalue;
619         if(value > maxvalue) value = maxvalue;
620         if(value != old_value) return 1;
621         return 0;
622 }
623
624 int64_t BC_QPot::get_value()
625 {
626         return Freq::tofreq(value);
627 }
628
629 void BC_QPot::update(int64_t value)
630 {
631         value = Freq::fromfreq(value);
632         if(value < minvalue) value = minvalue;
633         if(value > maxvalue) value = maxvalue;
634         if(this->value != value)
635         {
636                 this->value = value;
637                 draw(1);
638         }
639 }
640
641
642 BC_PercentagePot::BC_PercentagePot(int x, int y,
643         float value, float minvalue, float maxvalue, VFrame **data)
644  : BC_Pot(x, y, data)
645 {
646         this->value = value;
647         this->minvalue = minvalue;
648         this->maxvalue = maxvalue;
649 }
650
651 BC_PercentagePot::~BC_PercentagePot()
652 {
653 }
654
655 int BC_PercentagePot::increase_value()
656 {
657         value++;
658         if(value > maxvalue) value = maxvalue;
659         return 0;
660 }
661
662 int BC_PercentagePot::decrease_value()
663 {
664         value--;
665         if(value < minvalue) value = minvalue;
666         return 0;
667 }
668
669 const char* BC_PercentagePot::get_caption()
670 {
671         sprintf(caption, "%d%%", (int)(get_percentage() * 100 + 0.5));
672         return caption;
673 }
674
675 float BC_PercentagePot::get_percentage()
676 {
677         float range = maxvalue - minvalue;
678         return range > 0 ? (value - minvalue) / range : minvalue;
679 }
680
681 int BC_PercentagePot::percentage_to_value(float percentage)
682 {
683         float old_value = value;
684         value = percentage * (maxvalue - minvalue) + minvalue;
685         if(value < minvalue) value = minvalue;
686         if(value > maxvalue) value = maxvalue;
687         if(value != old_value) return 1;
688         return 0;
689 }
690
691 float BC_PercentagePot::get_value()
692 {
693         return value;
694 }
695
696 void BC_PercentagePot::update(float value)
697 {
698         if(value < minvalue) value= minvalue;
699         if(value > maxvalue) value= maxvalue;
700         if(this->value != value)
701         {
702                 this->value = value;
703                 draw(1);
704         }
705 }
706