723088eb2e877a5935d763fab3ac55e2d6cdcebb
[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                 N_("\"smooth\" Curve on current Camera Keyframes")
593         };
594 const _CVD Camera_Crv_Linear =
595         {       FloatAuto::LINEAR,
596                 true,
597                 "tan_linear",
598                 N_("\"linear\" Curve on current Camera Keyframes")
599         };
600 const _CVD Projector_Crv_Smooth =
601         {       FloatAuto::SMOOTH,
602                 false,
603                 "tan_smooth",
604                 N_("\"smooth\" Curve on current Projector Keyframes")
605         };
606 const _CVD Projector_Crv_Linear =
607         {       FloatAuto::LINEAR,
608                 false,
609                 "tan_linear",
610                 N_("\"linear\" Curve on current Projector Keyframes")
611         };
612
613 // Implementation Class für Keyframe Curve Mode buttons
614 //
615 // This button reflects the state of the "current" keyframe
616 // (the nearest keyframe on the left) for all three automation
617 // lines together. Clicking on this button (re)sets the curve
618 // mode for the three "current" keyframes simultanously, but
619 // never creates a new keyframe.
620 //
621 class CWindowCurveToggle : public BC_Toggle
622 {
623 public:
624         CWindowCurveToggle(_CVD mode, MWindow *mwindow, CWindowToolGUI *gui, int x, int y);
625         void check_toggle_state(FloatAuto *x, FloatAuto *y, FloatAuto *z);
626         int handle_event();
627 private:
628         _CVD cfg;
629         MWindow *mwindow;
630         CWindowToolGUI *gui;
631 };
632
633
634 CWindowCurveToggle::CWindowCurveToggle(_CVD mode, MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
635  : BC_Toggle(x, y, mwindow->theme->get_image_set(mode.icon_id), false),
636    cfg(mode)
637 {
638         this->gui = gui;
639         this->mwindow = mwindow;
640         set_tooltip(_(cfg.tooltip));
641 }
642
643 void CWindowCurveToggle::check_toggle_state(FloatAuto *x, FloatAuto *y, FloatAuto *z)
644 {
645 // the toggle state is only set to ON if all
646 // three automation lines have the same curve mode.
647 // For mixed states the toggle stays off.
648         set_value( x->curve_mode == this->cfg.mode &&
649                    y->curve_mode == this->cfg.mode &&
650                    z->curve_mode == this->cfg.mode
651                  ,true // redraw to show new state
652                  );
653 }
654
655 int CWindowCurveToggle::handle_event()
656 {
657         FloatAuto *x=0, *y=0, *z=0;
658         Track *track = mwindow->cwindow->calculate_affected_track();
659
660         if(track)
661         {       mwindow->cwindow->calculate_affected_autos(&x, &y, &z,
662                         track, cfg.use_camera, 0,0,0); // don't create new keyframe
663
664                 if(x)   x->change_curve_mode(cfg.mode);
665                 if(y)   y->change_curve_mode(cfg.mode);
666                 if(z)   z->change_curve_mode(cfg.mode);
667
668                 gui->update();
669                 gui->update_preview();
670         }
671
672         return 1;
673 }
674
675
676 CWindowCameraGUI::CWindowCameraGUI(MWindow *mwindow, CWindowTool *thread)
677  : CWindowToolGUI(mwindow,
678         thread,
679         _(PROGRAM_NAME ": Camera"),
680         170,
681         170)
682 {
683 }
684 CWindowCameraGUI::~CWindowCameraGUI()
685 {
686 }
687
688 void CWindowCameraGUI::create_objects()
689 {
690         int x = 10, y = 10, x1;
691         Track *track = mwindow->cwindow->calculate_affected_track();
692         FloatAuto *x_auto = 0;
693         FloatAuto *y_auto = 0;
694         FloatAuto *z_auto = 0;
695         BC_Title *title;
696         BC_Button *button;
697
698         lock_window("CWindowCameraGUI::create_objects");
699         if(track)
700         {
701                 mwindow->cwindow->calculate_affected_autos(&x_auto,
702                         &y_auto, &z_auto, track, 1, 0, 0, 0);
703         }
704
705         add_subwindow(title = new BC_Title(x, y, "X:"));
706         x += title->get_w();
707         this->x = new CWindowCoord(this, x, y,
708                 x_auto ? x_auto->get_value() : (float)0);
709         this->x->create_objects();
710
711
712         y += 30;
713         x = 10;
714         add_subwindow(title = new BC_Title(x, y, "Y:"));
715         x += title->get_w();
716         this->y = new CWindowCoord(this, x, y,
717                 y_auto ? y_auto->get_value() : (float)0);
718         this->y->create_objects();
719         y += 30;
720         x = 10;
721         add_subwindow(title = new BC_Title(x, y, "Z:"));
722         x += title->get_w();
723         this->z = new CWindowCoord(this, x, y,
724                 z_auto ? z_auto->get_value() : (float)1);
725         this->z->create_objects();
726         this->z->set_increment(0.01);
727
728         y += 30;
729         x1 = 10;
730         add_subwindow(button = new CWindowCameraLeft(mwindow, this, x1, y));
731         x1 += button->get_w();
732         add_subwindow(button = new CWindowCameraCenter(mwindow, this, x1, y));
733         x1 += button->get_w();
734         add_subwindow(button = new CWindowCameraRight(mwindow, this, x1, y));
735
736         y += button->get_h();
737         x1 = 10;
738         add_subwindow(button = new CWindowCameraTop(mwindow, this, x1, y));
739         x1 += button->get_w();
740         add_subwindow(button = new CWindowCameraMiddle(mwindow, this, x1, y));
741         x1 += button->get_w();
742         add_subwindow(button = new CWindowCameraBottom(mwindow, this, x1, y));
743 // additional Buttons to control the curve mode of the "current" keyframe
744         x1 += button->get_w() + 15;
745         add_subwindow(this->t_smooth = new CWindowCurveToggle(Camera_Crv_Smooth, mwindow, this, x1, y));
746         x1 += button->get_w();
747         add_subwindow(this->t_linear = new CWindowCurveToggle(Camera_Crv_Linear, mwindow, this, x1, y));
748
749 // fill in current auto keyframe values, set toggle states.
750         this->update();
751         unlock_window();
752 }
753
754 void CWindowCameraGUI::update_preview()
755 {
756         mwindow->restart_brender();
757         mwindow->sync_parameters(CHANGE_PARAMS);
758
759         mwindow->cwindow->playback_engine->que->send_command(CURRENT_FRAME,
760                         CHANGE_NONE,
761                         mwindow->edl,
762                         1);
763         mwindow->gui->lock_window("CWindowCameraGUI::update_preview");
764         mwindow->gui->draw_overlays(1);
765         mwindow->gui->unlock_window();
766         mwindow->cwindow->gui->lock_window("CWindowCameraGUI::update_preview");
767         mwindow->cwindow->gui->canvas->draw_refresh();
768         mwindow->cwindow->gui->unlock_window();
769 }
770
771
772 void CWindowCameraGUI::handle_event()
773 {
774         FloatAuto *x_auto = 0;
775         FloatAuto *y_auto = 0;
776         FloatAuto *z_auto = 0;
777         Track *track = mwindow->cwindow->calculate_affected_track();
778         if(track)
779         {
780                 mwindow->undo->update_undo_before(_("camera"), this);
781                 if(event_caller == x)
782                 {
783                         x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
784                                 track->automation->autos[AUTOMATION_CAMERA_X],
785                                 1);
786                         if(x_auto)
787                         {
788                                 x_auto->set_value(atof(x->get_text()));
789                                 update();
790                                 update_preview();
791                         }
792                 }
793                 else
794                 if(event_caller == y)
795                 {
796                         y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
797                                 track->automation->autos[AUTOMATION_CAMERA_Y],
798                                 1);
799                         if(y_auto)
800                         {
801                                 y_auto->set_value(atof(y->get_text()));
802                                 update();
803                                 update_preview();
804                         }
805                 }
806                 else
807                 if(event_caller == z)
808                 {
809                         z_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
810                                 track->automation->autos[AUTOMATION_CAMERA_Z],
811                                 1);
812                         if(z_auto)
813                         {
814                                 float zoom = atof(z->get_text());
815                                 if(zoom > 10) zoom = 10;
816                                 else
817                                 if(zoom < 0) zoom = 0;
818         // Doesn't allow user to enter from scratch
819         //              if(zoom != atof(z->get_text()))
820         //                      z->update(zoom);
821
822                                 z_auto->set_value(zoom);
823                                 mwindow->gui->lock_window("CWindowCameraGUI::handle_event");
824                                 mwindow->gui->draw_overlays(1);
825                                 mwindow->gui->unlock_window();
826                                 update();
827                                 update_preview();
828                         }
829                 }
830
831                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
832         }
833 }
834
835 void CWindowCameraGUI::update()
836 {
837         FloatAuto *x_auto = 0;
838         FloatAuto *y_auto = 0;
839         FloatAuto *z_auto = 0;
840         Track *track = mwindow->cwindow->calculate_affected_track();
841
842         if(track)
843         {
844                 mwindow->cwindow->calculate_affected_autos(&x_auto,
845                         &y_auto,
846                         &z_auto,
847                         track,
848                         1,
849                         0,
850                         0,
851                         0);
852         }
853
854         if(x_auto)
855                 x->update(x_auto->get_value());
856         if(y_auto)
857                 y->update(y_auto->get_value());
858         if(z_auto)
859                 z->update(z_auto->get_value());
860
861         if( x_auto && y_auto && z_auto )
862         {
863                 t_smooth->check_toggle_state(x_auto, y_auto, z_auto);
864                 t_linear->check_toggle_state(x_auto, y_auto, z_auto);
865         }
866 }
867
868
869
870
871 CWindowCameraLeft::CWindowCameraLeft(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
872  : BC_Button(x, y, mwindow->theme->get_image_set("left_justify"))
873 {
874         this->gui = gui;
875         this->mwindow = mwindow;
876         set_tooltip(_("Left justify"));
877 }
878 int CWindowCameraLeft::handle_event()
879 {
880         FloatAuto *x_auto = 0;
881         FloatAuto *z_auto = 0;
882         Track *track = mwindow->cwindow->calculate_affected_track();
883         if(track)
884         {
885                 mwindow->cwindow->calculate_affected_autos(&x_auto,
886                         0,
887                         &z_auto,
888                         track,
889                         1,
890                         1,
891                         0,
892                         0);
893         }
894
895         if(x_auto && z_auto)
896         {
897                 int w = 0, h = 0;
898                 track->get_source_dimensions(
899                         mwindow->edl->local_session->get_selectionstart(1),
900                         w,
901                         h);
902
903                 if(w && h)
904                 {
905                         mwindow->undo->update_undo_before(_("camera"), 0);
906                         x_auto->set_value(
907                                 (double)track->track_w / z_auto->get_value() / 2 -
908                                 (double)w / 2);
909                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
910                         gui->update();
911                         gui->update_preview();
912                 }
913         }
914
915         return 1;
916 }
917
918
919 CWindowCameraCenter::CWindowCameraCenter(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
920  : BC_Button(x, y, mwindow->theme->get_image_set("center_justify"))
921 {
922         this->gui = gui;
923         this->mwindow = mwindow;
924         set_tooltip(_("Center horizontal"));
925 }
926 int CWindowCameraCenter::handle_event()
927 {
928         FloatAuto *x_auto = 0;
929         Track *track = mwindow->cwindow->calculate_affected_track();
930         if(track)
931                 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
932                         track->automation->autos[AUTOMATION_CAMERA_X],
933                         1);
934
935         if(x_auto)
936         {
937                 mwindow->undo->update_undo_before(_("camera"), 0);
938                 x_auto->set_value(0);
939                 gui->update();
940                 gui->update_preview();
941                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
942         }
943
944         return 1;
945 }
946
947
948 CWindowCameraRight::CWindowCameraRight(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
949  : BC_Button(x, y, mwindow->theme->get_image_set("right_justify"))
950 {
951         this->gui = gui;
952         this->mwindow = mwindow;
953         set_tooltip(_("Right justify"));
954 }
955 int CWindowCameraRight::handle_event()
956 {
957         FloatAuto *x_auto = 0;
958         FloatAuto *z_auto = 0;
959         Track *track = mwindow->cwindow->calculate_affected_track();
960         if(track)
961         {
962                 mwindow->cwindow->calculate_affected_autos(&x_auto,
963                         0,
964                         &z_auto,
965                         track,
966                         1,
967                         1,
968                         0,
969                         0);
970         }
971
972         if(x_auto && z_auto)
973         {
974                 int w = 0, h = 0;
975                 track->get_source_dimensions(
976                         mwindow->edl->local_session->get_selectionstart(1),
977                         w,
978                         h);
979
980                 if(w && h)
981                 {
982                         mwindow->undo->update_undo_before(_("camera"), 0);
983                         x_auto->set_value( -((double)track->track_w / z_auto->get_value() / 2 -
984                                 (double)w / 2));
985                         gui->update();
986                         gui->update_preview();
987                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
988                 }
989         }
990
991         return 1;
992 }
993
994
995 CWindowCameraTop::CWindowCameraTop(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
996  : BC_Button(x, y, mwindow->theme->get_image_set("top_justify"))
997 {
998         this->gui = gui;
999         this->mwindow = mwindow;
1000         set_tooltip(_("Top justify"));
1001 }
1002 int CWindowCameraTop::handle_event()
1003 {
1004         FloatAuto *y_auto = 0;
1005         FloatAuto *z_auto = 0;
1006         Track *track = mwindow->cwindow->calculate_affected_track();
1007         if(track)
1008         {
1009                 mwindow->cwindow->calculate_affected_autos(0,
1010                         &y_auto,
1011                         &z_auto,
1012                         track,
1013                         1,
1014                         0,
1015                         1,
1016                         0);
1017         }
1018
1019         if(y_auto && z_auto)
1020         {
1021                 int w = 0, h = 0;
1022                 track->get_source_dimensions(
1023                         mwindow->edl->local_session->get_selectionstart(1),
1024                         w,
1025                         h);
1026
1027                 if(w && h)
1028                 {
1029                         mwindow->undo->update_undo_before(_("camera"), 0);
1030                         y_auto->set_value((double)track->track_h / z_auto->get_value() / 2 -
1031                                 (double)h / 2);
1032                         gui->update();
1033                         gui->update_preview();
1034                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1035                 }
1036         }
1037
1038         return 1;
1039 }
1040
1041
1042 CWindowCameraMiddle::CWindowCameraMiddle(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1043  : BC_Button(x, y, mwindow->theme->get_image_set("middle_justify"))
1044 {
1045         this->gui = gui;
1046         this->mwindow = mwindow;
1047         set_tooltip(_("Center vertical"));
1048 }
1049 int CWindowCameraMiddle::handle_event()
1050 {
1051         FloatAuto *y_auto = 0;
1052         Track *track = mwindow->cwindow->calculate_affected_track();
1053         if(track)
1054                 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1055                         track->automation->autos[AUTOMATION_CAMERA_Y], 1);
1056
1057         if(y_auto)
1058         {
1059                 mwindow->undo->update_undo_before(_("camera"), 0);
1060                 y_auto->set_value(0);
1061                 gui->update();
1062                 gui->update_preview();
1063                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1064         }
1065
1066         return 1;
1067 }
1068
1069
1070 CWindowCameraBottom::CWindowCameraBottom(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1071  : BC_Button(x, y, mwindow->theme->get_image_set("bottom_justify"))
1072 {
1073         this->gui = gui;
1074         this->mwindow = mwindow;
1075         set_tooltip(_("Bottom justify"));
1076 }
1077 int CWindowCameraBottom::handle_event()
1078 {
1079         FloatAuto *y_auto = 0;
1080         FloatAuto *z_auto = 0;
1081         Track *track = mwindow->cwindow->calculate_affected_track();
1082         if(track)
1083         {
1084                 mwindow->cwindow->calculate_affected_autos(0,
1085                         &y_auto,
1086                         &z_auto,
1087                         track,
1088                         1,
1089                         0,
1090                         1,
1091                         0);
1092         }
1093
1094         if(y_auto && z_auto)
1095         {
1096                 int w = 0, h = 0;
1097                 track->get_source_dimensions(
1098                         mwindow->edl->local_session->get_selectionstart(1),
1099                         w,
1100                         h);
1101
1102                 if(w && h)
1103                 {
1104                         mwindow->undo->update_undo_before(_("camera"), 0);
1105                         y_auto->set_value(-((double)track->track_h / z_auto->get_value() / 2 -
1106                                 (double)h / 2));
1107                         gui->update();
1108                         gui->update_preview();
1109                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1110                 }
1111         }
1112
1113         return 1;
1114 }
1115
1116
1117 CWindowProjectorGUI::CWindowProjectorGUI(MWindow *mwindow, CWindowTool *thread)
1118  : CWindowToolGUI(mwindow,
1119         thread,
1120         _(PROGRAM_NAME ": Projector"),
1121         170,
1122         170)
1123 {
1124 }
1125 CWindowProjectorGUI::~CWindowProjectorGUI()
1126 {
1127 }
1128 void CWindowProjectorGUI::create_objects()
1129 {
1130         int x = 10, y = 10, x1;
1131         Track *track = mwindow->cwindow->calculate_affected_track();
1132         FloatAuto *x_auto = 0;
1133         FloatAuto *y_auto = 0;
1134         FloatAuto *z_auto = 0;
1135         BC_Title *title;
1136         BC_Button *button;
1137
1138         lock_window("CWindowProjectorGUI::create_objects");
1139         if(track)
1140         {
1141                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1142                         &y_auto,
1143                         &z_auto,
1144                         track,
1145                         0,
1146                         0,
1147                         0,
1148                         0);
1149         }
1150
1151         add_subwindow(title = new BC_Title(x, y, "X:"));
1152         x += title->get_w();
1153         this->x = new CWindowCoord(this, x, y,
1154                 x_auto ? x_auto->get_value() : (float)0);
1155         this->x->create_objects();
1156         y += 30;
1157         x = 10;
1158         add_subwindow(title = new BC_Title(x, y, "Y:"));
1159         x += title->get_w();
1160         this->y = new CWindowCoord(this, x, y,
1161                 y_auto ? y_auto->get_value() : (float)0);
1162         this->y->create_objects();
1163         y += 30;
1164         x = 10;
1165         add_subwindow(title = new BC_Title(x, y, "Z:"));
1166         x += title->get_w();
1167         this->z = new CWindowCoord(this, x, y,
1168                 z_auto ? z_auto->get_value() : (float)1);
1169         this->z->create_objects();
1170         this->z->set_increment(0.01);
1171
1172         y += 30;
1173         x1 = 10;
1174         add_subwindow(button = new CWindowProjectorLeft(mwindow, this, x1, y));
1175         x1 += button->get_w();
1176         add_subwindow(button = new CWindowProjectorCenter(mwindow, this, x1, y));
1177         x1 += button->get_w();
1178         add_subwindow(button = new CWindowProjectorRight(mwindow, this, x1, y));
1179
1180         y += button->get_h();
1181         x1 = 10;
1182         add_subwindow(button = new CWindowProjectorTop(mwindow, this, x1, y));
1183         x1 += button->get_w();
1184         add_subwindow(button = new CWindowProjectorMiddle(mwindow, this, x1, y));
1185         x1 += button->get_w();
1186         add_subwindow(button = new CWindowProjectorBottom(mwindow, this, x1, y));
1187
1188 // additional Buttons to control the curve mode of the "current" keyframe
1189         x1 += button->get_w() + 15;
1190         add_subwindow(this->t_smooth = new CWindowCurveToggle(Projector_Crv_Smooth, mwindow, this, x1, y));
1191         x1 += button->get_w();
1192         add_subwindow(this->t_linear = new CWindowCurveToggle(Projector_Crv_Linear, mwindow, this, x1, y));
1193
1194 // fill in current auto keyframe values, set toggle states.
1195         this->update();
1196         unlock_window();
1197 }
1198
1199 void CWindowProjectorGUI::update_preview()
1200 {
1201         mwindow->restart_brender();
1202         mwindow->sync_parameters(CHANGE_PARAMS);
1203         mwindow->cwindow->playback_engine->que->send_command(CURRENT_FRAME,
1204                         CHANGE_NONE,
1205                         mwindow->edl,
1206                         1);
1207         // TODO: really need to lock the main window??
1208         mwindow->gui->lock_window("CWindowProjectorGUI::update_preview");
1209         mwindow->gui->draw_overlays(1);
1210         mwindow->gui->unlock_window();
1211         mwindow->cwindow->gui->lock_window("CWindowProjectorGUI::update_preview");
1212         mwindow->cwindow->gui->canvas->draw_refresh();
1213         mwindow->cwindow->gui->unlock_window();
1214 }
1215
1216 void CWindowProjectorGUI::handle_event()
1217 {
1218         FloatAuto *x_auto = 0;
1219         FloatAuto *y_auto = 0;
1220         FloatAuto *z_auto = 0;
1221         Track *track = mwindow->cwindow->calculate_affected_track();
1222
1223         if(track)
1224         {
1225                 mwindow->undo->update_undo_before(_("projector"), this);
1226                 if(event_caller == x)
1227                 {
1228                         x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1229                                 track->automation->autos[AUTOMATION_PROJECTOR_X],
1230                                 1);
1231                         if(x_auto)
1232                         {
1233                                 x_auto->set_value(atof(x->get_text()));
1234                                 update();
1235                                 update_preview();
1236                         }
1237                 }
1238                 else
1239                 if(event_caller == y)
1240                 {
1241                         y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1242                                 track->automation->autos[AUTOMATION_PROJECTOR_Y],
1243                                 1);
1244                         if(y_auto)
1245                         {
1246                                 y_auto->set_value(atof(y->get_text()));
1247                                 update();
1248                                 update_preview();
1249                         }
1250                 }
1251                 else
1252                 if(event_caller == z)
1253                 {
1254                         z_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1255                                 track->automation->autos[AUTOMATION_PROJECTOR_Z],
1256                                 1);
1257                         if(z_auto)
1258                         {
1259                                 float zoom = atof(z->get_text());
1260                                 if(zoom > 10000) zoom = 10000;
1261                                 else
1262                                 if(zoom < 0) zoom = 0;
1263 //                      if (zoom != atof(z->get_text()))
1264 //                              z->update(zoom);
1265                                 z_auto->set_value(zoom);
1266
1267                                 mwindow->gui->lock_window("CWindowProjectorGUI::handle_event");
1268                                 mwindow->gui->draw_overlays(1);
1269                                 mwindow->gui->unlock_window();
1270
1271                                 update();
1272                                 update_preview();
1273                         }
1274                 }
1275                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1276         }
1277 }
1278
1279 void CWindowProjectorGUI::update()
1280 {
1281         FloatAuto *x_auto = 0;
1282         FloatAuto *y_auto = 0;
1283         FloatAuto *z_auto = 0;
1284         Track *track = mwindow->cwindow->calculate_affected_track();
1285
1286         if(track)
1287         {
1288                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1289                         &y_auto,
1290                         &z_auto,
1291                         track,
1292                         0,
1293                         0,
1294                         0,
1295                         0);
1296         }
1297
1298         if(x_auto)
1299                 x->update(x_auto->get_value());
1300         if(y_auto)
1301                 y->update(y_auto->get_value());
1302         if(z_auto)
1303                 z->update(z_auto->get_value());
1304
1305         if( x_auto && y_auto && z_auto )
1306         {
1307                 t_smooth->check_toggle_state(x_auto, y_auto, z_auto);
1308                 t_linear->check_toggle_state(x_auto, y_auto, z_auto);
1309         }
1310 }
1311
1312 CWindowProjectorLeft::CWindowProjectorLeft(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1313  : BC_Button(x, y, mwindow->theme->get_image_set("left_justify"))
1314 {
1315         this->gui = gui;
1316         this->mwindow = mwindow;
1317         set_tooltip(_("Left justify"));
1318 }
1319 int CWindowProjectorLeft::handle_event()
1320 {
1321         FloatAuto *x_auto = 0;
1322         FloatAuto *z_auto = 0;
1323         Track *track = mwindow->cwindow->calculate_affected_track();
1324         if(track)
1325         {
1326                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1327                         0,
1328                         &z_auto,
1329                         track,
1330                         0,
1331                         1,
1332                         0,
1333                         0);
1334         }
1335         if(x_auto && z_auto)
1336         {
1337                 mwindow->undo->update_undo_before(_("projector"), 0);
1338                 x_auto->set_value( (double)track->track_w * z_auto->get_value() / 2 -
1339                         (double)mwindow->edl->session->output_w / 2 );
1340                 gui->update();
1341                 gui->update_preview();
1342                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1343         }
1344
1345         return 1;
1346 }
1347
1348
1349 CWindowProjectorCenter::CWindowProjectorCenter(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1350  : BC_Button(x, y, mwindow->theme->get_image_set("center_justify"))
1351 {
1352         this->gui = gui;
1353         this->mwindow = mwindow;
1354         set_tooltip(_("Center horizontal"));
1355 }
1356 int CWindowProjectorCenter::handle_event()
1357 {
1358         FloatAuto *x_auto = 0;
1359         Track *track = mwindow->cwindow->calculate_affected_track();
1360         if(track)
1361                 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1362                         track->automation->autos[AUTOMATION_PROJECTOR_X],
1363                         1);
1364
1365         if(x_auto)
1366         {
1367                 mwindow->undo->update_undo_before(_("projector"), 0);
1368                 x_auto->set_value(0);
1369                 gui->update();
1370                 gui->update_preview();
1371                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1372         }
1373
1374         return 1;
1375 }
1376
1377
1378 CWindowProjectorRight::CWindowProjectorRight(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1379  : BC_Button(x, y, mwindow->theme->get_image_set("right_justify"))
1380 {
1381         this->gui = gui;
1382         this->mwindow = mwindow;
1383         set_tooltip(_("Right justify"));
1384 }
1385 int CWindowProjectorRight::handle_event()
1386 {
1387         FloatAuto *x_auto = 0;
1388         FloatAuto *z_auto = 0;
1389         Track *track = mwindow->cwindow->calculate_affected_track();
1390         if(track)
1391         {
1392                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1393                         0,
1394                         &z_auto,
1395                         track,
1396                         0,
1397                         1,
1398                         0,
1399                         0);
1400         }
1401
1402         if(x_auto && z_auto)
1403         {
1404                 mwindow->undo->update_undo_before(_("projector"), 0);
1405                 x_auto->set_value( -((double)track->track_w * z_auto->get_value() / 2 -
1406                         (double)mwindow->edl->session->output_w / 2));
1407                 gui->update();
1408                 gui->update_preview();
1409                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1410         }
1411
1412         return 1;
1413 }
1414
1415
1416 CWindowProjectorTop::CWindowProjectorTop(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1417  : BC_Button(x, y, mwindow->theme->get_image_set("top_justify"))
1418 {
1419         this->gui = gui;
1420         this->mwindow = mwindow;
1421         set_tooltip(_("Top justify"));
1422 }
1423 int CWindowProjectorTop::handle_event()
1424 {
1425         FloatAuto *y_auto = 0;
1426         FloatAuto *z_auto = 0;
1427         Track *track = mwindow->cwindow->calculate_affected_track();
1428         if(track)
1429         {
1430                 mwindow->cwindow->calculate_affected_autos(0,
1431                         &y_auto,
1432                         &z_auto,
1433                         track,
1434                         0,
1435                         0,
1436                         1,
1437                         0);
1438         }
1439
1440         if(y_auto && z_auto)
1441         {
1442                 mwindow->undo->update_undo_before(_("projector"), 0);
1443                 y_auto->set_value( (double)track->track_h * z_auto->get_value() / 2 -
1444                         (double)mwindow->edl->session->output_h / 2 );
1445                 gui->update();
1446                 gui->update_preview();
1447                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1448         }
1449
1450         return 1;
1451 }
1452
1453
1454 CWindowProjectorMiddle::CWindowProjectorMiddle(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1455  : BC_Button(x, y, mwindow->theme->get_image_set("middle_justify"))
1456 {
1457         this->gui = gui;
1458         this->mwindow = mwindow;
1459         set_tooltip(_("Center vertical"));
1460 }
1461 int CWindowProjectorMiddle::handle_event()
1462 {
1463         FloatAuto *y_auto = 0;
1464         Track *track = mwindow->cwindow->calculate_affected_track();
1465         if(track)
1466                 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1467                         track->automation->autos[AUTOMATION_PROJECTOR_Y], 1);
1468
1469         if(y_auto)
1470         {
1471                 mwindow->undo->update_undo_before(_("projector"), 0);
1472                 y_auto->set_value(0);
1473                 gui->update();
1474                 gui->update_preview();
1475                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1476         }
1477
1478         return 1;
1479 }
1480
1481
1482 CWindowProjectorBottom::CWindowProjectorBottom(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1483  : BC_Button(x, y, mwindow->theme->get_image_set("bottom_justify"))
1484 {
1485         this->gui = gui;
1486         this->mwindow = mwindow;
1487         set_tooltip(_("Bottom justify"));
1488 }
1489 int CWindowProjectorBottom::handle_event()
1490 {
1491         FloatAuto *y_auto = 0;
1492         FloatAuto *z_auto = 0;
1493         Track *track = mwindow->cwindow->calculate_affected_track();
1494         if(track)
1495         {
1496                 mwindow->cwindow->calculate_affected_autos(0,
1497                         &y_auto,
1498                         &z_auto,
1499                         track,
1500                         0,
1501                         0,
1502                         1,
1503                         0);
1504         }
1505
1506         if(y_auto && z_auto)
1507         {
1508                 mwindow->undo->update_undo_before(_("projector"), 0);
1509                 y_auto->set_value( -((double)track->track_h * z_auto->get_value() / 2 -
1510                         (double)mwindow->edl->session->output_h / 2));
1511                 gui->update();
1512                 gui->update_preview();
1513                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1514         }
1515
1516         return 1;
1517 }
1518
1519
1520 CWindowMaskMode::CWindowMaskMode(MWindow *mwindow,
1521         CWindowToolGUI *gui, int x, int y, const char *text)
1522  : BC_PopupMenu(x, y, 220, text, 1)
1523 {
1524         this->mwindow = mwindow;
1525         this->gui = gui;
1526 }
1527
1528 void CWindowMaskMode::create_objects()
1529 {
1530         add_item(new BC_MenuItem(mode_to_text(MASK_MULTIPLY_ALPHA)));
1531         add_item(new BC_MenuItem(mode_to_text(MASK_SUBTRACT_ALPHA)));
1532 }
1533
1534 char* CWindowMaskMode::mode_to_text(int mode)
1535 {
1536         switch(mode)
1537         {
1538                 case MASK_MULTIPLY_ALPHA:
1539                         return _("Multiply alpha");
1540                         break;
1541
1542                 case MASK_SUBTRACT_ALPHA:
1543                         return _("Subtract alpha");
1544                         break;
1545         }
1546
1547         return _("Subtract alpha");
1548 }
1549
1550 int CWindowMaskMode::text_to_mode(char *text)
1551 {
1552         if(!strcasecmp(text, _("Multiply alpha")))
1553                 return MASK_MULTIPLY_ALPHA;
1554         else
1555         if(!strcasecmp(text, _("Subtract alpha")))
1556                 return MASK_SUBTRACT_ALPHA;
1557
1558         return MASK_SUBTRACT_ALPHA;
1559 }
1560
1561 int CWindowMaskMode::handle_event()
1562 {
1563         MaskAutos *autos;
1564         MaskAuto *keyframe;
1565         Track *track;
1566         MaskPoint *point;
1567         SubMask *mask;
1568 // Get existing keyframe
1569         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1570         if(track)
1571         {
1572                 mwindow->undo->update_undo_before(_("mask mode"), 0);
1573 #ifdef USE_KEYFRAME_SPANNING
1574 // Create temp keyframe
1575                 MaskAuto temp_keyframe(mwindow->edl, autos);
1576                 temp_keyframe.copy_data(keyframe);
1577 // Update parameter
1578                 temp_keyframe.mode = text_to_mode(get_text());
1579 // Commit change to span of keyframes
1580                 autos->update_parameter(&temp_keyframe);
1581 #else
1582                 ((MaskAuto*)autos->default_auto)->mode =
1583                         text_to_mode(get_text());
1584 #endif
1585                 mwindow->undo->update_undo_after(_("mask mode"), LOAD_AUTOMATION);
1586         }
1587
1588 //printf("CWindowMaskMode::handle_event 1\n");
1589         gui->update_preview();
1590         return 1;
1591 }
1592
1593
1594
1595
1596
1597
1598
1599
1600 CWindowMaskDelete::CWindowMaskDelete(MWindow *mwindow,
1601         CWindowToolGUI *gui,
1602         int x,
1603         int y)
1604  : BC_GenericButton(x, y, _("Delete"))
1605 {
1606         this->mwindow = mwindow;
1607         this->gui = gui;
1608 }
1609
1610 int CWindowMaskDelete::handle_event()
1611 {
1612         MaskAutos *autos;
1613         MaskAuto *keyframe;
1614         Track *track;
1615         MaskPoint *point;
1616         SubMask *mask;
1617         int total_points = 0;
1618
1619 // Get existing keyframe
1620         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1621
1622         if(track)
1623         {
1624                 mwindow->undo->update_undo_before(_("mask delete"), 0);
1625
1626 #ifdef USE_KEYFRAME_SPANNING
1627 // Create temp keyframe
1628                 MaskAuto temp_keyframe(mwindow->edl, autos);
1629                 temp_keyframe.copy_data(keyframe);
1630 // Update parameter
1631                 SubMask *submask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
1632                 for(int i = mwindow->cwindow->gui->affected_point;
1633                         i < submask->points.total - 1;
1634                         i++)
1635                 {
1636                         *submask->points.values[i] = *submask->points.values[i + 1];
1637                 }
1638
1639                 if(submask->points.total)
1640                 {
1641                         submask->points.remove_object(
1642                                 submask->points.values[submask->points.total - 1]);
1643                 }
1644                 total_points = submask->points.total;
1645
1646 // Commit change to span of keyframes
1647                 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe);
1648 #else
1649                 for(MaskAuto *current = (MaskAuto*)autos->default_auto;
1650                         current; )
1651                 {
1652                         SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1653
1654                         for(int i = mwindow->cwindow->gui->affected_point;
1655                                 i < submask->points.total - 1;
1656                                 i++)
1657                         {
1658                                 *submask->points.values[i] = *submask->points.values[i + 1];
1659                         }
1660
1661                         if(submask->points.total)
1662                         {
1663                                 submask->points.remove_object(
1664                                         submask->points.values[submask->points.total - 1]);
1665                         }
1666                         total_points = submask->points.total;
1667
1668                         if(current == (MaskAuto*)autos->default_auto)
1669                                 current = (MaskAuto*)autos->first;
1670                         else
1671                                 current = (MaskAuto*)NEXT;
1672                 }
1673 #endif
1674                 if( mwindow->cwindow->gui->affected_point >= total_points )
1675                         mwindow->cwindow->gui->affected_point =
1676                                 total_points > 0 ? total_points-1 : 0;
1677
1678                 gui->update();
1679                 gui->update_preview();
1680                 mwindow->undo->update_undo_after(_("mask delete"), LOAD_AUTOMATION);
1681         }
1682
1683
1684         return 1;
1685 }
1686
1687 int CWindowMaskDelete::keypress_event()
1688 {
1689         if(get_keypress() == BACKSPACE ||
1690                 get_keypress() == DELETE)
1691                 return handle_event();
1692         return 0;
1693 }
1694
1695
1696 // CWindowMaskCycleNext::CWindowMaskCycleNext(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1697 //  : BC_GenericButton(x, y, _("Cycle next"))
1698 // {
1699 //      this->mwindow = mwindow;
1700 //      this->gui = gui;
1701 // }
1702 // int CWindowMaskCycleNext::handle_event()
1703 // {
1704 //      MaskAuto *keyframe;
1705 //      MaskAutos *autos;
1706 //      Track *track;
1707 //      MaskPoint *point;
1708 //      SubMask *mask;
1709 //      ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1710 //
1711 //      MaskPoint *temp;
1712 //
1713 // // Should apply to all keyframes
1714 //      if(keyframe && mask->points.total)
1715 //      {
1716 //              temp = mask->points.values[0];
1717 //
1718 //              for(int i = 0; i < mask->points.total - 1; i++)
1719 //              {
1720 //                      mask->points.values[i] = mask->points.values[i + 1];
1721 //              }
1722 //              mask->points.values[mask->points.total - 1] = temp;
1723 //
1724 //              mwindow->cwindow->gui->affected_point--;
1725 //              if(mwindow->cwindow->gui->affected_point < 0)
1726 //                      mwindow->cwindow->gui->affected_point = mask->points.total - 1;
1727 //
1728 //              gui->update();
1729 //              gui->update_preview();
1730 //      }
1731 //
1732 //      return 1;
1733 // }
1734 //
1735 // CWindowMaskCyclePrev::CWindowMaskCyclePrev(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1736 //  : BC_GenericButton(x, y, _("Cycle prev"))
1737 // {
1738 //      this->mwindow = mwindow;
1739 //      this->gui = gui;
1740 // }
1741 // int CWindowMaskCyclePrev::handle_event()
1742 // {
1743 //      MaskAuto *keyframe;
1744 //      MaskAutos *autos;
1745 //      Track *track;
1746 //      MaskPoint *point;
1747 //      SubMask *mask;
1748 //      ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1749 //
1750 // // Should apply to all keyframes
1751 //      MaskPoint *temp;
1752 //      if(keyframe && mask->points.total)
1753 //      {
1754 //              temp = mask->points.values[mask->points.total - 1];
1755 //
1756 //              for(int i = mask->points.total - 1; i > 0; i--)
1757 //              {
1758 //                      mask->points.values[i] = mask->points.values[i - 1];
1759 //              }
1760 //              mask->points.values[0] = temp;
1761 //
1762 //              mwindow->cwindow->gui->affected_point++;
1763 //              if(mwindow->cwindow->gui->affected_point >= mask->points.total)
1764 //                      mwindow->cwindow->gui->affected_point = 0;
1765 //
1766 //              gui->update();
1767 //              gui->update_preview();
1768 //      }
1769 //      return 1;
1770 // }
1771
1772
1773 CWindowMaskNumber::CWindowMaskNumber(MWindow *mwindow,
1774         CWindowToolGUI *gui,
1775         int x,
1776         int y)
1777  : BC_TumbleTextBox(gui,
1778                 (int64_t)mwindow->edl->session->cwindow_mask,
1779                 (int64_t)0,
1780                 (int64_t)SUBMASKS - 1,
1781                 x,
1782                 y,
1783                 100)
1784 {
1785         this->mwindow = mwindow;
1786         this->gui = gui;
1787 }
1788
1789 CWindowMaskNumber::~CWindowMaskNumber()
1790 {
1791 }
1792
1793 int CWindowMaskNumber::handle_event()
1794 {
1795         mwindow->edl->session->cwindow_mask = atol(get_text());
1796         gui->update();
1797         gui->update_preview();
1798         return 1;
1799 }
1800
1801
1802 CWindowMaskAffectedPoint::CWindowMaskAffectedPoint(MWindow *mwindow,
1803         CWindowToolGUI *gui, int x, int y)
1804  : BC_TumbleTextBox(gui,
1805                 (int64_t)mwindow->cwindow->gui->affected_point,
1806                 (int64_t)0, INT64_MAX, x, y, 100)
1807 {
1808         this->mwindow = mwindow;
1809         this->gui = gui;
1810 }
1811
1812 CWindowMaskAffectedPoint::~CWindowMaskAffectedPoint()
1813 {
1814 }
1815
1816 int CWindowMaskAffectedPoint::handle_event()
1817 {
1818         int total_points = 0;
1819         int affected_point = atol(get_text());
1820         Track *track = mwindow->cwindow->calculate_affected_track();
1821         if(track) {
1822                 MaskAutos *autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
1823                 MaskAuto *keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(autos, 0);
1824                 if( keyframe ) {
1825                         SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
1826                         total_points = mask->points.size();
1827                 }
1828         }
1829         int active_point = affected_point;
1830         if( affected_point >= total_points )
1831                 affected_point = total_points - 1;
1832         else if( affected_point < 0 )
1833                 affected_point = 0;
1834         if( active_point != affected_point )
1835                 update((int64_t)affected_point);
1836         mwindow->cwindow->gui->affected_point = affected_point;
1837         gui->update();
1838         gui->update_preview();
1839         return 1;
1840 }
1841
1842
1843
1844
1845
1846 CWindowMaskFeather::CWindowMaskFeather(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1847  : BC_TumbleTextBox(gui,
1848                 (int64_t)0,
1849                 (int64_t)0,
1850                 (int64_t)0xff,
1851                 x,
1852                 y,
1853                 100)
1854 {
1855         this->mwindow = mwindow;
1856         this->gui = gui;
1857 }
1858 CWindowMaskFeather::~CWindowMaskFeather()
1859 {
1860 }
1861 int CWindowMaskFeather::handle_event()
1862 {
1863         MaskAutos *autos;
1864         MaskAuto *keyframe;
1865         Track *track;
1866         MaskPoint *point;
1867         SubMask *mask;
1868 #ifdef USE_KEYFRAME_SPANNING
1869         int create_it = 0;
1870 #else
1871         int create_it = 1;
1872 #endif
1873
1874         mwindow->undo->update_undo_before(_("mask feather"), this);
1875
1876 // Get existing keyframe
1877         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe,
1878                         mask, point, create_it);
1879
1880         if(track)
1881         {       
1882 #ifdef USE_KEYFRAME_SPANNING
1883 // Create temp keyframe
1884                 MaskAuto temp_keyframe(mwindow->edl, autos);
1885                 temp_keyframe.copy_data(keyframe);
1886 // Update parameter
1887                 temp_keyframe.feather = atof(get_text());
1888 // Commit change to span of keyframes
1889                 autos->update_parameter(&temp_keyframe);
1890 #else
1891                 keyframe->feather = atof(get_text());
1892 #endif
1893
1894                 gui->update_preview();
1895         }
1896
1897         mwindow->undo->update_undo_after(_("mask feather"), LOAD_AUTOMATION);
1898         return 1;
1899 }
1900
1901
1902 CWindowMaskValue::CWindowMaskValue(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1903  : BC_ISlider(x,
1904                         y,
1905                         0,
1906                         200,
1907                         200,
1908                         0,
1909                         100,
1910                         0)
1911 {
1912         this->mwindow = mwindow;
1913         this->gui = gui;
1914 }
1915
1916 CWindowMaskValue::~CWindowMaskValue()
1917 {
1918 }
1919
1920 int CWindowMaskValue::handle_event()
1921 {
1922         MaskAutos *autos;
1923         MaskAuto *keyframe;
1924         Track *track;
1925         MaskPoint *point;
1926         SubMask *mask;
1927 #ifdef USE_KEYFRAME_SPANNING
1928         int create_it = 0;
1929 #else
1930         int create_it = 1;
1931 #endif
1932         
1933         mwindow->undo->update_undo_before(_("mask value"), this);
1934         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe,
1935                 mask, point, create_it);
1936
1937         if(track)
1938         {
1939 #ifdef USE_KEYFRAME_SPANNING
1940 // Create temp keyframe
1941                 MaskAuto temp_keyframe(mwindow->edl, autos);
1942                 temp_keyframe.copy_data(keyframe);
1943 // Update parameter
1944                 temp_keyframe.value = get_value();
1945 // Commit change to span of keyframes
1946                 autos->update_parameter(&temp_keyframe);
1947 #else
1948                 keyframe->value = get_value();
1949 #endif
1950         }
1951
1952         gui->update_preview();
1953         mwindow->undo->update_undo_after(_("mask value"), LOAD_AUTOMATION);
1954         return 1;
1955 }
1956
1957
1958 CWindowMaskBeforePlugins::CWindowMaskBeforePlugins(CWindowToolGUI *gui, int x, int y)
1959  : BC_CheckBox(x,
1960         y,
1961         1,
1962         _("Apply mask before plugins"))
1963 {
1964         this->gui = gui;
1965 }
1966
1967 int CWindowMaskBeforePlugins::handle_event()
1968 {
1969         Track *track;
1970         MaskAutos *autos;
1971         MaskAuto *keyframe;
1972         SubMask *mask;
1973         MaskPoint *point;
1974         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 1);
1975
1976         if (keyframe) {
1977                 keyframe->apply_before_plugins = get_value();
1978                 gui->update_preview();
1979         }
1980         return 1;
1981 }
1982
1983
1984 CWindowDisableOpenGLMasking::CWindowDisableOpenGLMasking(CWindowToolGUI *gui, int x, int y)
1985  : BC_CheckBox(x, y, 1, _("Disable OpenGL masking"))
1986 {
1987         this->gui = gui;
1988 }
1989
1990 int CWindowDisableOpenGLMasking::handle_event()
1991 {
1992         Track *track;
1993         MaskAutos *autos;
1994         MaskAuto *keyframe;
1995         SubMask *mask;
1996         MaskPoint *point;
1997         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 1);
1998
1999         if (keyframe) {
2000                 keyframe->disable_opengl_masking = get_value();
2001                 gui->update_preview();
2002         }
2003         return 1;
2004 }
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014 CWindowMaskGUI::CWindowMaskGUI(MWindow *mwindow, CWindowTool *thread)
2015  : CWindowToolGUI(mwindow,
2016         thread,
2017         _(PROGRAM_NAME ": Mask"),
2018         330,
2019         310)
2020 {
2021         this->mwindow = mwindow;
2022         this->thread = thread;
2023         number = 0;
2024         active_point = 0;
2025         feather = 0;
2026 }
2027 CWindowMaskGUI::~CWindowMaskGUI()
2028 {
2029         lock_window("CWindowMaskGUI::~CWindowMaskGUI");
2030         delete number;
2031         delete active_point;
2032         delete feather;
2033         unlock_window();
2034 }
2035
2036 void CWindowMaskGUI::create_objects()
2037 {
2038         int x = 10, y = 10, margin = mwindow->theme->widget_border;
2039         //MaskAuto *keyframe = 0;
2040         //Track *track = mwindow->cwindow->calculate_affected_track();
2041         //if(track)
2042         //      keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(track->automation->autos[AUTOMATION_MASK], 0);
2043
2044         lock_window("CWindowMaskGUI::create_objects");
2045         BC_Title *title;
2046         add_subwindow(title = new BC_Title(x, y, _("Mode:")));
2047         add_subwindow(mode = new CWindowMaskMode(mwindow,
2048                 this, x + title->get_w() + margin, y, ""));
2049         mode->create_objects();
2050         y += mode->get_h() + margin;
2051         add_subwindow(title = new BC_Title(x, y, _("Value:")));
2052         add_subwindow(value = new CWindowMaskValue(mwindow, this, x + title->get_w() + margin, y));
2053         y += value->get_h() + margin;
2054         add_subwindow(delete_point = new CWindowMaskDelete(mwindow, this, x, y));
2055         int x1 = x + delete_point->get_w() + 2*margin;
2056         add_subwindow(title = new BC_Title(x1, y, _("Point:")));
2057         x1 += title->get_w() + margin;
2058         active_point = new CWindowMaskAffectedPoint(mwindow, this, x1, y);
2059         active_point->create_objects();
2060         y += delete_point->get_h() + margin;
2061         add_subwindow(title = new BC_Title(x, y, _("Mask number:")));
2062         number = new CWindowMaskNumber(mwindow,
2063                 this, x + title->get_w() + margin, y);
2064         number->create_objects();
2065         y += number->get_h() + margin;
2066         add_subwindow(title = new BC_Title(x, y, _("Feather:")));
2067         feather = new CWindowMaskFeather(mwindow,
2068                 this, x + title->get_w() + margin, y);
2069         feather->create_objects();
2070         y += feather->get_h() + margin;
2071         add_subwindow(title = new BC_Title(x, y, "X:"));
2072         x += title->get_w() + margin;
2073         this->x = new CWindowCoord(this, x, y, (float)0.0);
2074         this->x->create_objects();
2075         x += this->x->get_w() + margin;
2076         add_subwindow(title = new BC_Title(x, y, "Y:"));
2077         x += title->get_w() + margin;
2078         this->y = new CWindowCoord(this, x, y, (float)0.0);
2079         this->y->create_objects();
2080
2081         x = 10;
2082         y += this->y->get_h() + margin;
2083         add_subwindow(title = new BC_Title(x, y, _("Press Shift to move an end point")));
2084         y += title->get_h() + margin;
2085         add_subwindow(title = new BC_Title(x, y, _("Press Ctrl to move a control point")));
2086         y += title->get_h() + margin;
2087         add_subwindow(title = new BC_Title(x, y, _("Press Alt to translate the mask")));
2088         y += 30;
2089
2090         add_subwindow(this->apply_before_plugins = new CWindowMaskBeforePlugins(this, 10, y));
2091         y += this->apply_before_plugins->get_h() + margin;
2092         add_subwindow(this->disable_opengl_masking = new CWindowDisableOpenGLMasking(this, 10, y));
2093
2094         update();
2095         unlock_window();
2096 }
2097
2098 void CWindowMaskGUI::get_keyframe(Track* &track,
2099         MaskAutos* &autos,
2100         MaskAuto* &keyframe,
2101         SubMask* &mask,
2102         MaskPoint* &point,
2103         int create_it)
2104 {
2105         autos = 0;
2106         keyframe = 0;
2107
2108         track = mwindow->cwindow->calculate_affected_track();
2109         if(track)
2110         {
2111                 autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
2112                 keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(
2113                         autos,
2114                         create_it);
2115         }
2116
2117         if(keyframe)
2118                 mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
2119         else
2120                 mask = 0;
2121
2122         point = 0;
2123         if(keyframe)
2124         {
2125                 if(mwindow->cwindow->gui->affected_point < mask->points.total &&
2126                         mwindow->cwindow->gui->affected_point >= 0)
2127                 {
2128                         point = mask->points.values[mwindow->cwindow->gui->affected_point];
2129                 }
2130         }
2131 }
2132
2133 void CWindowMaskGUI::update()
2134 {
2135         Track *track;
2136         MaskAutos *autos;
2137         MaskAuto *keyframe;
2138         SubMask *mask;
2139         MaskPoint *point;
2140 //printf("CWindowMaskGUI::update 1\n");
2141         get_keyframe(track, autos, keyframe, mask, point, 0);
2142
2143         double position = mwindow->edl->local_session->get_selectionstart(1);
2144         position = mwindow->edl->align_to_frame(position, 0);
2145         if(track)
2146         {
2147                 int64_t position_i = track->to_units(position, 0);
2148
2149                 if(point)
2150                 {
2151                         x->update(point->x);
2152                         y->update(point->y);
2153                 }
2154
2155                 if(mask)
2156                 {
2157                         feather->update((int64_t)autos->get_feather(position_i, PLAY_FORWARD));
2158                         value->update((int64_t)autos->get_value(position_i, PLAY_FORWARD));
2159                         apply_before_plugins->update((int64_t)keyframe->apply_before_plugins);
2160                         disable_opengl_masking->update((int64_t)keyframe->disable_opengl_masking);
2161                 }
2162         }
2163
2164 //printf("CWindowMaskGUI::update 1\n");
2165         active_point->update((int64_t)mwindow->cwindow->gui->affected_point);
2166         number->update((int64_t)mwindow->edl->session->cwindow_mask);
2167
2168 //printf("CWindowMaskGUI::update 1\n");
2169         if(track)
2170         {
2171 #ifdef USE_KEYFRAME_SPANNING
2172                 mode->set_text(
2173                         CWindowMaskMode::mode_to_text(keyframe->mode));
2174 #else
2175                 mode->set_text(
2176                         CWindowMaskMode::mode_to_text(((MaskAuto*)autos->default_auto)->mode));
2177 #endif
2178         }
2179 //printf("CWindowMaskGUI::update 2\n");
2180 }
2181
2182 void CWindowMaskGUI::handle_event()
2183 {
2184         Track *track;
2185         MaskAuto *keyframe;
2186         MaskAutos *autos;
2187         SubMask *mask;
2188         MaskPoint *point;
2189         get_keyframe(track, autos, keyframe, mask, point, 0);
2190
2191         mwindow->undo->update_undo_before(_("mask point"), this);
2192
2193         if(point)
2194         {
2195 #ifdef USE_KEYFRAME_SPANNING
2196 // Create temp keyframe
2197                 MaskAuto temp_keyframe(mwindow->edl, autos);
2198                 temp_keyframe.copy_data(keyframe);
2199 // Get affected point in temp keyframe
2200                 mask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
2201                 if(mwindow->cwindow->gui->affected_point < mask->points.total &&
2202                         mwindow->cwindow->gui->affected_point >= 0)
2203                 {
2204                         point = mask->points.values[mwindow->cwindow->gui->affected_point];
2205                 }
2206
2207                 if(point)
2208                 {
2209                         point->x = atof(x->get_text());
2210                         point->y = atof(y->get_text());
2211 // Commit to spanned keyframes
2212                         autos->update_parameter(&temp_keyframe);
2213                 }
2214 #else
2215                 point->x = atof(x->get_text());
2216                 point->y = atof(y->get_text());
2217 #endif
2218         }
2219
2220         update_preview();
2221         mwindow->undo->update_undo_after(_("mask point"), LOAD_AUTOMATION);
2222 }
2223
2224 void CWindowMaskGUI::update_preview()
2225 {
2226         mwindow->restart_brender();
2227         mwindow->sync_parameters(CHANGE_PARAMS);
2228         mwindow->cwindow->playback_engine->que->send_command(CURRENT_FRAME,
2229                         CHANGE_NONE,
2230                         mwindow->edl,
2231                         1);
2232         mwindow->cwindow->gui->lock_window("CWindowMaskGUI::update_preview");
2233         mwindow->cwindow->gui->canvas->draw_refresh();
2234         mwindow->cwindow->gui->unlock_window();
2235 }
2236
2237
2238 CWindowRulerGUI::CWindowRulerGUI(MWindow *mwindow, CWindowTool *thread)
2239  : CWindowToolGUI(mwindow,
2240         thread,
2241         _(PROGRAM_NAME ": Ruler"),
2242         320,
2243         240)
2244 {
2245 }
2246
2247 CWindowRulerGUI::~CWindowRulerGUI()
2248 {
2249 }
2250
2251 void CWindowRulerGUI::create_objects()
2252 {
2253         int x = 10, y = 10;
2254         BC_Title *title;
2255
2256         lock_window("CWindowRulerGUI::create_objects");
2257         add_subwindow(title = new BC_Title(x, y, _("Current:")));
2258         add_subwindow(current = new BC_Title(x + title->get_w() + 10, y, ""));
2259         y += title->get_h() + 5;
2260
2261         add_subwindow(title = new BC_Title(x, y, _("Point 1:")));
2262         add_subwindow(point1 = new BC_Title(x + title->get_w() + 10, y, ""));
2263         y += title->get_h() + 5;
2264
2265         add_subwindow(title = new BC_Title(x, y, _("Point 2:")));
2266         add_subwindow(point2 = new BC_Title(x + title->get_w() + 10, y, ""));
2267         y += title->get_h() + 5;
2268
2269         add_subwindow(title = new BC_Title(x, y, _("Distance:")));
2270         add_subwindow(distance = new BC_Title(x + title->get_w() + 10, y, ""));
2271         y += title->get_h() + 5;
2272         add_subwindow(title = new BC_Title(x, y, _("Angle:")));
2273         add_subwindow(angle = new BC_Title(x + title->get_w() + 10, y, ""));
2274         y += title->get_h() + 10;
2275         char string[BCTEXTLEN];
2276         sprintf(string, _("Press Ctrl to lock ruler to the\nnearest 45%c angle."), 0xb0);
2277         add_subwindow(title = new BC_Title(x,
2278                 y,
2279                 string));
2280         y += title->get_h() + 10;
2281         sprintf(string, _("Press Alt to translate the ruler."));
2282         add_subwindow(title = new BC_Title(x,
2283                 y,
2284                 string));
2285         update();
2286         unlock_window();
2287 }
2288
2289 void CWindowRulerGUI::update()
2290 {
2291         double distance_value =
2292                 sqrt(SQR(mwindow->edl->session->ruler_x2 - mwindow->edl->session->ruler_x1) +
2293                 SQR(mwindow->edl->session->ruler_y2 - mwindow->edl->session->ruler_y1));
2294         double angle_value = atan((mwindow->edl->session->ruler_y2 - mwindow->edl->session->ruler_y1) /
2295                 (mwindow->edl->session->ruler_x2 - mwindow->edl->session->ruler_x1)) *
2296                 360 /
2297                 2 /
2298                 M_PI;
2299
2300         if(EQUIV(distance_value, 0.0))
2301         {
2302                 angle_value = 0.0;
2303         }
2304         else
2305         if(angle_value < 0)
2306         {
2307                 angle_value *= -1;
2308         }
2309
2310         char string[BCTEXTLEN];
2311         sprintf(string, "%d, %d",
2312                 mwindow->session->cwindow_output_x,
2313                 mwindow->session->cwindow_output_y);
2314         current->update(string);
2315         sprintf(string, "%.0f, %.0f",
2316                 mwindow->edl->session->ruler_x1,
2317                 mwindow->edl->session->ruler_y1);
2318         point1->update(string);
2319         sprintf(string, "%.0f, %.0f",
2320                 mwindow->edl->session->ruler_x2,
2321                 mwindow->edl->session->ruler_y2);
2322         point2->update(string);
2323
2324         sprintf(string, _("%0.01f pixels"), distance_value);
2325         distance->update(string);
2326         sprintf(string, "%0.02f %c", angle_value, 0xb0);
2327         angle->update(string);
2328 }
2329
2330 void CWindowRulerGUI::handle_event()
2331 {
2332 }
2333
2334
2335
2336