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