Credit Andrew - improve in-tree documentation
[goodguy/cinelerra.git] / cinelerra / vwindowgui.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2011 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 "arender.h"
23 #include "asset.h"
24 #include "assets.h"
25 #include "awindowgui.h"
26 #include "awindow.h"
27 #include "cache.h"
28 #include "canvas.h"
29 #include "clip.h"
30 #include "clipedit.h"
31 #include "edl.h"
32 #include "edlsession.h"
33 #include "filesystem.h"
34 #include "filexml.h"
35 #include "fonts.h"
36 #include "keys.h"
37 #include "labels.h"
38 #include "language.h"
39 #include "localsession.h"
40 #include "mainclock.h"
41 #include "mainmenu.h"
42 #include "mainsession.h"
43 #include "mainundo.h"
44 #include "meterpanel.h"
45 #include "mwindowgui.h"
46 #include "mwindow.h"
47 #include "playtransport.h"
48 #include "preferences.h"
49 #include "renderengine.h"
50 #include "samples.h"
51 #include "theme.h"
52 #include "timebar.h"
53 #include "tracks.h"
54 #include "transportque.h"
55 #include "vframe.h"
56 #include "vplayback.h"
57 #include "vtimebar.h"
58 #include "vwindowgui.h"
59 #include "vwindow.h"
60
61
62
63
64 VWindowGUI::VWindowGUI(MWindow *mwindow, VWindow *vwindow)
65  : BC_Window(_(PROGRAM_NAME ": Viewer"),
66         mwindow->session->vwindow_x,
67         mwindow->session->vwindow_y,
68         mwindow->session->vwindow_w,
69         mwindow->session->vwindow_h,
70         100,
71         100,
72         1,
73         1,
74         0) // Hide it
75 {
76         this->mwindow = mwindow;
77         this->vwindow = vwindow;
78         canvas = 0;
79         transport = 0;
80         edit_panel = 0;
81         meters = 0;
82 //      source = 0;
83         strcpy(loaded_title, "");
84         highlighted = 0;
85 }
86
87 VWindowGUI::~VWindowGUI()
88 {
89         vwindow->playback_engine->interrupt_playback(1);
90         sources.remove_all_objects();
91         labels.remove_all_objects();
92         delete canvas;
93         delete transport;
94         delete edit_panel;
95         delete meters;
96 //      delete source;
97 }
98
99 void VWindowGUI::draw_wave()
100 {
101         TransportCommand command;
102         command.command = NORMAL_FWD;
103         command.get_edl()->copy_all(vwindow->get_edl());
104         command.change_type = CHANGE_ALL;
105         command.realtime = 0;
106         RenderEngine *render_engine = new RenderEngine(0, mwindow->preferences, 0, 0);
107         CICache *cache = new CICache(mwindow->preferences);
108         render_engine->set_acache(cache);
109         render_engine->arm_command(&command);
110
111         double duration = 1.;
112         int w = mwindow->edl->session->output_w;
113         int h = mwindow->edl->session->output_h;
114         VFrame *vframe = new VFrame(w, h, BC_RGB888);
115         vframe->clear_frame();
116         int sample_rate = mwindow->edl->get_sample_rate();
117         int channels = mwindow->edl->session->audio_channels;
118         if( channels > 2 ) channels = 2;
119         int64_t bfrsz = sample_rate * duration;
120         Samples *samples[MAXCHANNELS];
121         int ch = 0;
122         while( ch < channels ) samples[ch++] = new Samples(bfrsz);
123         while( ch < MAXCHANNELS ) samples[ch++] = 0;
124         render_engine->arender->process_buffer(samples, bfrsz, 0);
125
126         static int line_colors[2] = { GREEN, YELLOW };
127         static int base_colors[2] = { RED, PINK };
128         for( int i=channels; --i>=0; ) {
129                 AssetPicon::draw_wave(vframe, samples[i]->get_data(), bfrsz,
130                         base_colors[i], line_colors[i]);
131         }
132
133         for( int i=channels; --i>=0; ) delete samples[i];
134         delete render_engine;
135         delete cache;
136         delete canvas->refresh_frame;
137         canvas->refresh_frame = vframe;
138         canvas->draw_refresh(1);
139 }
140
141 void VWindowGUI::change_source(EDL *edl, const char *title)
142 {
143 //printf("VWindowGUI::change_source %d\n", __LINE__);
144
145         update_sources(title);
146         strcpy(loaded_title, title);
147         char string[BCTEXTLEN];
148         if(title[0])
149                 sprintf(string, _(PROGRAM_NAME ": %s"), title);
150         else
151                 sprintf(string, _(PROGRAM_NAME ": Viewer"));
152
153         lock_window("VWindowGUI::change_source");
154         canvas->clear();
155         if( edl &&
156             !edl->tracks->playable_video_tracks() &&
157             edl->tracks->playable_audio_tracks() )
158                 draw_wave();
159         timebar->update(0);
160         set_title(string);
161         unlock_window();
162 }
163
164
165 // Get source list from master EDL
166 void VWindowGUI::update_sources(const char *title)
167 {
168         lock_window("VWindowGUI::update_sources");
169         sources.remove_all_objects();
170
171         for( int i=0; i<mwindow->edl->clips.size(); ++i ) {
172                 char *clip_title = mwindow->edl->clips.values[i]->local_session->clip_title;
173                 int exists = 0;
174
175                 for( int j=0; !exists && j<sources.size(); ++j ) {
176                         if( !strcasecmp(sources.values[j]->get_text(), clip_title) )
177                                 exists = 1;
178                 }
179
180                 if( !exists )
181                         sources.append(new BC_ListBoxItem(clip_title));
182         }
183
184         FileSystem fs;
185         for( Asset *current=mwindow->edl->assets->first; current; current=NEXT ) {
186                 char clip_title[BCTEXTLEN];
187                 fs.extract_name(clip_title, current->path);
188                 int exists = 0;
189
190                 for( int j=0; !exists && j<sources.size(); ++j ) {
191                         if( !strcasecmp(sources.values[j]->get_text(), clip_title) )
192                                 exists = 1;
193                 }
194
195                 if( !exists )
196                         sources.append(new BC_ListBoxItem(clip_title));
197         }
198
199         unlock_window();
200 }
201
202 void VWindowGUI::create_objects()
203 {
204         lock_window("VWindowGUI::create_objects");
205         in_point = 0;
206         out_point = 0;
207         set_icon(mwindow->theme->get_image("vwindow_icon"));
208
209 //printf("VWindowGUI::create_objects 1\n");
210         mwindow->theme->get_vwindow_sizes(this);
211         mwindow->theme->draw_vwindow_bg(this);
212         flash(0);
213
214         meters = new VWindowMeters(mwindow,
215                 this,
216                 mwindow->theme->vmeter_x,
217                 mwindow->theme->vmeter_y,
218                 mwindow->theme->vmeter_h);
219         meters->create_objects();
220
221 //printf("VWindowGUI::create_objects 1\n");
222 // Requires meters to build
223         edit_panel = new VWindowEditing(mwindow, vwindow);
224         edit_panel->set_meters(meters);
225         edit_panel->create_objects();
226
227 //printf("VWindowGUI::create_objects 1\n");
228         transport = new VWindowTransport(mwindow,
229                 this,
230                 mwindow->theme->vtransport_x,
231                 mwindow->theme->vtransport_y);
232         transport->create_objects();
233
234 //printf("VWindowGUI::create_objects 1\n");
235 //      add_subwindow(fps_title = new BC_Title(mwindow->theme->vedit_x, y, ""));
236     add_subwindow(clock = new MainClock(mwindow,
237                 mwindow->theme->vtime_x,
238                 mwindow->theme->vtime_y,
239                 mwindow->theme->vtime_w));
240
241         canvas = new VWindowCanvas(mwindow, this);
242         canvas->create_objects(mwindow->edl);
243         canvas->use_vwindow();
244
245
246 //printf("VWindowGUI::create_objects 1\n");
247         add_subwindow(timebar = new VTimeBar(mwindow,
248                 this,
249                 mwindow->theme->vtimebar_x,
250                 mwindow->theme->vtimebar_y,
251                 mwindow->theme->vtimebar_w,
252                 mwindow->theme->vtimebar_h));
253         timebar->create_objects();
254 //printf("VWindowGUI::create_objects 2\n");
255
256
257 //printf("VWindowGUI::create_objects 1\n");
258 //      source = new VWindowSource(mwindow,
259 //              this,
260 //              mwindow->theme->vsource_x,
261 //              mwindow->theme->vsource_y);
262 //      source->create_objects();
263         update_sources(_("None"));
264
265 //printf("VWindowGUI::create_objects 2\n");
266         deactivate();
267
268         show_window();
269         unlock_window();
270 }
271
272 int VWindowGUI::resize_event(int w, int h)
273 {
274         mwindow->session->vwindow_x = get_x();
275         mwindow->session->vwindow_y = get_y();
276         mwindow->session->vwindow_w = w;
277         mwindow->session->vwindow_h = h;
278
279         mwindow->theme->get_vwindow_sizes(this);
280         mwindow->theme->draw_vwindow_bg(this);
281         flash(0);
282
283 //printf("VWindowGUI::resize_event %d %d\n", __LINE__, mwindow->theme->vedit_y);
284         edit_panel->reposition_buttons(mwindow->theme->vedit_x,
285                 mwindow->theme->vedit_y);
286
287         timebar->resize_event();
288         transport->reposition_buttons(mwindow->theme->vtransport_x,
289                 mwindow->theme->vtransport_y);
290         clock->reposition_window(mwindow->theme->vtime_x,
291                 mwindow->theme->vtime_y,
292                 mwindow->theme->vtime_w,
293                 clock->get_h());
294         canvas->reposition_window(0,
295                 mwindow->theme->vcanvas_x,
296                 mwindow->theme->vcanvas_y,
297                 mwindow->theme->vcanvas_w,
298                 mwindow->theme->vcanvas_h);
299 //printf("VWindowGUI::resize_event %d %d\n", __LINE__, mwindow->theme->vcanvas_x);
300 //      source->reposition_window(mwindow->theme->vsource_x,
301 //              mwindow->theme->vsource_y);
302         meters->reposition_window(mwindow->theme->vmeter_x,
303                 mwindow->theme->vmeter_y,
304                 -1,
305                 mwindow->theme->vmeter_h);
306
307         BC_WindowBase::resize_event(w, h);
308         return 1;
309 }
310
311
312
313
314
315 int VWindowGUI::translation_event()
316 {
317         mwindow->session->vwindow_x = get_x();
318         mwindow->session->vwindow_y = get_y();
319         return 0;
320 }
321
322 int VWindowGUI::close_event()
323 {
324         hide_window();
325         int i = mwindow->vwindows.size();
326         while( --i >= 0 && mwindow->vwindows.get(i)->gui != this );
327         if( i > 0 ) {
328                 set_done(0);
329                 return 1;
330         }
331
332         mwindow->session->show_vwindow = 0;
333         unlock_window();
334
335         mwindow->gui->lock_window("VWindowGUI::close_event");
336         mwindow->gui->mainmenu->show_vwindow->set_checked(0);
337         mwindow->gui->unlock_window();
338
339         lock_window("VWindowGUI::close_event");
340         mwindow->save_defaults();
341         return 1;
342 }
343
344 int VWindowGUI::keypress_event()
345 {
346         int result = 0;
347         switch( get_keypress() ) {
348         case 'w':
349         case 'W':
350                 close_event();
351                 result = 1;
352                 break;
353         case 'z':
354                 mwindow->undo_entry(this);
355                 break;
356         case 'Z':
357                 mwindow->redo_entry(this);
358                 break;
359         case 'f':
360                 unlock_window();
361                 if(mwindow->session->vwindow_fullscreen)
362                         canvas->stop_fullscreen();
363                 else
364                         canvas->start_fullscreen();
365                 lock_window("VWindowGUI::keypress_event 1");
366                 break;
367         case ESC:
368                 unlock_window();
369                 if(mwindow->session->vwindow_fullscreen)
370                         canvas->stop_fullscreen();
371                 lock_window("VWindowGUI::keypress_event 2");
372                 break;
373         case KEY_F1:
374         case KEY_F2:
375         case KEY_F3:
376         case KEY_F4:
377                 if( ctrl_down() && shift_down() ) {
378                         resend_event(mwindow->gui);
379                         result = 1;
380                         break;
381                 }
382         }
383         if( !result )
384                 result = transport->keypress_event();
385         return result;
386 }
387
388 void VWindowGUI::stop_transport(const char *lock_msg)
389 {
390         if( !transport->is_stopped() ) {
391                 if( lock_msg ) unlock_window();
392                 transport->handle_transport(STOP, 1, 0, 0);
393                 if( lock_msg ) lock_window(lock_msg);
394         }
395 }
396
397 int VWindowGUI::button_press_event()
398 {
399         if( vwindow->get_edl() != 0 && canvas->get_canvas() &&
400             mwindow->edl->session->vwindow_click2play &&
401             canvas->get_canvas()->get_cursor_over_window() ) {
402                 switch( get_buttonpress() ) {
403                 case LEFT_BUTTON:
404                         if( !vwindow->playback_engine->is_playing_back ) {
405                                 double length = vwindow->get_edl()->tracks->total_playable_length();
406                                 double position = vwindow->playback_engine->get_tracking_position();
407                                 if( position >= length ) transport->goto_start();
408                         }
409                         return transport->forward_play->handle_event();
410                 case MIDDLE_BUTTON:
411                         if( !vwindow->playback_engine->is_playing_back ) {
412                                 double position = vwindow->playback_engine->get_tracking_position();
413                                 if( position <= 0 ) transport->goto_end();
414                         }
415                         return transport->reverse_play->handle_event();
416                 case RIGHT_BUTTON:  // activates popup
417                         break;
418                 case WHEEL_UP:
419                         return transport->frame_forward_play->handle_event();
420                 case WHEEL_DOWN:
421                         return transport->frame_reverse_play->handle_event();
422                 }
423         }
424         if(canvas->get_canvas())
425                 return canvas->button_press_event_base(canvas->get_canvas());
426         return 0;
427 }
428
429 int VWindowGUI::cursor_leave_event()
430 {
431         if(canvas->get_canvas())
432                 return canvas->cursor_leave_event_base(canvas->get_canvas());
433         return 0;
434 }
435
436 int VWindowGUI::cursor_enter_event()
437 {
438         if(canvas->get_canvas())
439                 return canvas->cursor_enter_event_base(canvas->get_canvas());
440         return 0;
441 }
442
443 int VWindowGUI::button_release_event()
444 {
445         if(canvas->get_canvas())
446                 return canvas->button_release_event();
447         return 0;
448 }
449
450 int VWindowGUI::cursor_motion_event()
451 {
452         if(canvas->get_canvas())
453         {
454                 canvas->get_canvas()->unhide_cursor();
455                 return canvas->cursor_motion_event();
456         }
457         return 0;
458 }
459
460
461 void VWindowGUI::drag_motion()
462 {
463 // Window hidden
464         if(get_hidden()) return;
465         if(mwindow->session->current_operation != DRAG_ASSET) return;
466         int need_highlight = cursor_above() && get_cursor_over_window() ? 1 : 0;
467         if( highlighted == need_highlight ) return;
468         highlighted = need_highlight;
469         canvas->draw_refresh();
470 }
471
472 int VWindowGUI::drag_stop()
473 {
474         if( get_hidden() ) return 0;
475
476         if( highlighted &&
477             mwindow->session->current_operation == DRAG_ASSET ) {
478                 highlighted = 0;
479                 canvas->draw_refresh();
480                 unlock_window();
481
482                 Indexable *indexable =
483                         mwindow->session->drag_assets->size() > 0 ?
484                                 (Indexable *)mwindow->session->drag_assets->get(0) :
485                         mwindow->session->drag_clips->size() > 0 ?
486                                 (Indexable *)mwindow->session->drag_clips->get(0) : 0;
487                 if( indexable )
488                         vwindow->change_source(indexable);
489
490                 lock_window("VWindowGUI::drag_stop");
491                 return 1;
492         }
493
494         return 0;
495 }
496
497
498 void VWindowGUI::update_meters()
499 {
500         if(mwindow->edl->session->vwindow_meter != meters->visible)
501         {
502                 meters->set_meters(meters->meter_count,
503                         mwindow->edl->session->vwindow_meter);
504                 mwindow->theme->get_vwindow_sizes(this);
505                 resize_event(get_w(), get_h());
506         }
507 }
508
509
510
511 VWindowMeters::VWindowMeters(MWindow *mwindow,
512         VWindowGUI *gui,
513         int x,
514         int y,
515         int h)
516  : MeterPanel(mwindow,
517                 gui,
518                 x,
519                 y,
520                 -1,
521                 h,
522                 mwindow->edl->session->audio_channels,
523                 mwindow->edl->session->vwindow_meter,
524                 0,
525                 0)
526 {
527         this->mwindow = mwindow;
528         this->gui = gui;
529 }
530
531 VWindowMeters::~VWindowMeters()
532 {
533 }
534
535 int VWindowMeters::change_status_event(int new_status)
536 {
537         mwindow->edl->session->vwindow_meter = new_status;
538         gui->update_meters();
539         return 1;
540 }
541
542
543 VWindowEditing::VWindowEditing(MWindow *mwindow, VWindow *vwindow)
544  : EditPanel(mwindow, vwindow->gui, VWINDOW_ID,
545                 mwindow->theme->vedit_x, mwindow->theme->vedit_y,
546                 EDITING_ARROW,
547                 0, // use_editing_mode
548                 0, // use_keyframe
549                 1, // use_splice
550                 1, // use_overwrite
551                 0, // use_lift
552                 0, // use_extract
553                 1, // use_copy
554                 0, // use_paste
555                 0, // use_undo
556                 0, // use_fit
557                 0, // locklabels
558                 1, // use_labels
559                 1, // use_toclip
560                 1, // use_meters
561                 0, // use_cut
562                 0, // use_commerical
563                 0, // use_goto
564                 1) // use_clk2play
565 {
566         this->mwindow = mwindow;
567         this->vwindow = vwindow;
568 }
569
570 VWindowEditing::~VWindowEditing()
571 {
572 }
573
574 void VWindowEditing::copy_selection()
575 {
576         vwindow->copy(subwindow->shift_down());
577 }
578
579 void VWindowEditing::splice_selection()
580 {
581         if(vwindow->get_edl())
582         {
583                 mwindow->gui->lock_window("VWindowEditing::splice_selection");
584                 mwindow->splice(vwindow->get_edl(), subwindow->shift_down());
585                 mwindow->gui->unlock_window();
586         }
587 }
588
589 void VWindowEditing::overwrite_selection()
590 {
591         if(vwindow->get_edl())
592         {
593                 mwindow->gui->lock_window("VWindowEditing::overwrite_selection");
594                 mwindow->overwrite(vwindow->get_edl(), subwindow->shift_down());
595                 mwindow->gui->unlock_window();
596         }
597 }
598
599 void VWindowEditing::toggle_label()
600 {
601         if(vwindow->get_edl())
602         {
603                 EDL *edl = vwindow->get_edl();
604                 edl->labels->toggle_label(edl->local_session->get_selectionstart(1),
605                         edl->local_session->get_selectionend(1));
606                 vwindow->gui->timebar->update(1);
607         }
608 }
609
610 void VWindowEditing::prev_label(int cut)
611 {
612         if(vwindow->get_edl())
613         {
614                 EDL *edl = vwindow->get_edl();
615                 vwindow->gui->unlock_window();
616                 vwindow->playback_engine->interrupt_playback(1);
617                 vwindow->gui->lock_window("VWindowEditing::prev_label");
618
619                 Label *current = edl->labels->prev_label(
620                         edl->local_session->get_selectionstart(1));
621
622
623                 if(!current)
624                 {
625                         edl->local_session->set_selectionstart(0);
626                         edl->local_session->set_selectionend(0);
627                         vwindow->update_position(CHANGE_NONE, 0, 1, 0);
628                         vwindow->gui->timebar->update(1);
629                 }
630                 else
631                 {
632                         edl->local_session->set_selectionstart(current->position);
633                         edl->local_session->set_selectionend(current->position);
634                         vwindow->update_position(CHANGE_NONE, 0, 1, 0);
635                         vwindow->gui->timebar->update(1);
636                 }
637         }
638 }
639
640 void VWindowEditing::next_label(int cut)
641 {
642         if(vwindow->get_edl())
643         {
644                 EDL *edl = vwindow->get_edl();
645                 Label *current = edl->labels->next_label(
646                         edl->local_session->get_selectionstart(1));
647                 if(!current)
648                 {
649                         vwindow->gui->unlock_window();
650                         vwindow->playback_engine->interrupt_playback(1);
651                         vwindow->gui->lock_window("VWindowEditing::next_label 1");
652
653                         double position = edl->tracks->total_length();
654                         edl->local_session->set_selectionstart(position);
655                         edl->local_session->set_selectionend(position);
656                         vwindow->update_position(CHANGE_NONE, 0, 1, 0);
657                         vwindow->gui->timebar->update(1);
658                 }
659                 else
660                 {
661                         vwindow->gui->unlock_window();
662                         vwindow->playback_engine->interrupt_playback(1);
663                         vwindow->gui->lock_window("VWindowEditing::next_label 2");
664
665                         edl->local_session->set_selectionstart(current->position);
666                         edl->local_session->set_selectionend(current->position);
667                         vwindow->update_position(CHANGE_NONE, 0, 1, 0);
668                         vwindow->gui->timebar->update(1);
669                 }
670         }
671 }
672
673 double VWindowEditing::get_position()
674 {
675         EDL *edl = vwindow->get_edl();
676         double position = !edl ? 0 : edl->local_session->get_selectionstart(1);
677         return position;
678 }
679
680 void VWindowEditing::set_position(double position)
681 {
682         EDL *edl = vwindow->get_edl();
683         if( !edl ) return;
684         if( get_position() != position ) {
685                 if( position < 0 ) position = 0;
686                 edl->local_session->set_selectionstart(position);
687                 edl->local_session->set_selectionend(position);
688                 vwindow->update_position(CHANGE_NONE, 0, 1);
689         }
690 }
691
692 void VWindowEditing::set_inpoint()
693 {
694         vwindow->set_inpoint();
695 }
696
697 void VWindowEditing::set_outpoint()
698 {
699         vwindow->set_outpoint();
700 }
701
702 void VWindowEditing::unset_inoutpoint()
703 {
704         vwindow->unset_inoutpoint();
705 }
706
707
708 void VWindowEditing::to_clip()
709 {
710         EDL *edl = vwindow->get_edl();
711         if( !edl ) return;
712         mwindow->to_clip(edl, _("viewer window: "), subwindow->shift_down());
713 }
714
715 VWindowSource::VWindowSource(MWindow *mwindow, VWindowGUI *vwindow, int x, int y)
716  : BC_PopupTextBox(vwindow,
717         &vwindow->sources,
718         "",
719         x,
720         y,
721         200,
722         200)
723 {
724         this->mwindow = mwindow;
725         this->vwindow = vwindow;
726 }
727
728 VWindowSource::~VWindowSource()
729 {
730 }
731
732 int VWindowSource::handle_event()
733 {
734         return 1;
735 }
736
737
738 VWindowTransport::VWindowTransport(MWindow *mwindow,
739         VWindowGUI *gui,
740         int x,
741         int y)
742  : PlayTransport(mwindow,
743         gui,
744         x,
745         y)
746 {
747         this->gui = gui;
748 }
749
750 EDL* VWindowTransport::get_edl()
751 {
752         return gui->vwindow->get_edl();
753 }
754
755
756 void VWindowTransport::goto_start()
757 {
758         gui->unlock_window();
759         handle_transport(REWIND, 1);
760         gui->lock_window("VWindowTransport::goto_start");
761         gui->vwindow->goto_start();
762 }
763
764 void VWindowTransport::goto_end()
765 {
766         gui->unlock_window();
767         handle_transport(GOTO_END, 1);
768         gui->lock_window("VWindowTransport::goto_end");
769         gui->vwindow->goto_end();
770 }
771
772
773
774
775 VWindowCanvas::VWindowCanvas(MWindow *mwindow, VWindowGUI *gui)
776  : Canvas(mwindow,
777         gui,
778         mwindow->theme->vcanvas_x,
779         mwindow->theme->vcanvas_y,
780         mwindow->theme->vcanvas_w,
781         mwindow->theme->vcanvas_h,
782         0, 0, 0)
783 {
784 //printf("VWindowCanvas::VWindowCanvas %d %d\n", __LINE__, mwindow->theme->vcanvas_x);
785         this->mwindow = mwindow;
786         this->gui = gui;
787 }
788
789 void VWindowCanvas::zoom_resize_window(float percentage)
790 {
791         EDL *edl = gui->vwindow->get_edl();
792         if(!edl) edl = mwindow->edl;
793
794         int canvas_w, canvas_h;
795         int new_w, new_h;
796
797 // Get required canvas size
798         calculate_sizes(edl->get_aspect_ratio(),
799                 edl->session->output_w,
800                 edl->session->output_h,
801                 percentage,
802                 canvas_w,
803                 canvas_h);
804
805 // Estimate window size from current borders
806         new_w = canvas_w + (gui->get_w() - mwindow->theme->vcanvas_w);
807         new_h = canvas_h + (gui->get_h() - mwindow->theme->vcanvas_h);
808
809         mwindow->session->vwindow_w = new_w;
810         mwindow->session->vwindow_h = new_h;
811
812         mwindow->theme->get_vwindow_sizes(gui);
813
814 // Estimate again from new borders
815         new_w = canvas_w + (mwindow->session->vwindow_w - mwindow->theme->vcanvas_w);
816         new_h = canvas_h + (mwindow->session->vwindow_h - mwindow->theme->vcanvas_h);
817
818
819         gui->resize_window(new_w, new_h);
820         gui->resize_event(new_w, new_h);
821 }
822
823 void VWindowCanvas::close_source()
824 {
825         gui->unlock_window();
826         gui->vwindow->playback_engine->interrupt_playback(1);
827         gui->lock_window("VWindowCanvas::close_source");
828         gui->vwindow->delete_source(1, 1);
829 }
830
831
832 void VWindowCanvas::draw_refresh(int flush)
833 {
834         EDL *edl = gui->vwindow->get_edl();
835
836         if(!get_canvas()->get_video_on()) get_canvas()->clear_box(0, 0, get_canvas()->get_w(), get_canvas()->get_h());
837         if(!get_canvas()->get_video_on() && refresh_frame && edl)
838         {
839                 float in_x1, in_y1, in_x2, in_y2;
840                 float out_x1, out_y1, out_x2, out_y2;
841                 get_transfers(edl,
842                         in_x1, in_y1, in_x2, in_y2,
843                         out_x1, out_y1, out_x2, out_y2);
844 // input scaled from session to refresh frame coordinates
845                 int ow = get_output_w(edl);
846                 int oh = get_output_h(edl);
847                 int rw = refresh_frame->get_w();
848                 int rh = refresh_frame->get_h();
849                 float xs = (float)rw / ow;
850                 float ys = (float)rh / oh;
851                 in_x1 *= xs;  in_x2 *= xs;
852                 in_y1 *= ys;  in_y2 *= ys;
853                 get_canvas()->draw_vframe(refresh_frame,
854                                 (int)out_x1,
855                                 (int)out_y1,
856                                 (int)(out_x2 - out_x1),
857                                 (int)(out_y2 - out_y1),
858                                 (int)in_x1,
859                                 (int)in_y1,
860                                 (int)(in_x2 - in_x1),
861                                 (int)(in_y2 - in_y1),
862                                 0);
863         }
864
865         if(!get_canvas()->get_video_on())
866         {
867                 draw_overlays();
868                 get_canvas()->flash(flush);
869         }
870 }
871
872 int VWindowCanvas::need_overlays()
873 {
874         if( gui->highlighted ) return 1;
875         return 0;
876 }
877
878 void VWindowCanvas::draw_overlays()
879 {
880         if( gui->highlighted )
881         {
882                 get_canvas()->set_color(WHITE);
883                 get_canvas()->set_inverse();
884                 get_canvas()->draw_rectangle(0, 0, get_canvas()->get_w(), get_canvas()->get_h());
885                 get_canvas()->draw_rectangle(1, 1, get_canvas()->get_w() - 2, get_canvas()->get_h() - 2);
886                 get_canvas()->set_opaque();
887         }
888 }
889
890 int VWindowCanvas::get_fullscreen()
891 {
892         return mwindow->session->vwindow_fullscreen;
893 }
894
895 void VWindowCanvas::set_fullscreen(int value)
896 {
897         mwindow->session->vwindow_fullscreen = value;
898 }
899