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