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