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