update ffmpeg.git patch set
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / cwindowtool.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
4  *
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.
9  *
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.
14  *
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
18  *
19  */
20
21 #include <stdio.h>
22 #include <stdint.h>
23
24 #include "automation.h"
25 #include "bccolors.h"
26 #include "clip.h"
27 #include "condition.h"
28 #include "cpanel.h"
29 #include "cplayback.h"
30 #include "cwindow.h"
31 #include "cwindowgui.h"
32 #include "cwindowtool.h"
33 #include "edl.h"
34 #include "edlsession.h"
35 #include "floatauto.h"
36 #include "floatautos.h"
37 #include "keys.h"
38 #include "language.h"
39 #include "localsession.h"
40 #include "mainsession.h"
41 #include "mainundo.h"
42 #include "maskauto.h"
43 #include "maskautos.h"
44 #include "mutex.h"
45 #include "mwindow.h"
46 #include "mwindowgui.h"
47 #include "theme.h"
48 #include "track.h"
49 #include "trackcanvas.h"
50 #include "transportque.h"
51
52
53 CWindowTool::CWindowTool(MWindow *mwindow, CWindowGUI *gui)
54  : Thread(1, 0, 0)
55 {
56         this->mwindow = mwindow;
57         this->gui = gui;
58         tool_gui = 0;
59         done = 0;
60         current_tool = CWINDOW_NONE;
61         set_synchronous(1);
62         input_lock = new Condition(0, "CWindowTool::input_lock");
63         output_lock = new Condition(1, "CWindowTool::output_lock");
64         tool_gui_lock = new Mutex("CWindowTool::tool_gui_lock");
65 }
66
67 CWindowTool::~CWindowTool()
68 {
69         done = 1;
70         stop_tool();
71         input_lock->unlock();
72         Thread::join();
73         delete input_lock;
74         delete output_lock;
75         delete tool_gui_lock;
76 }
77
78 void CWindowTool::start_tool(int operation)
79 {
80         CWindowToolGUI *new_gui = 0;
81         int result = 0;
82
83 //printf("CWindowTool::start_tool 1\n");
84         if(current_tool != operation)
85         {
86                 int previous_tool = current_tool;
87                 current_tool = operation;
88                 switch(operation)
89                 {
90                         case CWINDOW_EYEDROP:
91                                 new_gui = new CWindowEyedropGUI(mwindow, this);
92                                 break;
93                         case CWINDOW_CROP:
94                                 new_gui = new CWindowCropGUI(mwindow, this);
95                                 break;
96                         case CWINDOW_CAMERA:
97                                 new_gui = new CWindowCameraGUI(mwindow, this);
98                                 break;
99                         case CWINDOW_PROJECTOR:
100                                 new_gui = new CWindowProjectorGUI(mwindow, this);
101                                 break;
102                         case CWINDOW_MASK:
103                                 new_gui = new CWindowMaskGUI(mwindow, this);
104                                 break;
105                         case CWINDOW_RULER:
106                                 new_gui = new CWindowRulerGUI(mwindow, this);
107                                 break;
108                         case CWINDOW_PROTECT:
109                                 mwindow->edl->session->tool_window = 0;
110                                 gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]->update(0);
111                                 // fall thru
112                         default:
113                                 result = 1;
114                                 stop_tool();
115                                 break;
116                 }
117
118 //printf("CWindowTool::start_tool 1\n");
119
120
121                 if(!result)
122                 {
123                         stop_tool();
124 // Wait for previous tool GUI to finish
125                         output_lock->lock("CWindowTool::start_tool");
126                         this->tool_gui = new_gui;
127                         tool_gui->create_objects();
128                         if( previous_tool == CWINDOW_PROTECT || previous_tool == CWINDOW_NONE ) {
129                                 mwindow->edl->session->tool_window = 1;
130                                 gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]->update(1);
131                         }
132                         update_show_window();
133
134 // Signal thread to run next tool GUI
135                         input_lock->unlock();
136                 }
137 //printf("CWindowTool::start_tool 1\n");
138         }
139         else
140         if(tool_gui)
141         {
142                 tool_gui->lock_window("CWindowTool::start_tool");
143                 tool_gui->update();
144                 tool_gui->unlock_window();
145         }
146
147 //printf("CWindowTool::start_tool 2\n");
148
149 }
150
151
152 void CWindowTool::stop_tool()
153 {
154         if(tool_gui)
155         {
156                 tool_gui->lock_window("CWindowTool::stop_tool");
157                 tool_gui->set_done(0);
158                 tool_gui->unlock_window();
159         }
160 }
161
162 void CWindowTool::show_tool()
163 {
164         if(tool_gui && mwindow->edl->session->tool_window)
165         {
166                 tool_gui->lock_window("CWindowTool::show_tool");
167                 tool_gui->show_window();
168                 tool_gui->unlock_window();
169         }
170 }
171
172 void CWindowTool::hide_tool()
173 {
174         if(tool_gui && mwindow->edl->session->tool_window)
175         {
176                 tool_gui->lock_window("CWindowTool::show_tool");
177                 tool_gui->hide_window();
178                 tool_gui->unlock_window();
179         }
180 }
181
182
183 void CWindowTool::run()
184 {
185         while(!done)
186         {
187                 input_lock->lock("CWindowTool::run");
188                 if(!done)
189                 {
190                         tool_gui->run_window();
191                         tool_gui_lock->lock("CWindowTool::run");
192                         delete tool_gui;
193                         tool_gui = 0;
194                         tool_gui_lock->unlock();
195                 }
196                 output_lock->unlock();
197         }
198 }
199
200 void CWindowTool::update_show_window()
201 {
202         if(tool_gui)
203         {
204                 tool_gui->lock_window("CWindowTool::update_show_window");
205
206                 if(mwindow->edl->session->tool_window)
207                 {
208                         tool_gui->update();
209                         tool_gui->show_window();
210                 }
211                 else
212                         tool_gui->hide_window();
213                 tool_gui->flush();
214
215                 tool_gui->unlock_window();
216         }
217 }
218
219 void CWindowTool::raise_window()
220 {
221         if(tool_gui)
222         {
223                 gui->unlock_window();
224                 tool_gui->lock_window("CWindowTool::raise_window");
225                 tool_gui->raise_window();
226                 tool_gui->unlock_window();
227                 gui->lock_window("CWindowTool::raise_window");
228         }
229 }
230
231 void CWindowTool::update_values()
232 {
233         tool_gui_lock->lock("CWindowTool::update_values");
234         if(tool_gui)
235         {
236                 tool_gui->lock_window("CWindowTool::update_values");
237                 tool_gui->update();
238                 tool_gui->flush();
239                 tool_gui->unlock_window();
240         }
241         tool_gui_lock->unlock();
242 }
243
244
245
246
247
248
249
250 CWindowToolGUI::CWindowToolGUI(MWindow *mwindow,
251         CWindowTool *thread,
252         const char *title,
253         int w,
254         int h)
255  : BC_Window(title,
256         mwindow->session->ctool_x,
257         mwindow->session->ctool_y,
258         w,
259         h,
260         w,
261         h,
262         0,
263         0,
264         1)
265 {
266         this->mwindow = mwindow;
267         this->thread = thread;
268         current_operation = 0;
269 }
270
271 CWindowToolGUI::~CWindowToolGUI()
272 {
273 }
274
275 int CWindowToolGUI::close_event()
276 {
277         hide_window();
278         flush();
279         mwindow->edl->session->tool_window = 0;
280         unlock_window();
281
282
283
284         thread->gui->lock_window("CWindowToolGUI::close_event");
285         thread->gui->composite_panel->set_operation(mwindow->edl->session->cwindow_operation);
286         thread->gui->flush();
287         thread->gui->unlock_window();
288
289         lock_window("CWindowToolGUI::close_event");
290         return 1;
291 ;}
292
293 int CWindowToolGUI::keypress_event()
294 {
295         int result = 0;
296
297         switch( get_keypress() ) {
298         case 'w':
299         case 'W':
300                 return close_event();
301         case KEY_F1:
302         case KEY_F2:
303         case KEY_F3:
304         case KEY_F4:
305         case KEY_F5:
306         case KEY_F6:
307         case KEY_F7:
308         case KEY_F8:
309         case KEY_F9:
310         case KEY_F10:
311         case KEY_F11:
312         case KEY_F12:
313                 resend_event(thread->gui);
314                 result = 1;
315         }
316
317         return result;
318 }
319
320 int CWindowToolGUI::translation_event()
321 {
322         mwindow->session->ctool_x = get_x();
323         mwindow->session->ctool_y = get_y();
324         return 0;
325 }
326
327
328
329
330
331
332 CWindowCoord::CWindowCoord(CWindowToolGUI *gui, int x, int y, float value, int log_increment = 0)
333  : BC_TumbleTextBox(gui, (float)value, (float)-65536, (float)65536, x, y, 100)
334 {
335         this->gui = gui;
336         set_log_floatincrement(log_increment);
337 }
338
339 CWindowCoord::CWindowCoord(CWindowToolGUI *gui, int x, int y, int value)
340  : BC_TumbleTextBox(gui, (int64_t)value, (int64_t)-65536, (int64_t)65536, x, y, 100)
341 {
342         this->gui = gui;
343 }
344 int CWindowCoord::handle_event()
345 {
346         gui->event_caller = this;
347         gui->handle_event();
348         return 1;
349 }
350
351
352 CWindowCropOK::CWindowCropOK(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
353  : BC_GenericButton(x, y, _("Do it"))
354 {
355         this->mwindow = mwindow;
356         this->gui = gui;
357 }
358 int CWindowCropOK::handle_event()
359 {
360         mwindow->crop_video();
361         return 1;
362 }
363
364
365 int CWindowCropOK::keypress_event()
366 {
367         if(get_keypress() == 0xd)
368         {
369                 handle_event();
370                 return 1;
371         }
372         return 0;
373 }
374
375
376
377
378
379
380
381 CWindowCropGUI::CWindowCropGUI(MWindow *mwindow, CWindowTool *thread)
382  : CWindowToolGUI(mwindow,
383         thread,
384         _(PROGRAM_NAME ": Crop"),
385         330,
386         100)
387 {
388 }
389
390
391 CWindowCropGUI::~CWindowCropGUI()
392 {
393 }
394
395 void CWindowCropGUI::create_objects()
396 {
397         int x = 10, y = 10;
398         BC_Title *title;
399
400         lock_window("CWindowCropGUI::create_objects");
401         int column1 = 0;
402         int pad = MAX(BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1),
403                 BC_Title::calculate_h(this, "X")) + 5;
404         add_subwindow(title = new BC_Title(x, y, "X1:"));
405         column1 = MAX(column1, title->get_w());
406         y += pad;
407         add_subwindow(title = new BC_Title(x, y, _("W:")));
408         column1 = MAX(column1, title->get_w());
409         y += pad;
410         add_subwindow(new CWindowCropOK(mwindow, thread->tool_gui, x, y));
411
412         x += column1 + 5;
413         y = 10;
414         x1 = new CWindowCoord(thread->tool_gui, x, y,
415                 mwindow->edl->session->crop_x1);
416         x1->create_objects();
417         y += pad;
418         width = new CWindowCoord(thread->tool_gui, x, y,
419                 mwindow->edl->session->crop_x2 - mwindow->edl->session->crop_x1);
420         width->create_objects();
421
422
423         x += x1->get_w() + 10;
424         y = 10;
425         int column2 = 0;
426         add_subwindow(title = new BC_Title(x, y, "Y1:"));
427         column2 = MAX(column2, title->get_w());
428         y += pad;
429         add_subwindow(title = new BC_Title(x, y, _("H:")));
430         column2 = MAX(column2, title->get_w());
431         y += pad;
432
433         y = 10;
434         x += column2 + 5;
435         y1 = new CWindowCoord(thread->tool_gui, x, y,
436                 mwindow->edl->session->crop_y1);
437         y1->create_objects();
438         y += pad;
439         height = new CWindowCoord(thread->tool_gui, x, y,
440                 mwindow->edl->session->crop_y2 - mwindow->edl->session->crop_y1);
441         height->create_objects();
442         unlock_window();
443 }
444
445 void CWindowCropGUI::handle_event()
446 {
447         int new_x1, new_y1;
448         new_x1 = atol(x1->get_text());
449         new_y1 = atol(y1->get_text());
450         if(new_x1 != mwindow->edl->session->crop_x1)
451         {
452                 mwindow->edl->session->crop_x2 = new_x1 +
453                         mwindow->edl->session->crop_x2 -
454                         mwindow->edl->session->crop_x1;
455                 mwindow->edl->session->crop_x1 = new_x1;
456         }
457         if(new_y1 != mwindow->edl->session->crop_y1)
458         {
459                 mwindow->edl->session->crop_y2 = new_y1 +
460                         mwindow->edl->session->crop_y2 -
461                         mwindow->edl->session->crop_y1;
462                 mwindow->edl->session->crop_y1 = atol(y1->get_text());
463         }
464         mwindow->edl->session->crop_x2 = atol(width->get_text()) +
465                 mwindow->edl->session->crop_x1;
466         mwindow->edl->session->crop_y2 = atol(height->get_text()) +
467                 mwindow->edl->session->crop_y1;
468         update();
469         mwindow->cwindow->gui->canvas->redraw(1);
470 }
471
472 void CWindowCropGUI::update()
473 {
474         x1->update((int64_t)mwindow->edl->session->crop_x1);
475         y1->update((int64_t)mwindow->edl->session->crop_y1);
476         width->update((int64_t)mwindow->edl->session->crop_x2 -
477                 mwindow->edl->session->crop_x1);
478         height->update((int64_t)mwindow->edl->session->crop_y2 -
479                 mwindow->edl->session->crop_y1);
480 }
481
482
483 CWindowEyedropGUI::CWindowEyedropGUI(MWindow *mwindow, CWindowTool *thread)
484  : CWindowToolGUI(mwindow, thread, _(PROGRAM_NAME ": Color"), 220, 290)
485 {
486 }
487
488 CWindowEyedropGUI::~CWindowEyedropGUI()
489 {
490 }
491
492 void CWindowEyedropGUI::create_objects()
493 {
494         int margin = mwindow->theme->widget_border;
495         int x = 10 + margin;
496         int y = 10 + margin;
497         int x2 = 70, x3 = x2 + 60;
498         lock_window("CWindowEyedropGUI::create_objects");
499         BC_Title *title0, *title1, *title2, *title3, *title4, *title5, *title6, *title7;
500         add_subwindow(title0 = new BC_Title(x, y,_("X,Y:")));
501         y += title0->get_h() + margin;
502         add_subwindow(title7 = new BC_Title(x, y, _("Radius:")));
503         y += BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1) + margin;
504
505         add_subwindow(title1 = new BC_Title(x, y, _("Red:")));
506         y += title1->get_h() + margin;
507         add_subwindow(title2 = new BC_Title(x, y, _("Green:")));
508         y += title2->get_h() + margin;
509         add_subwindow(title3 = new BC_Title(x, y, _("Blue:")));
510         y += title3->get_h() + margin;
511
512         add_subwindow(title4 = new BC_Title(x, y, "Y:"));
513         y += title4->get_h() + margin;
514         add_subwindow(title5 = new BC_Title(x, y, "U:"));
515         y += title5->get_h() + margin;
516         add_subwindow(title6 = new BC_Title(x, y, "V:"));
517
518         add_subwindow(current = new BC_Title(x2, title0->get_y(), ""));
519
520         radius = new CWindowCoord(this, x2, title7->get_y(),
521                 mwindow->edl->session->eyedrop_radius);
522         radius->create_objects();
523         radius->set_boundaries((int64_t)0, (int64_t)255);
524
525         add_subwindow(red = new BC_Title(x2, title1->get_y(), "0"));
526         add_subwindow(green = new BC_Title(x2, title2->get_y(), "0"));
527         add_subwindow(blue = new BC_Title(x2, title3->get_y(), "0"));
528         add_subwindow(rgb_hex = new BC_Title(x3, red->get_y(), "#000000"));
529
530         add_subwindow(this->y = new BC_Title(x2, title4->get_y(), "0"));
531         add_subwindow(this->u = new BC_Title(x2, title5->get_y(), "0"));
532         add_subwindow(this->v = new BC_Title(x2, title6->get_y(), "0"));
533         add_subwindow(yuv_hex = new BC_Title(x3, this->y->get_y(), "#000000"));
534
535         y = title6->get_y() + this->v->get_h() + 2*margin;
536         add_subwindow(sample = new BC_SubWindow(x, y, 50, 50));
537         y += sample->get_h() + margin;
538         add_subwindow(use_max = new CWindowEyedropCheckBox(mwindow, this, x, y));
539         update();
540         unlock_window();
541 }
542
543 void CWindowEyedropGUI::update()
544 {
545         char string[BCTEXTLEN];
546         sprintf(string, "%d, %d",
547                 thread->gui->eyedrop_x,
548                 thread->gui->eyedrop_y);
549         current->update(string);
550
551         radius->update((int64_t)mwindow->edl->session->eyedrop_radius);
552
553         LocalSession *local_session = mwindow->edl->local_session;
554         int use_max = local_session->use_max;
555         float r = use_max ? local_session->red_max : local_session->red;
556         float g = use_max ? local_session->green_max : local_session->green;
557         float b = use_max ? local_session->blue_max : local_session->blue;
558         this->red->update(r);
559         this->green->update(g);
560         this->blue->update(b);
561
562         int rx = 255*r + 0.5;  bclamp(rx,0,255);
563         int gx = 255*g + 0.5;  bclamp(gx,0,255);
564         int bx = 255*b + 0.5;  bclamp(bx,0,255);
565         char rgb_text[BCSTRLEN];
566         sprintf(rgb_text, "#%02x%02x%02x", rx, gx, bx);
567         rgb_hex->update(rgb_text);
568         
569         float y, u, v;
570         YUV::yuv.rgb_to_yuv_f(r, g, b, y, u, v);
571         this->y->update(y);
572         this->u->update(u);  u += 0.5;
573         this->v->update(v);  v += 0.5;
574
575         int yx = 255*y + 0.5;  bclamp(yx,0,255);
576         int ux = 255*u + 0.5;  bclamp(ux,0,255);
577         int vx = 255*v + 0.5;  bclamp(vx,0,255);
578         char yuv_text[BCSTRLEN];
579         sprintf(yuv_text, "#%02x%02x%02x", yx, ux, vx);
580         yuv_hex->update(yuv_text);
581
582         int rgb = (rx << 16) | (gx << 8) | (bx << 0);
583         sample->set_color(rgb);
584         sample->draw_box(0, 0, sample->get_w(), sample->get_h());
585         sample->set_color(BLACK);
586         sample->draw_rectangle(0, 0, sample->get_w(), sample->get_h());
587         sample->flash();
588 }
589
590 void CWindowEyedropGUI::handle_event()
591 {
592         int new_radius = atoi(radius->get_text());
593         if(new_radius != mwindow->edl->session->eyedrop_radius)
594         {
595                 CWindowGUI *gui = mwindow->cwindow->gui;
596                 if(gui->eyedrop_visible)
597                 {
598                         gui->lock_window("CWindowEyedropGUI::handle_event");
599 // hide it
600                         int rerender;
601                         gui->canvas->do_eyedrop(rerender, 0, 1);
602                 }
603
604                 mwindow->edl->session->eyedrop_radius = new_radius;
605
606                 if(gui->eyedrop_visible)
607                 {
608 // draw it
609                         int rerender;
610                         gui->canvas->do_eyedrop(rerender, 0, 1);
611                         gui->unlock_window();
612                 }
613         }
614 }
615
616
617
618 /* Buttons to control Keyframe-Curve-Mode for Projector or Camera */
619
620 // Configuration for all possible Keyframe Curve Mode toggles
621 struct _CVD {
622         FloatAuto::t_mode mode;
623         bool use_camera;
624         const char* icon_id;
625         const char* tooltip;
626 };
627
628 const _CVD Camera_Crv_Smooth =
629         {       FloatAuto::SMOOTH,
630                 true,
631                 "tan_smooth",
632                 N_("\"smooth\" Curve on current Camera Keyframes")
633         };
634 const _CVD Camera_Crv_Linear =
635         {       FloatAuto::LINEAR,
636                 true,
637                 "tan_linear",
638                 N_("\"linear\" Curve on current Camera Keyframes")
639         };
640 const _CVD Projector_Crv_Smooth =
641         {       FloatAuto::SMOOTH,
642                 false,
643                 "tan_smooth",
644                 N_("\"smooth\" Curve on current Projector Keyframes")
645         };
646 const _CVD Projector_Crv_Linear =
647         {       FloatAuto::LINEAR,
648                 false,
649                 "tan_linear",
650                 N_("\"linear\" Curve on current Projector Keyframes")
651         };
652
653 // Implementation Class für Keyframe Curve Mode buttons
654 //
655 // This button reflects the state of the "current" keyframe
656 // (the nearest keyframe on the left) for all three automation
657 // lines together. Clicking on this button (re)sets the curve
658 // mode for the three "current" keyframes simultanously, but
659 // never creates a new keyframe.
660 //
661 class CWindowCurveToggle : public BC_Toggle
662 {
663 public:
664         CWindowCurveToggle(_CVD mode, MWindow *mwindow, CWindowToolGUI *gui, int x, int y);
665         void check_toggle_state(FloatAuto *x, FloatAuto *y, FloatAuto *z);
666         int handle_event();
667 private:
668         _CVD cfg;
669         MWindow *mwindow;
670         CWindowToolGUI *gui;
671 };
672
673
674 CWindowCurveToggle::CWindowCurveToggle(_CVD mode, MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
675  : BC_Toggle(x, y, mwindow->theme->get_image_set(mode.icon_id), false),
676    cfg(mode)
677 {
678         this->gui = gui;
679         this->mwindow = mwindow;
680         set_tooltip(_(cfg.tooltip));
681 }
682
683 void CWindowCurveToggle::check_toggle_state(FloatAuto *x, FloatAuto *y, FloatAuto *z)
684 {
685 // the toggle state is only set to ON if all
686 // three automation lines have the same curve mode.
687 // For mixed states the toggle stays off.
688         set_value( x->curve_mode == this->cfg.mode &&
689                    y->curve_mode == this->cfg.mode &&
690                    z->curve_mode == this->cfg.mode
691                  ,true // redraw to show new state
692                  );
693 }
694
695 int CWindowCurveToggle::handle_event()
696 {
697         Track *track = mwindow->cwindow->calculate_affected_track();
698         if(track) {
699                 FloatAuto *x=0, *y=0, *z=0;
700                 mwindow->cwindow->calculate_affected_autos(track,
701                         &x, &y, &z, cfg.use_camera, 0,0,0); // don't create new keyframe
702                 if( x ) x->change_curve_mode(cfg.mode);
703                 if( y ) y->change_curve_mode(cfg.mode);
704                 if( z ) z->change_curve_mode(cfg.mode);
705
706                 gui->update();
707                 gui->update_preview();
708         }
709
710         return 1;
711 }
712
713
714 CWindowEyedropCheckBox::CWindowEyedropCheckBox(MWindow *mwindow, 
715         CWindowEyedropGUI *gui, int x, int y)
716  : BC_CheckBox(x, y, mwindow->edl->local_session->use_max, _("Use maximum"))
717 {
718         this->mwindow = mwindow;
719         this->gui = gui;
720 }
721
722 int CWindowEyedropCheckBox::handle_event()
723 {
724         mwindow->edl->local_session->use_max = get_value();
725         
726         gui->update();
727         return 1;
728 }
729
730
731 CWindowCameraGUI::CWindowCameraGUI(MWindow *mwindow, CWindowTool *thread)
732  : CWindowToolGUI(mwindow,
733         thread,
734         _(PROGRAM_NAME ": Camera"),
735         170,
736         170)
737 {
738 }
739 CWindowCameraGUI::~CWindowCameraGUI()
740 {
741 }
742
743 void CWindowCameraGUI::create_objects()
744 {
745         int x = 10, y = 10, x1;
746         Track *track = mwindow->cwindow->calculate_affected_track();
747         FloatAuto *x_auto = 0, *y_auto = 0, *z_auto = 0;
748         BC_Title *title;
749         BC_Button *button;
750
751         lock_window("CWindowCameraGUI::create_objects");
752         if( track ) {
753                 mwindow->cwindow->calculate_affected_autos(track,
754                         &x_auto, &y_auto, &z_auto, 1, 0, 0, 0);
755         }
756
757         add_subwindow(title = new BC_Title(x, y, "X:"));
758         x += title->get_w();
759         this->x = new CWindowCoord(this, x, y,
760                 x_auto ? x_auto->get_value() : (float)0);
761         this->x->create_objects();
762
763
764         y += 30;
765         x = 10;
766         add_subwindow(title = new BC_Title(x, y, "Y:"));
767         x += title->get_w();
768         this->y = new CWindowCoord(this, x, y,
769                 y_auto ? y_auto->get_value() : (float)0);
770         this->y->create_objects();
771         y += 30;
772         x = 10;
773         add_subwindow(title = new BC_Title(x, y, "Z:"));
774         x += title->get_w();
775         this->z = new CWindowCoord(this, x, y,
776                 z_auto ? z_auto->get_value() : (float)1);
777         this->z->create_objects();
778         this->z->set_increment(0.01);
779
780         y += 30;
781         x1 = 10;
782         add_subwindow(button = new CWindowCameraLeft(mwindow, this, x1, y));
783         x1 += button->get_w();
784         add_subwindow(button = new CWindowCameraCenter(mwindow, this, x1, y));
785         x1 += button->get_w();
786         add_subwindow(button = new CWindowCameraRight(mwindow, this, x1, y));
787
788         y += button->get_h();
789         x1 = 10;
790         add_subwindow(button = new CWindowCameraTop(mwindow, this, x1, y));
791         x1 += button->get_w();
792         add_subwindow(button = new CWindowCameraMiddle(mwindow, this, x1, y));
793         x1 += button->get_w();
794         add_subwindow(button = new CWindowCameraBottom(mwindow, this, x1, y));
795 // additional Buttons to control the curve mode of the "current" keyframe
796         x1 += button->get_w() + 15;
797         add_subwindow(this->t_smooth = new CWindowCurveToggle(Camera_Crv_Smooth, mwindow, this, x1, y));
798         x1 += button->get_w();
799         add_subwindow(this->t_linear = new CWindowCurveToggle(Camera_Crv_Linear, mwindow, this, x1, y));
800
801 // fill in current auto keyframe values, set toggle states.
802         this->update();
803         unlock_window();
804 }
805
806 void CWindowCameraGUI::update_preview()
807 {
808         CWindowGUI *cgui = mwindow->cwindow->gui;
809         cgui->lock_window("CWindowCameraGUI::update_preview");
810         cgui->sync_parameters(CHANGE_PARAMS, 0, 1);
811         cgui->unlock_window();
812 }
813
814
815 void CWindowCameraGUI::handle_event()
816 {
817         FloatAuto *x_auto = 0;
818         FloatAuto *y_auto = 0;
819         FloatAuto *z_auto = 0;
820         Track *track = mwindow->cwindow->calculate_affected_track();
821         if(track)
822         {
823                 mwindow->undo->update_undo_before(_("camera"), this);
824                 if(event_caller == x)
825                 {
826                         x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
827                                 track->automation->autos[AUTOMATION_CAMERA_X],
828                                 1);
829                         if(x_auto)
830                         {
831                                 x_auto->set_value(atof(x->get_text()));
832                                 update();
833                                 update_preview();
834                         }
835                 }
836                 else
837                 if(event_caller == y)
838                 {
839                         y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
840                                 track->automation->autos[AUTOMATION_CAMERA_Y],
841                                 1);
842                         if(y_auto)
843                         {
844                                 y_auto->set_value(atof(y->get_text()));
845                                 update();
846                                 update_preview();
847                         }
848                 }
849                 else
850                 if(event_caller == z)
851                 {
852                         z_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
853                                 track->automation->autos[AUTOMATION_CAMERA_Z],
854                                 1);
855                         if(z_auto)
856                         {
857                                 float zoom = atof(z->get_text());
858                                 if(zoom > 100.) zoom = 100.;
859                                 else
860                                 if(zoom < 0.01) zoom = 0.01;
861         // Doesn't allow user to enter from scratch
862         //              if(zoom != atof(z->get_text()))
863         //                      z->update(zoom);
864
865                                 z_auto->set_value(zoom);
866                                 mwindow->gui->lock_window("CWindowCameraGUI::handle_event");
867                                 mwindow->gui->draw_overlays(1);
868                                 mwindow->gui->unlock_window();
869                                 update();
870                                 update_preview();
871                         }
872                 }
873
874                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
875         }
876 }
877
878 void CWindowCameraGUI::update()
879 {
880         FloatAuto *x_auto = 0;
881         FloatAuto *y_auto = 0;
882         FloatAuto *z_auto = 0;
883         Track *track = mwindow->cwindow->calculate_affected_track();
884         if( track ) {
885                 mwindow->cwindow->calculate_affected_autos(track,
886                         &x_auto, &y_auto, &z_auto, 1, 0, 0, 0);
887         }
888
889         if(x_auto)
890                 x->update(x_auto->get_value());
891         if(y_auto)
892                 y->update(y_auto->get_value());
893         if(z_auto) {
894                 float value = z_auto->get_value();
895                 z->update(value);
896                 thread->gui->lock_window("CWindowCameraGUI::update");
897                 thread->gui->composite_panel->cpanel_zoom->update(value);
898                 thread->gui->unlock_window();
899         }
900
901         if( x_auto && y_auto && z_auto )
902         {
903                 t_smooth->check_toggle_state(x_auto, y_auto, z_auto);
904                 t_linear->check_toggle_state(x_auto, y_auto, z_auto);
905         }
906 }
907
908
909
910
911 CWindowCameraLeft::CWindowCameraLeft(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
912  : BC_Button(x, y, mwindow->theme->get_image_set("left_justify"))
913 {
914         this->gui = gui;
915         this->mwindow = mwindow;
916         set_tooltip(_("Left justify"));
917 }
918 int CWindowCameraLeft::handle_event()
919 {
920         FloatAuto *x_auto = 0;
921         FloatAuto *z_auto = 0;
922         Track *track = mwindow->cwindow->calculate_affected_track();
923         if( track ) {
924                 mwindow->cwindow->calculate_affected_autos(track,
925                         &x_auto, 0, &z_auto, 1, 1, 0, 0);
926         }
927
928         if(x_auto && z_auto)
929         {
930                 int w = 0, h = 0;
931                 track->get_source_dimensions(
932                         mwindow->edl->local_session->get_selectionstart(1),
933                         w,
934                         h);
935
936                 if(w && h)
937                 {
938                         mwindow->undo->update_undo_before(_("camera"), 0);
939                         x_auto->set_value(
940                                 (double)track->track_w / z_auto->get_value() / 2 -
941                                 (double)w / 2);
942                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
943                         gui->update();
944                         gui->update_preview();
945                 }
946         }
947
948         return 1;
949 }
950
951
952 CWindowCameraCenter::CWindowCameraCenter(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
953  : BC_Button(x, y, mwindow->theme->get_image_set("center_justify"))
954 {
955         this->gui = gui;
956         this->mwindow = mwindow;
957         set_tooltip(_("Center horizontal"));
958 }
959 int CWindowCameraCenter::handle_event()
960 {
961         FloatAuto *x_auto = 0;
962         Track *track = mwindow->cwindow->calculate_affected_track();
963         if(track)
964                 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
965                         track->automation->autos[AUTOMATION_CAMERA_X],
966                         1);
967
968         if(x_auto)
969         {
970                 mwindow->undo->update_undo_before(_("camera"), 0);
971                 x_auto->set_value(0);
972                 gui->update();
973                 gui->update_preview();
974                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
975         }
976
977         return 1;
978 }
979
980
981 CWindowCameraRight::CWindowCameraRight(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
982  : BC_Button(x, y, mwindow->theme->get_image_set("right_justify"))
983 {
984         this->gui = gui;
985         this->mwindow = mwindow;
986         set_tooltip(_("Right justify"));
987 }
988 int CWindowCameraRight::handle_event()
989 {
990         FloatAuto *x_auto = 0;
991         FloatAuto *z_auto = 0;
992         Track *track = mwindow->cwindow->calculate_affected_track();
993         if( track ) {
994                 mwindow->cwindow->calculate_affected_autos(track,
995                         &x_auto, 0, &z_auto, 1, 1, 0, 0);
996         }
997
998         if(x_auto && z_auto)
999         {
1000                 int w = 0, h = 0;
1001                 track->get_source_dimensions(
1002                         mwindow->edl->local_session->get_selectionstart(1),
1003                         w,
1004                         h);
1005
1006                 if(w && h)
1007                 {
1008                         mwindow->undo->update_undo_before(_("camera"), 0);
1009                         x_auto->set_value( -((double)track->track_w / z_auto->get_value() / 2 -
1010                                 (double)w / 2));
1011                         gui->update();
1012                         gui->update_preview();
1013                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1014                 }
1015         }
1016
1017         return 1;
1018 }
1019
1020
1021 CWindowCameraTop::CWindowCameraTop(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1022  : BC_Button(x, y, mwindow->theme->get_image_set("top_justify"))
1023 {
1024         this->gui = gui;
1025         this->mwindow = mwindow;
1026         set_tooltip(_("Top justify"));
1027 }
1028 int CWindowCameraTop::handle_event()
1029 {
1030         FloatAuto *y_auto = 0;
1031         FloatAuto *z_auto = 0;
1032         Track *track = mwindow->cwindow->calculate_affected_track();
1033         if( track ) {
1034                 mwindow->cwindow->calculate_affected_autos(track,
1035                         0, &y_auto, &z_auto, 1, 0, 1, 0);
1036         }
1037
1038         if(y_auto && z_auto)
1039         {
1040                 int w = 0, h = 0;
1041                 track->get_source_dimensions(
1042                         mwindow->edl->local_session->get_selectionstart(1),
1043                         w,
1044                         h);
1045
1046                 if(w && h)
1047                 {
1048                         mwindow->undo->update_undo_before(_("camera"), 0);
1049                         y_auto->set_value((double)track->track_h / z_auto->get_value() / 2 -
1050                                 (double)h / 2);
1051                         gui->update();
1052                         gui->update_preview();
1053                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1054                 }
1055         }
1056
1057         return 1;
1058 }
1059
1060
1061 CWindowCameraMiddle::CWindowCameraMiddle(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1062  : BC_Button(x, y, mwindow->theme->get_image_set("middle_justify"))
1063 {
1064         this->gui = gui;
1065         this->mwindow = mwindow;
1066         set_tooltip(_("Center vertical"));
1067 }
1068 int CWindowCameraMiddle::handle_event()
1069 {
1070         FloatAuto *y_auto = 0;
1071         Track *track = mwindow->cwindow->calculate_affected_track();
1072         if(track)
1073                 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1074                         track->automation->autos[AUTOMATION_CAMERA_Y], 1);
1075
1076         if(y_auto)
1077         {
1078                 mwindow->undo->update_undo_before(_("camera"), 0);
1079                 y_auto->set_value(0);
1080                 gui->update();
1081                 gui->update_preview();
1082                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1083         }
1084
1085         return 1;
1086 }
1087
1088
1089 CWindowCameraBottom::CWindowCameraBottom(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1090  : BC_Button(x, y, mwindow->theme->get_image_set("bottom_justify"))
1091 {
1092         this->gui = gui;
1093         this->mwindow = mwindow;
1094         set_tooltip(_("Bottom justify"));
1095 }
1096 int CWindowCameraBottom::handle_event()
1097 {
1098         FloatAuto *y_auto = 0;
1099         FloatAuto *z_auto = 0;
1100         Track *track = mwindow->cwindow->calculate_affected_track();
1101         if( track ) {
1102                 mwindow->cwindow->calculate_affected_autos(track,
1103                         0, &y_auto, &z_auto, 1, 0, 1, 0);
1104         }
1105
1106         if(y_auto && z_auto)
1107         {
1108                 int w = 0, h = 0;
1109                 track->get_source_dimensions(
1110                         mwindow->edl->local_session->get_selectionstart(1),
1111                         w,
1112                         h);
1113
1114                 if(w && h)
1115                 {
1116                         mwindow->undo->update_undo_before(_("camera"), 0);
1117                         y_auto->set_value(-((double)track->track_h / z_auto->get_value() / 2 -
1118                                 (double)h / 2));
1119                         gui->update();
1120                         gui->update_preview();
1121                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1122                 }
1123         }
1124
1125         return 1;
1126 }
1127
1128
1129 CWindowProjectorGUI::CWindowProjectorGUI(MWindow *mwindow, CWindowTool *thread)
1130  : CWindowToolGUI(mwindow,
1131         thread,
1132         _(PROGRAM_NAME ": Projector"),
1133         170,
1134         170)
1135 {
1136 }
1137 CWindowProjectorGUI::~CWindowProjectorGUI()
1138 {
1139 }
1140 void CWindowProjectorGUI::create_objects()
1141 {
1142         int x = 10, y = 10, x1;
1143         Track *track = mwindow->cwindow->calculate_affected_track();
1144         FloatAuto *x_auto = 0;
1145         FloatAuto *y_auto = 0;
1146         FloatAuto *z_auto = 0;
1147         BC_Title *title;
1148         BC_Button *button;
1149
1150         lock_window("CWindowProjectorGUI::create_objects");
1151         if( track ) {
1152                 mwindow->cwindow->calculate_affected_autos(track,
1153                         &x_auto, &y_auto, &z_auto, 0, 0, 0, 0);
1154         }
1155
1156         add_subwindow(title = new BC_Title(x, y, "X:"));
1157         x += title->get_w();
1158         this->x = new CWindowCoord(this, x, y,
1159                 x_auto ? x_auto->get_value() : (float)0);
1160         this->x->create_objects();
1161         y += 30;
1162         x = 10;
1163         add_subwindow(title = new BC_Title(x, y, "Y:"));
1164         x += title->get_w();
1165         this->y = new CWindowCoord(this, x, y,
1166                 y_auto ? y_auto->get_value() : (float)0);
1167         this->y->create_objects();
1168         y += 30;
1169         x = 10;
1170         add_subwindow(title = new BC_Title(x, y, "Z:"));
1171         x += title->get_w();
1172         this->z = new CWindowCoord(this, x, y,
1173                 z_auto ? z_auto->get_value() : (float)1);
1174         this->z->create_objects();
1175         this->z->set_increment(0.01);
1176
1177         y += 30;
1178         x1 = 10;
1179         add_subwindow(button = new CWindowProjectorLeft(mwindow, this, x1, y));
1180         x1 += button->get_w();
1181         add_subwindow(button = new CWindowProjectorCenter(mwindow, this, x1, y));
1182         x1 += button->get_w();
1183         add_subwindow(button = new CWindowProjectorRight(mwindow, this, x1, y));
1184
1185         y += button->get_h();
1186         x1 = 10;
1187         add_subwindow(button = new CWindowProjectorTop(mwindow, this, x1, y));
1188         x1 += button->get_w();
1189         add_subwindow(button = new CWindowProjectorMiddle(mwindow, this, x1, y));
1190         x1 += button->get_w();
1191         add_subwindow(button = new CWindowProjectorBottom(mwindow, this, x1, y));
1192
1193 // additional Buttons to control the curve mode of the "current" keyframe
1194         x1 += button->get_w() + 15;
1195         add_subwindow(this->t_smooth = new CWindowCurveToggle(Projector_Crv_Smooth, mwindow, this, x1, y));
1196         x1 += button->get_w();
1197         add_subwindow(this->t_linear = new CWindowCurveToggle(Projector_Crv_Linear, mwindow, this, x1, y));
1198
1199 // fill in current auto keyframe values, set toggle states.
1200         this->update();
1201         unlock_window();
1202 }
1203
1204 void CWindowProjectorGUI::update_preview()
1205 {
1206         CWindowGUI *cgui = mwindow->cwindow->gui;
1207         cgui->lock_window("CWindowProjectorGUI::update_preview");
1208         cgui->sync_parameters(CHANGE_PARAMS, 0, 1);
1209         cgui->unlock_window();
1210 }
1211
1212 void CWindowProjectorGUI::handle_event()
1213 {
1214         FloatAuto *x_auto = 0;
1215         FloatAuto *y_auto = 0;
1216         FloatAuto *z_auto = 0;
1217         Track *track = mwindow->cwindow->calculate_affected_track();
1218
1219         if(track)
1220         {
1221                 mwindow->undo->update_undo_before(_("projector"), this);
1222                 if(event_caller == x)
1223                 {
1224                         x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1225                                 track->automation->autos[AUTOMATION_PROJECTOR_X],
1226                                 1);
1227                         if(x_auto)
1228                         {
1229                                 x_auto->set_value(atof(x->get_text()));
1230                                 update();
1231                                 update_preview();
1232                         }
1233                 }
1234                 else
1235                 if(event_caller == y)
1236                 {
1237                         y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1238                                 track->automation->autos[AUTOMATION_PROJECTOR_Y],
1239                                 1);
1240                         if(y_auto)
1241                         {
1242                                 y_auto->set_value(atof(y->get_text()));
1243                                 update();
1244                                 update_preview();
1245                         }
1246                 }
1247                 else
1248                 if(event_caller == z)
1249                 {
1250                         z_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1251                                 track->automation->autos[AUTOMATION_PROJECTOR_Z],
1252                                 1);
1253                         if(z_auto)
1254                         {
1255                                 float zoom = atof(z->get_text());
1256                                 if(zoom > 100.) zoom = 100.;
1257                                 else if(zoom < 0.01) zoom = 0.01;
1258 //                      if (zoom != atof(z->get_text()))
1259 //                              z->update(zoom);
1260                                 z_auto->set_value(zoom);
1261
1262                                 mwindow->gui->lock_window("CWindowProjectorGUI::handle_event");
1263                                 mwindow->gui->draw_overlays(1);
1264                                 mwindow->gui->unlock_window();
1265
1266                                 update();
1267                                 update_preview();
1268                         }
1269                 }
1270                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1271         }
1272 }
1273
1274 void CWindowProjectorGUI::update()
1275 {
1276         FloatAuto *x_auto = 0;
1277         FloatAuto *y_auto = 0;
1278         FloatAuto *z_auto = 0;
1279         Track *track = mwindow->cwindow->calculate_affected_track();
1280         if( track ) {
1281                 mwindow->cwindow->calculate_affected_autos(track,
1282                         &x_auto, &y_auto, &z_auto, 0, 0, 0, 0);
1283         }
1284
1285         if(x_auto)
1286                 x->update(x_auto->get_value());
1287         if(y_auto)
1288                 y->update(y_auto->get_value());
1289         if(z_auto) {
1290                 float value = z_auto->get_value();
1291                 z->update(value);
1292                 thread->gui->lock_window("CWindowProjectorGUI::update");
1293                 thread->gui->composite_panel->cpanel_zoom->update(value);
1294                 thread->gui->unlock_window();
1295         }
1296
1297         if( x_auto && y_auto && z_auto )
1298         {
1299                 t_smooth->check_toggle_state(x_auto, y_auto, z_auto);
1300                 t_linear->check_toggle_state(x_auto, y_auto, z_auto);
1301         }
1302 }
1303
1304 CWindowProjectorLeft::CWindowProjectorLeft(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1305  : BC_Button(x, y, mwindow->theme->get_image_set("left_justify"))
1306 {
1307         this->gui = gui;
1308         this->mwindow = mwindow;
1309         set_tooltip(_("Left justify"));
1310 }
1311 int CWindowProjectorLeft::handle_event()
1312 {
1313         FloatAuto *x_auto = 0;
1314         FloatAuto *z_auto = 0;
1315         Track *track = mwindow->cwindow->calculate_affected_track();
1316         if( track ) {
1317                 mwindow->cwindow->calculate_affected_autos(track,
1318                         &x_auto, 0, &z_auto, 0, 1, 0, 0);
1319         }
1320         if(x_auto && z_auto)
1321         {
1322                 mwindow->undo->update_undo_before(_("projector"), 0);
1323                 x_auto->set_value( (double)track->track_w * z_auto->get_value() / 2 -
1324                         (double)mwindow->edl->session->output_w / 2 );
1325                 gui->update();
1326                 gui->update_preview();
1327                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1328         }
1329
1330         return 1;
1331 }
1332
1333
1334 CWindowProjectorCenter::CWindowProjectorCenter(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1335  : BC_Button(x, y, mwindow->theme->get_image_set("center_justify"))
1336 {
1337         this->gui = gui;
1338         this->mwindow = mwindow;
1339         set_tooltip(_("Center horizontal"));
1340 }
1341 int CWindowProjectorCenter::handle_event()
1342 {
1343         FloatAuto *x_auto = 0;
1344         Track *track = mwindow->cwindow->calculate_affected_track();
1345         if(track)
1346                 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1347                         track->automation->autos[AUTOMATION_PROJECTOR_X],
1348                         1);
1349
1350         if(x_auto)
1351         {
1352                 mwindow->undo->update_undo_before(_("projector"), 0);
1353                 x_auto->set_value(0);
1354                 gui->update();
1355                 gui->update_preview();
1356                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1357         }
1358
1359         return 1;
1360 }
1361
1362
1363 CWindowProjectorRight::CWindowProjectorRight(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1364  : BC_Button(x, y, mwindow->theme->get_image_set("right_justify"))
1365 {
1366         this->gui = gui;
1367         this->mwindow = mwindow;
1368         set_tooltip(_("Right justify"));
1369 }
1370 int CWindowProjectorRight::handle_event()
1371 {
1372         FloatAuto *x_auto = 0;
1373         FloatAuto *z_auto = 0;
1374         Track *track = mwindow->cwindow->calculate_affected_track();
1375         if( track ) {
1376                 mwindow->cwindow->calculate_affected_autos(track,
1377                         &x_auto, 0, &z_auto, 0, 1, 0, 0);
1378         }
1379
1380         if(x_auto && z_auto)
1381         {
1382                 mwindow->undo->update_undo_before(_("projector"), 0);
1383                 x_auto->set_value( -((double)track->track_w * z_auto->get_value() / 2 -
1384                         (double)mwindow->edl->session->output_w / 2));
1385                 gui->update();
1386                 gui->update_preview();
1387                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1388         }
1389
1390         return 1;
1391 }
1392
1393
1394 CWindowProjectorTop::CWindowProjectorTop(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1395  : BC_Button(x, y, mwindow->theme->get_image_set("top_justify"))
1396 {
1397         this->gui = gui;
1398         this->mwindow = mwindow;
1399         set_tooltip(_("Top justify"));
1400 }
1401 int CWindowProjectorTop::handle_event()
1402 {
1403         FloatAuto *y_auto = 0;
1404         FloatAuto *z_auto = 0;
1405         Track *track = mwindow->cwindow->calculate_affected_track();
1406         if( track ) {
1407                 mwindow->cwindow->calculate_affected_autos(track,
1408                         0, &y_auto, &z_auto, 0, 0, 1, 0);
1409         }
1410
1411         if(y_auto && z_auto)
1412         {
1413                 mwindow->undo->update_undo_before(_("projector"), 0);
1414                 y_auto->set_value( (double)track->track_h * z_auto->get_value() / 2 -
1415                         (double)mwindow->edl->session->output_h / 2 );
1416                 gui->update();
1417                 gui->update_preview();
1418                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1419         }
1420
1421         return 1;
1422 }
1423
1424
1425 CWindowProjectorMiddle::CWindowProjectorMiddle(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1426  : BC_Button(x, y, mwindow->theme->get_image_set("middle_justify"))
1427 {
1428         this->gui = gui;
1429         this->mwindow = mwindow;
1430         set_tooltip(_("Center vertical"));
1431 }
1432 int CWindowProjectorMiddle::handle_event()
1433 {
1434         FloatAuto *y_auto = 0;
1435         Track *track = mwindow->cwindow->calculate_affected_track();
1436         if(track)
1437                 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1438                         track->automation->autos[AUTOMATION_PROJECTOR_Y], 1);
1439
1440         if(y_auto)
1441         {
1442                 mwindow->undo->update_undo_before(_("projector"), 0);
1443                 y_auto->set_value(0);
1444                 gui->update();
1445                 gui->update_preview();
1446                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1447         }
1448
1449         return 1;
1450 }
1451
1452
1453 CWindowProjectorBottom::CWindowProjectorBottom(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1454  : BC_Button(x, y, mwindow->theme->get_image_set("bottom_justify"))
1455 {
1456         this->gui = gui;
1457         this->mwindow = mwindow;
1458         set_tooltip(_("Bottom justify"));
1459 }
1460 int CWindowProjectorBottom::handle_event()
1461 {
1462         FloatAuto *y_auto = 0;
1463         FloatAuto *z_auto = 0;
1464         Track *track = mwindow->cwindow->calculate_affected_track();
1465         if( track ) {
1466                 mwindow->cwindow->calculate_affected_autos(track,
1467                         0, &y_auto, &z_auto, 0, 0, 1, 0);
1468         }
1469
1470         if(y_auto && z_auto)
1471         {
1472                 mwindow->undo->update_undo_before(_("projector"), 0);
1473                 y_auto->set_value( -((double)track->track_h * z_auto->get_value() / 2 -
1474                         (double)mwindow->edl->session->output_h / 2));
1475                 gui->update();
1476                 gui->update_preview();
1477                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1478         }
1479
1480         return 1;
1481 }
1482
1483
1484 CWindowMaskMode::CWindowMaskMode(MWindow *mwindow,
1485         CWindowToolGUI *gui, int x, int y, const char *text)
1486  : BC_PopupMenu(x, y, 220, text, 1)
1487 {
1488         this->mwindow = mwindow;
1489         this->gui = gui;
1490 }
1491
1492 void CWindowMaskMode::create_objects()
1493 {
1494         add_item(new BC_MenuItem(mode_to_text(MASK_MULTIPLY_ALPHA)));
1495         add_item(new BC_MenuItem(mode_to_text(MASK_SUBTRACT_ALPHA)));
1496 }
1497
1498 char* CWindowMaskMode::mode_to_text(int mode)
1499 {
1500         switch(mode)
1501         {
1502                 case MASK_MULTIPLY_ALPHA:
1503                         return _("Multiply alpha");
1504                         break;
1505
1506                 case MASK_SUBTRACT_ALPHA:
1507                         return _("Subtract alpha");
1508                         break;
1509         }
1510
1511         return _("Subtract alpha");
1512 }
1513
1514 int CWindowMaskMode::text_to_mode(char *text)
1515 {
1516         if(!strcasecmp(text, _("Multiply alpha")))
1517                 return MASK_MULTIPLY_ALPHA;
1518         else
1519         if(!strcasecmp(text, _("Subtract alpha")))
1520                 return MASK_SUBTRACT_ALPHA;
1521
1522         return MASK_SUBTRACT_ALPHA;
1523 }
1524
1525 int CWindowMaskMode::handle_event()
1526 {
1527         MaskAutos *autos;
1528         MaskAuto *keyframe;
1529         Track *track;
1530         MaskPoint *point;
1531         SubMask *mask;
1532 // Get existing keyframe
1533         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1534         if(track)
1535         {
1536                 mwindow->undo->update_undo_before(_("mask mode"), 0);
1537 #ifdef USE_KEYFRAME_SPANNING
1538 // Create temp keyframe
1539                 MaskAuto temp_keyframe(mwindow->edl, autos);
1540                 temp_keyframe.copy_data(keyframe);
1541 // Update parameter
1542                 temp_keyframe.mode = text_to_mode(get_text());
1543 // Commit change to span of keyframes
1544                 autos->update_parameter(&temp_keyframe);
1545 #else
1546                 ((MaskAuto*)autos->default_auto)->mode =
1547                         text_to_mode(get_text());
1548 #endif
1549                 mwindow->undo->update_undo_after(_("mask mode"), LOAD_AUTOMATION);
1550         }
1551
1552 //printf("CWindowMaskMode::handle_event 1\n");
1553         gui->update_preview();
1554         return 1;
1555 }
1556
1557
1558
1559
1560
1561
1562
1563
1564 CWindowMaskDelete::CWindowMaskDelete(MWindow *mwindow,
1565         CWindowToolGUI *gui,
1566         int x,
1567         int y)
1568  : BC_GenericButton(x, y, _("Delete"))
1569 {
1570         this->mwindow = mwindow;
1571         this->gui = gui;
1572 }
1573
1574 int CWindowMaskDelete::handle_event()
1575 {
1576         MaskAutos *autos;
1577         MaskAuto *keyframe;
1578         Track *track;
1579         MaskPoint *point;
1580         SubMask *mask;
1581         int total_points = 0;
1582
1583 // Get existing keyframe
1584         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1585
1586         if(track)
1587         {
1588                 mwindow->undo->update_undo_before(_("mask delete"), 0);
1589
1590 #ifdef USE_KEYFRAME_SPANNING
1591 // Create temp keyframe
1592                 MaskAuto temp_keyframe(mwindow->edl, autos);
1593                 temp_keyframe.copy_data(keyframe);
1594 // Update parameter
1595                 SubMask *submask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
1596                 if( shift_down() )
1597                         submask->points.remove_all_objects();
1598
1599                 for(int i = mwindow->cwindow->gui->affected_point;
1600                         i < submask->points.total - 1;
1601                         i++)
1602                 {
1603                         *submask->points.values[i] = *submask->points.values[i + 1];
1604                 }
1605
1606                 if(submask->points.total)
1607                 {
1608                         submask->points.remove_object(
1609                                 submask->points.values[submask->points.total - 1]);
1610                 }
1611                 total_points = submask->points.total;
1612
1613 // Commit change to span of keyframes
1614                 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe);
1615 #else
1616                 for(MaskAuto *current = (MaskAuto*)autos->default_auto;
1617                         current; )
1618                 {
1619                         SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1620                         if( shift_down() )
1621                                 submask->points.remove_all_objects();
1622
1623                         for(int i = mwindow->cwindow->gui->affected_point;
1624                                 i < submask->points.total - 1;
1625                                 i++)
1626                         {
1627                                 *submask->points.values[i] = *submask->points.values[i + 1];
1628                         }
1629
1630                         if(submask->points.total)
1631                         {
1632                                 submask->points.remove_object(
1633                                         submask->points.values[submask->points.total - 1]);
1634                         }
1635                         total_points = submask->points.total;
1636
1637                         if(current == (MaskAuto*)autos->default_auto)
1638                                 current = (MaskAuto*)autos->first;
1639                         else
1640                                 current = (MaskAuto*)NEXT;
1641                 }
1642 #endif
1643                 if( mwindow->cwindow->gui->affected_point >= total_points )
1644                         mwindow->cwindow->gui->affected_point =
1645                                 total_points > 0 ? total_points-1 : 0;
1646
1647                 gui->update();
1648                 gui->update_preview();
1649                 mwindow->undo->update_undo_after(_("mask delete"), LOAD_AUTOMATION);
1650         }
1651
1652
1653         return 1;
1654 }
1655
1656 int CWindowMaskDelete::keypress_event()
1657 {
1658         if(get_keypress() == BACKSPACE ||
1659                 get_keypress() == DELETE)
1660                 return handle_event();
1661         return 0;
1662 }
1663
1664
1665 // CWindowMaskCycleNext::CWindowMaskCycleNext(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1666 //  : BC_GenericButton(x, y, _("Cycle next"))
1667 // {
1668 //      this->mwindow = mwindow;
1669 //      this->gui = gui;
1670 // }
1671 // int CWindowMaskCycleNext::handle_event()
1672 // {
1673 //      MaskAuto *keyframe;
1674 //      MaskAutos *autos;
1675 //      Track *track;
1676 //      MaskPoint *point;
1677 //      SubMask *mask;
1678 //      ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1679 //
1680 //      MaskPoint *temp;
1681 //
1682 // // Should apply to all keyframes
1683 //      if(keyframe && mask->points.total)
1684 //      {
1685 //              temp = mask->points.values[0];
1686 //
1687 //              for(int i = 0; i < mask->points.total - 1; i++)
1688 //              {
1689 //                      mask->points.values[i] = mask->points.values[i + 1];
1690 //              }
1691 //              mask->points.values[mask->points.total - 1] = temp;
1692 //
1693 //              mwindow->cwindow->gui->affected_point--;
1694 //              if(mwindow->cwindow->gui->affected_point < 0)
1695 //                      mwindow->cwindow->gui->affected_point = mask->points.total - 1;
1696 //
1697 //              gui->update();
1698 //              gui->update_preview();
1699 //      }
1700 //
1701 //      return 1;
1702 // }
1703 //
1704 // CWindowMaskCyclePrev::CWindowMaskCyclePrev(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1705 //  : BC_GenericButton(x, y, _("Cycle prev"))
1706 // {
1707 //      this->mwindow = mwindow;
1708 //      this->gui = gui;
1709 // }
1710 // int CWindowMaskCyclePrev::handle_event()
1711 // {
1712 //      MaskAuto *keyframe;
1713 //      MaskAutos *autos;
1714 //      Track *track;
1715 //      MaskPoint *point;
1716 //      SubMask *mask;
1717 //      ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1718 //
1719 // // Should apply to all keyframes
1720 //      MaskPoint *temp;
1721 //      if(keyframe && mask->points.total)
1722 //      {
1723 //              temp = mask->points.values[mask->points.total - 1];
1724 //
1725 //              for(int i = mask->points.total - 1; i > 0; i--)
1726 //              {
1727 //                      mask->points.values[i] = mask->points.values[i - 1];
1728 //              }
1729 //              mask->points.values[0] = temp;
1730 //
1731 //              mwindow->cwindow->gui->affected_point++;
1732 //              if(mwindow->cwindow->gui->affected_point >= mask->points.total)
1733 //                      mwindow->cwindow->gui->affected_point = 0;
1734 //
1735 //              gui->update();
1736 //              gui->update_preview();
1737 //      }
1738 //      return 1;
1739 // }
1740
1741
1742 CWindowMaskNumber::CWindowMaskNumber(MWindow *mwindow,
1743         CWindowToolGUI *gui,
1744         int x,
1745         int y)
1746  : BC_TumbleTextBox(gui,
1747                 (int64_t)mwindow->edl->session->cwindow_mask,
1748                 (int64_t)0,
1749                 (int64_t)SUBMASKS - 1,
1750                 x,
1751                 y,
1752                 100)
1753 {
1754         this->mwindow = mwindow;
1755         this->gui = gui;
1756 }
1757
1758 CWindowMaskNumber::~CWindowMaskNumber()
1759 {
1760 }
1761
1762 int CWindowMaskNumber::handle_event()
1763 {
1764         mwindow->edl->session->cwindow_mask = atol(get_text());
1765         gui->update();
1766         gui->update_preview();
1767         return 1;
1768 }
1769
1770
1771 CWindowMaskAffectedPoint::CWindowMaskAffectedPoint(MWindow *mwindow,
1772         CWindowToolGUI *gui, int x, int y)
1773  : BC_TumbleTextBox(gui,
1774                 (int64_t)mwindow->cwindow->gui->affected_point,
1775                 (int64_t)0, INT64_MAX, x, y, 100)
1776 {
1777         this->mwindow = mwindow;
1778         this->gui = gui;
1779 }
1780
1781 CWindowMaskAffectedPoint::~CWindowMaskAffectedPoint()
1782 {
1783 }
1784
1785 int CWindowMaskAffectedPoint::handle_event()
1786 {
1787         int total_points = 0;
1788         int affected_point = atol(get_text());
1789         Track *track = mwindow->cwindow->calculate_affected_track();
1790         if(track) {
1791                 MaskAutos *autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
1792                 MaskAuto *keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(autos, 0);
1793                 if( keyframe ) {
1794                         SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
1795                         total_points = mask->points.size();
1796                 }
1797         }
1798         int active_point = affected_point;
1799         if( affected_point >= total_points )
1800                 affected_point = total_points - 1;
1801         else if( affected_point < 0 )
1802                 affected_point = 0;
1803         if( active_point != affected_point )
1804                 update((int64_t)affected_point);
1805         mwindow->cwindow->gui->affected_point = affected_point;
1806         gui->update();
1807         gui->update_preview();
1808         return 1;
1809 }
1810
1811
1812
1813
1814
1815 CWindowMaskFeather::CWindowMaskFeather(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1816  : BC_TumbleTextBox(gui,
1817                 (int64_t)0,
1818                 (int64_t)0,
1819                 (int64_t)0xff,
1820                 x,
1821                 y,
1822                 100)
1823 {
1824         this->mwindow = mwindow;
1825         this->gui = gui;
1826 }
1827 CWindowMaskFeather::~CWindowMaskFeather()
1828 {
1829 }
1830 int CWindowMaskFeather::handle_event()
1831 {
1832         MaskAutos *autos;
1833         MaskAuto *keyframe;
1834         Track *track;
1835         MaskPoint *point;
1836         SubMask *mask;
1837 #ifdef USE_KEYFRAME_SPANNING
1838         int create_it = 0;
1839 #else
1840         int create_it = 1;
1841 #endif
1842
1843         mwindow->undo->update_undo_before(_("mask feather"), this);
1844
1845 // Get existing keyframe
1846         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe,
1847                         mask, point, create_it);
1848
1849         if(track)
1850         {
1851 #ifdef USE_KEYFRAME_SPANNING
1852 // Create temp keyframe
1853                 MaskAuto temp_keyframe(mwindow->edl, autos);
1854                 temp_keyframe.copy_data(keyframe);
1855 // Update parameter
1856                 temp_keyframe.feather = atof(get_text());
1857 // Commit change to span of keyframes
1858                 autos->update_parameter(&temp_keyframe);
1859 #else
1860                 keyframe->feather = atof(get_text());
1861 #endif
1862
1863                 gui->update_preview();
1864         }
1865
1866         mwindow->undo->update_undo_after(_("mask feather"), LOAD_AUTOMATION);
1867         return 1;
1868 }
1869
1870
1871 CWindowMaskValue::CWindowMaskValue(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1872  : BC_ISlider(x,
1873                         y,
1874                         0,
1875                         200,
1876                         200,
1877                         0,
1878                         100,
1879                         0)
1880 {
1881         this->mwindow = mwindow;
1882         this->gui = gui;
1883 }
1884
1885 CWindowMaskValue::~CWindowMaskValue()
1886 {
1887 }
1888
1889 int CWindowMaskValue::handle_event()
1890 {
1891         MaskAutos *autos;
1892         MaskAuto *keyframe;
1893         Track *track;
1894         MaskPoint *point;
1895         SubMask *mask;
1896 #ifdef USE_KEYFRAME_SPANNING
1897         int create_it = 0;
1898 #else
1899         int create_it = 1;
1900 #endif
1901
1902         mwindow->undo->update_undo_before(_("mask value"), this);
1903         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe,
1904                 mask, point, create_it);
1905
1906         if(track)
1907         {
1908 #ifdef USE_KEYFRAME_SPANNING
1909 // Create temp keyframe
1910                 MaskAuto temp_keyframe(mwindow->edl, autos);
1911                 temp_keyframe.copy_data(keyframe);
1912 // Update parameter
1913                 temp_keyframe.value = get_value();
1914 // Commit change to span of keyframes
1915                 autos->update_parameter(&temp_keyframe);
1916 #else
1917                 keyframe->value = get_value();
1918 #endif
1919         }
1920
1921         gui->update_preview();
1922         mwindow->undo->update_undo_after(_("mask value"), LOAD_AUTOMATION);
1923         return 1;
1924 }
1925
1926
1927 CWindowMaskBeforePlugins::CWindowMaskBeforePlugins(CWindowToolGUI *gui, int x, int y)
1928  : BC_CheckBox(x,
1929         y,
1930         1,
1931         _("Apply mask before plugins"))
1932 {
1933         this->gui = gui;
1934 }
1935
1936 int CWindowMaskBeforePlugins::handle_event()
1937 {
1938         Track *track;
1939         MaskAutos *autos;
1940         MaskAuto *keyframe;
1941         SubMask *mask;
1942         MaskPoint *point;
1943         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 1);
1944
1945         if (keyframe) {
1946                 keyframe->apply_before_plugins = get_value();
1947                 gui->update_preview();
1948         }
1949         return 1;
1950 }
1951
1952
1953 CWindowDisableOpenGLMasking::CWindowDisableOpenGLMasking(CWindowToolGUI *gui, int x, int y)
1954  : BC_CheckBox(x, y, 1, _("Disable OpenGL masking"))
1955 {
1956         this->gui = gui;
1957 }
1958
1959 int CWindowDisableOpenGLMasking::handle_event()
1960 {
1961         Track *track;
1962         MaskAutos *autos;
1963         MaskAuto *keyframe;
1964         SubMask *mask;
1965         MaskPoint *point;
1966         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 1);
1967
1968         if (keyframe) {
1969                 keyframe->disable_opengl_masking = get_value();
1970                 gui->update_preview();
1971         }
1972         return 1;
1973 }
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983 CWindowMaskGUI::CWindowMaskGUI(MWindow *mwindow, CWindowTool *thread)
1984  : CWindowToolGUI(mwindow, thread,
1985         _(PROGRAM_NAME ": Mask"), 330, 320)
1986 {
1987         this->mwindow = mwindow;
1988         this->thread = thread;
1989         number = 0;
1990         active_point = 0;
1991         feather = 0;
1992 }
1993 CWindowMaskGUI::~CWindowMaskGUI()
1994 {
1995         lock_window("CWindowMaskGUI::~CWindowMaskGUI");
1996         delete number;
1997         delete active_point;
1998         delete feather;
1999         unlock_window();
2000 }
2001
2002 void CWindowMaskGUI::create_objects()
2003 {
2004         int x = 10, y = 10, margin = mwindow->theme->widget_border;
2005         //MaskAuto *keyframe = 0;
2006         //Track *track = mwindow->cwindow->calculate_affected_track();
2007         //if(track)
2008         //      keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(track->automation->autos[AUTOMATION_MASK], 0);
2009
2010         lock_window("CWindowMaskGUI::create_objects");
2011         BC_Title *title;
2012         add_subwindow(title = new BC_Title(x, y, _("Mode:")));
2013         add_subwindow(mode = new CWindowMaskMode(mwindow,
2014                 this, x + title->get_w() + margin, y, ""));
2015         mode->create_objects();
2016         y += mode->get_h() + margin;
2017         add_subwindow(title = new BC_Title(x, y, _("Value:")));
2018         add_subwindow(value = new CWindowMaskValue(mwindow, this, x + title->get_w() + margin, y));
2019         y += value->get_h() + margin;
2020         add_subwindow(delete_point = new CWindowMaskDelete(mwindow, this, x, y));
2021         int x1 = x + delete_point->get_w() + 2*margin;
2022         add_subwindow(title = new BC_Title(x1, y, _("Point:")));
2023         x1 += title->get_w() + margin;
2024         active_point = new CWindowMaskAffectedPoint(mwindow, this, x1, y);
2025         active_point->create_objects();
2026         y += delete_point->get_h() + margin;
2027         add_subwindow(title = new BC_Title(x, y, _("Mask number:")));
2028         number = new CWindowMaskNumber(mwindow,
2029                 this, x + title->get_w() + margin, y);
2030         number->create_objects();
2031         y += number->get_h() + margin;
2032         add_subwindow(title = new BC_Title(x, y, _("Feather:")));
2033         feather = new CWindowMaskFeather(mwindow,
2034                 this, x + title->get_w() + margin, y);
2035         feather->create_objects();
2036         y += feather->get_h() + margin;
2037         add_subwindow(title = new BC_Title(x, y, "X:"));
2038         x += title->get_w() + margin;
2039         this->x = new CWindowCoord(this, x, y, (float)0.0);
2040         this->x->create_objects();
2041         x += this->x->get_w() + margin;
2042         add_subwindow(title = new BC_Title(x, y, "Y:"));
2043         x += title->get_w() + margin;
2044         this->y = new CWindowCoord(this, x, y, (float)0.0);
2045         this->y->create_objects();
2046
2047         x = 10;
2048         y += this->y->get_h() + margin;
2049         add_subwindow(title = new BC_Title(x, y, _("Press Shift to move an end point")));
2050         y += title->get_h() + margin;
2051         add_subwindow(title = new BC_Title(x, y, _("Press Ctrl to move a control point")));
2052         y += title->get_h() + margin;
2053         add_subwindow(title = new BC_Title(x, y, _("Shift+click Delete to delete the mask")));
2054         y += title->get_h() + margin;
2055         add_subwindow(title = new BC_Title(x, y, _("Press Alt to translate the mask")));
2056         y += 30;
2057
2058         add_subwindow(this->apply_before_plugins = new CWindowMaskBeforePlugins(this, 10, y));
2059         y += this->apply_before_plugins->get_h() + margin;
2060         add_subwindow(this->disable_opengl_masking = new CWindowDisableOpenGLMasking(this, 10, y));
2061
2062         update();
2063         unlock_window();
2064 }
2065
2066 void CWindowMaskGUI::get_keyframe(Track* &track,
2067         MaskAutos* &autos,
2068         MaskAuto* &keyframe,
2069         SubMask* &mask,
2070         MaskPoint* &point,
2071         int create_it)
2072 {
2073         autos = 0;
2074         keyframe = 0;
2075
2076         track = mwindow->cwindow->calculate_affected_track();
2077         if(track)
2078         {
2079                 autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
2080                 keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(
2081                         autos,
2082                         create_it);
2083         }
2084
2085         if(keyframe)
2086                 mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
2087         else
2088                 mask = 0;
2089
2090         point = 0;
2091         if(keyframe)
2092         {
2093                 if(mwindow->cwindow->gui->affected_point < mask->points.total &&
2094                         mwindow->cwindow->gui->affected_point >= 0)
2095                 {
2096                         point = mask->points.values[mwindow->cwindow->gui->affected_point];
2097                 }
2098         }
2099 }
2100
2101 void CWindowMaskGUI::update()
2102 {
2103         Track *track;
2104         MaskAutos *autos;
2105         MaskAuto *keyframe;
2106         SubMask *mask;
2107         MaskPoint *point;
2108 //printf("CWindowMaskGUI::update 1\n");
2109         get_keyframe(track, autos, keyframe, mask, point, 0);
2110
2111         double position = mwindow->edl->local_session->get_selectionstart(1);
2112         position = mwindow->edl->align_to_frame(position, 0);
2113         if(track)
2114         {
2115                 int64_t position_i = track->to_units(position, 0);
2116
2117                 if(point)
2118                 {
2119                         x->update(point->x);
2120                         y->update(point->y);
2121                 }
2122
2123                 if(mask)
2124                 {
2125                         feather->update((int64_t)autos->get_feather(position_i, PLAY_FORWARD));
2126                         value->update((int64_t)autos->get_value(position_i, PLAY_FORWARD));
2127                         apply_before_plugins->update((int64_t)keyframe->apply_before_plugins);
2128                         disable_opengl_masking->update((int64_t)keyframe->disable_opengl_masking);
2129                 }
2130         }
2131
2132 //printf("CWindowMaskGUI::update 1\n");
2133         active_point->update((int64_t)mwindow->cwindow->gui->affected_point);
2134         number->update((int64_t)mwindow->edl->session->cwindow_mask);
2135
2136 //printf("CWindowMaskGUI::update 1\n");
2137         if(track)
2138         {
2139 #ifdef USE_KEYFRAME_SPANNING
2140                 mode->set_text(
2141                         CWindowMaskMode::mode_to_text(keyframe->mode));
2142 #else
2143                 mode->set_text(
2144                         CWindowMaskMode::mode_to_text(((MaskAuto*)autos->default_auto)->mode));
2145 #endif
2146         }
2147 //printf("CWindowMaskGUI::update 2\n");
2148 }
2149
2150 void CWindowMaskGUI::handle_event()
2151 {
2152         Track *track;
2153         MaskAuto *keyframe;
2154         MaskAutos *autos;
2155         SubMask *mask;
2156         MaskPoint *point;
2157         get_keyframe(track, autos, keyframe, mask, point, 0);
2158
2159         mwindow->undo->update_undo_before(_("mask point"), this);
2160
2161         if(point)
2162         {
2163 #ifdef USE_KEYFRAME_SPANNING
2164 // Create temp keyframe
2165                 MaskAuto temp_keyframe(mwindow->edl, autos);
2166                 temp_keyframe.copy_data(keyframe);
2167 // Get affected point in temp keyframe
2168                 mask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
2169                 if(mwindow->cwindow->gui->affected_point < mask->points.total &&
2170                         mwindow->cwindow->gui->affected_point >= 0)
2171                 {
2172                         point = mask->points.values[mwindow->cwindow->gui->affected_point];
2173                 }
2174
2175                 if(point)
2176                 {
2177                         point->x = atof(x->get_text());
2178                         point->y = atof(y->get_text());
2179 // Commit to spanned keyframes
2180                         autos->update_parameter(&temp_keyframe);
2181                 }
2182 #else
2183                 point->x = atof(x->get_text());
2184                 point->y = atof(y->get_text());
2185 #endif
2186         }
2187
2188         update_preview();
2189         mwindow->undo->update_undo_after(_("mask point"), LOAD_AUTOMATION);
2190 }
2191
2192 void CWindowMaskGUI::update_preview()
2193 {
2194         unlock_window();
2195         CWindowGUI *cgui = mwindow->cwindow->gui;
2196         cgui->lock_window("CWindowMaskGUI::update_preview");
2197         cgui->sync_parameters(CHANGE_PARAMS, 0, 1);
2198         cgui->unlock_window();
2199         lock_window("CWindowMaskGUI::update_preview");
2200 }
2201
2202
2203 CWindowRulerGUI::CWindowRulerGUI(MWindow *mwindow, CWindowTool *thread)
2204  : CWindowToolGUI(mwindow,
2205         thread,
2206         _(PROGRAM_NAME ": Ruler"),
2207         320,
2208         240)
2209 {
2210 }
2211
2212 CWindowRulerGUI::~CWindowRulerGUI()
2213 {
2214 }
2215
2216 void CWindowRulerGUI::create_objects()
2217 {
2218         int x = 10, y = 10, x1 = 100;
2219         BC_Title *title;
2220
2221         lock_window("CWindowRulerGUI::create_objects");
2222         add_subwindow(title = new BC_Title(x, y, _("Current:")));
2223         add_subwindow(current = new BC_TextBox(x1, y, 200, 1, ""));
2224         y += title->get_h() + 5;
2225         add_subwindow(title = new BC_Title(x, y, _("Point 1:")));
2226         add_subwindow(point1 = new BC_TextBox(x1, y, 200, 1, ""));
2227         y += title->get_h() + 5;
2228         add_subwindow(title = new BC_Title(x, y, _("Point 2:")));
2229         add_subwindow(point2 = new BC_TextBox(x1, y, 200, 1, ""));
2230         y += title->get_h() + 5;
2231         add_subwindow(title = new BC_Title(x, y, _("Deltas:")));
2232         add_subwindow(deltas = new BC_TextBox(x1, y, 200, 1, ""));
2233         y += title->get_h() + 5;
2234         add_subwindow(title = new BC_Title(x, y, _("Distance:")));
2235         add_subwindow(distance = new BC_TextBox(x1, y, 200, 1, ""));
2236         y += title->get_h() + 5;
2237         add_subwindow(title = new BC_Title(x, y, _("Angle:")));
2238         add_subwindow(angle = new BC_TextBox(x1, y, 200, 1, ""));
2239         y += title->get_h() + 10;
2240         char string[BCTEXTLEN];
2241         sprintf(string,
2242                  _("Press Ctrl to lock ruler to the\nnearest 45%c%c angle."),
2243                 0xc2, 0xb0); // degrees utf
2244         add_subwindow(title = new BC_Title(x,
2245                 y,
2246                 string));
2247         y += title->get_h() + 10;
2248         sprintf(string, _("Press Alt to translate the ruler."));
2249         add_subwindow(title = new BC_Title(x,
2250                 y,
2251                 string));
2252         update();
2253         unlock_window();
2254 }
2255
2256 void CWindowRulerGUI::update()
2257 {
2258         char string[BCTEXTLEN];
2259         int cx = mwindow->session->cwindow_output_x;
2260         int cy = mwindow->session->cwindow_output_y;
2261         sprintf(string, "%d, %d", cx, cy);
2262         current->update(string);
2263         double x1 = mwindow->edl->session->ruler_x1;
2264         double y1 = mwindow->edl->session->ruler_y1;
2265         sprintf(string, "%.0f, %.0f", x1, y1);
2266         point1->update(string);
2267         double x2 = mwindow->edl->session->ruler_x2;
2268         double y2 = mwindow->edl->session->ruler_y2;
2269         sprintf(string, "%.0f, %.0f", x2, y2);
2270         point2->update(string);
2271         double dx = x2 - x1, dy = y2 - y1;
2272         sprintf(string, "%s%.0f, %s%.0f", (dx>=0? "+":""), dx, (dy>=0? "+":""), dy);
2273         deltas->update(string);
2274         double d = sqrt(dx*dx + dy*dy);
2275         sprintf(string, _("%0.01f pixels"), d);
2276         distance->update(string);
2277         double a = d > 0 ? (atan2(-dy, dx) * 180/M_PI) : 0.;
2278         sprintf(string, "%0.02f %c%c", a, 0xc2, 0xb0);
2279         angle->update(string);
2280 }
2281
2282 void CWindowRulerGUI::handle_event()
2283 {
2284 }
2285
2286
2287
2288