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