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