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