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