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