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