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