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