4 * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
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.
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.
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
25 #include "awindowgui.h"
32 #include "edlsession.h"
33 #include "filesystem.h"
39 #include "localsession.h"
40 #include "mainclock.h"
42 #include "mainsession.h"
44 #include "meterpanel.h"
45 #include "mwindowgui.h"
47 #include "playtransport.h"
48 #include "preferences.h"
49 #include "renderengine.h"
54 #include "transportque.h"
56 #include "vplayback.h"
58 #include "vwindowgui.h"
64 VWindowGUI::VWindowGUI(MWindow *mwindow, VWindow *vwindow)
65 : BC_Window(_(PROGRAM_NAME ": Viewer"),
66 mwindow->session->vwindow_x,
67 mwindow->session->vwindow_y,
68 mwindow->session->vwindow_w,
69 mwindow->session->vwindow_h,
76 this->mwindow = mwindow;
77 this->vwindow = vwindow;
83 strcpy(loaded_title, "");
87 VWindowGUI::~VWindowGUI()
89 vwindow->playback_engine->interrupt_playback(1);
90 sources.remove_all_objects();
91 labels.remove_all_objects();
99 void VWindowGUI::draw_wave()
101 TransportCommand command;
102 command.command = NORMAL_FWD;
103 command.get_edl()->copy_all(vwindow->get_edl());
104 command.change_type = CHANGE_ALL;
105 command.realtime = 0;
106 RenderEngine *render_engine = new RenderEngine(0, mwindow->preferences, 0, 0);
107 CICache *cache = new CICache(mwindow->preferences);
108 render_engine->set_acache(cache);
109 render_engine->arm_command(&command);
111 double duration = 1.;
112 int w = mwindow->edl->session->output_w;
113 int h = mwindow->edl->session->output_h;
114 VFrame *vframe = new VFrame(w, h, BC_RGB888);
115 vframe->clear_frame();
116 int sample_rate = mwindow->edl->get_sample_rate();
117 int channels = mwindow->edl->session->audio_channels;
118 if( channels > 2 ) channels = 2;
119 int64_t bfrsz = sample_rate * duration;
120 Samples *samples[MAXCHANNELS];
122 while( ch < channels ) samples[ch++] = new Samples(bfrsz);
123 while( ch < MAXCHANNELS ) samples[ch++] = 0;
124 render_engine->arender->process_buffer(samples, bfrsz, 0);
126 static int line_colors[2] = { GREEN, YELLOW };
127 static int base_colors[2] = { RED, PINK };
128 for( int i=channels; --i>=0; ) {
129 AssetPicon::draw_wave(vframe, samples[i]->get_data(), bfrsz,
130 base_colors[i], line_colors[i]);
133 for( int i=channels; --i>=0; ) delete samples[i];
134 delete render_engine;
136 delete canvas->refresh_frame;
137 canvas->refresh_frame = vframe;
138 canvas->draw_refresh(1);
141 void VWindowGUI::change_source(EDL *edl, const char *title)
143 //printf("VWindowGUI::change_source %d\n", __LINE__);
145 update_sources(title);
146 strcpy(loaded_title, title);
147 char string[BCTEXTLEN];
149 sprintf(string, _(PROGRAM_NAME ": %s"), title);
151 sprintf(string, _(PROGRAM_NAME ": Viewer"));
153 lock_window("VWindowGUI::change_source");
156 !edl->tracks->playable_video_tracks() &&
157 edl->tracks->playable_audio_tracks() )
165 // Get source list from master EDL
166 void VWindowGUI::update_sources(const char *title)
168 lock_window("VWindowGUI::update_sources");
169 sources.remove_all_objects();
171 for( int i=0; i<mwindow->edl->clips.size(); ++i ) {
172 char *clip_title = mwindow->edl->clips.values[i]->local_session->clip_title;
175 for( int j=0; !exists && j<sources.size(); ++j ) {
176 if( !strcasecmp(sources.values[j]->get_text(), clip_title) )
181 sources.append(new BC_ListBoxItem(clip_title));
185 for( Asset *current=mwindow->edl->assets->first; current; current=NEXT ) {
186 char clip_title[BCTEXTLEN];
187 fs.extract_name(clip_title, current->path);
190 for( int j=0; !exists && j<sources.size(); ++j ) {
191 if( !strcasecmp(sources.values[j]->get_text(), clip_title) )
196 sources.append(new BC_ListBoxItem(clip_title));
202 void VWindowGUI::create_objects()
204 lock_window("VWindowGUI::create_objects");
207 set_icon(mwindow->theme->get_image("vwindow_icon"));
209 //printf("VWindowGUI::create_objects 1\n");
210 mwindow->theme->get_vwindow_sizes(this);
211 mwindow->theme->draw_vwindow_bg(this);
214 meters = new VWindowMeters(mwindow,
216 mwindow->theme->vmeter_x,
217 mwindow->theme->vmeter_y,
218 mwindow->theme->vmeter_h);
219 meters->create_objects();
221 //printf("VWindowGUI::create_objects 1\n");
222 // Requires meters to build
223 edit_panel = new VWindowEditing(mwindow, vwindow);
224 edit_panel->set_meters(meters);
225 edit_panel->create_objects();
227 //printf("VWindowGUI::create_objects 1\n");
228 transport = new VWindowTransport(mwindow,
230 mwindow->theme->vtransport_x,
231 mwindow->theme->vtransport_y);
232 transport->create_objects();
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));
241 canvas = new VWindowCanvas(mwindow, this);
242 canvas->create_objects(mwindow->edl);
243 canvas->use_vwindow();
246 //printf("VWindowGUI::create_objects 1\n");
247 add_subwindow(timebar = new VTimeBar(mwindow,
249 mwindow->theme->vtimebar_x,
250 mwindow->theme->vtimebar_y,
251 mwindow->theme->vtimebar_w,
252 mwindow->theme->vtimebar_h));
253 timebar->create_objects();
254 //printf("VWindowGUI::create_objects 2\n");
257 //printf("VWindowGUI::create_objects 1\n");
258 // source = new VWindowSource(mwindow,
260 // mwindow->theme->vsource_x,
261 // mwindow->theme->vsource_y);
262 // source->create_objects();
263 update_sources(_("None"));
265 //printf("VWindowGUI::create_objects 2\n");
272 int VWindowGUI::resize_event(int w, int h)
274 mwindow->session->vwindow_x = get_x();
275 mwindow->session->vwindow_y = get_y();
276 mwindow->session->vwindow_w = w;
277 mwindow->session->vwindow_h = h;
279 mwindow->theme->get_vwindow_sizes(this);
280 mwindow->theme->draw_vwindow_bg(this);
283 //printf("VWindowGUI::resize_event %d %d\n", __LINE__, mwindow->theme->vedit_y);
284 edit_panel->reposition_buttons(mwindow->theme->vedit_x,
285 mwindow->theme->vedit_y);
287 timebar->resize_event();
288 transport->reposition_buttons(mwindow->theme->vtransport_x,
289 mwindow->theme->vtransport_y);
290 clock->reposition_window(mwindow->theme->vtime_x,
291 mwindow->theme->vtime_y,
292 mwindow->theme->vtime_w,
294 canvas->reposition_window(0,
295 mwindow->theme->vcanvas_x,
296 mwindow->theme->vcanvas_y,
297 mwindow->theme->vcanvas_w,
298 mwindow->theme->vcanvas_h);
299 //printf("VWindowGUI::resize_event %d %d\n", __LINE__, mwindow->theme->vcanvas_x);
300 // source->reposition_window(mwindow->theme->vsource_x,
301 // mwindow->theme->vsource_y);
302 meters->reposition_window(mwindow->theme->vmeter_x,
303 mwindow->theme->vmeter_y,
305 mwindow->theme->vmeter_h);
307 BC_WindowBase::resize_event(w, h);
315 int VWindowGUI::translation_event()
317 mwindow->session->vwindow_x = get_x();
318 mwindow->session->vwindow_y = get_y();
322 int VWindowGUI::close_event()
325 int i = mwindow->vwindows.size();
326 while( --i >= 0 && mwindow->vwindows.get(i)->gui != this );
332 mwindow->session->show_vwindow = 0;
335 mwindow->gui->lock_window("VWindowGUI::close_event");
336 mwindow->gui->mainmenu->show_vwindow->set_checked(0);
337 mwindow->gui->unlock_window();
339 lock_window("VWindowGUI::close_event");
340 mwindow->save_defaults();
344 int VWindowGUI::keypress_event()
347 switch( get_keypress() ) {
354 mwindow->undo_entry(this);
357 mwindow->redo_entry(this);
361 if( canvas->get_fullscreen() )
362 canvas->stop_fullscreen();
364 canvas->start_fullscreen();
365 lock_window("VWindowGUI::keypress_event 1");
369 if( canvas->get_fullscreen() )
370 canvas->stop_fullscreen();
371 lock_window("VWindowGUI::keypress_event 2");
377 if( ctrl_down() && shift_down() ) {
378 resend_event(mwindow->gui);
384 result = transport->keypress_event();
388 int VWindowGUI::button_press_event()
390 if( vwindow->get_edl() != 0 && canvas->get_canvas() &&
391 mwindow->edl->session->vwindow_click2play &&
392 canvas->get_canvas()->get_cursor_over_window() ) {
393 switch( get_buttonpress() ) {
395 if( !vwindow->playback_engine->is_playing_back ) {
396 double length = vwindow->get_edl()->tracks->total_playable_length();
397 double position = vwindow->playback_engine->get_tracking_position();
398 if( position >= length ) transport->goto_start();
400 return transport->forward_play->handle_event();
402 if( !vwindow->playback_engine->is_playing_back ) {
403 double position = vwindow->playback_engine->get_tracking_position();
404 if( position <= 0 ) transport->goto_end();
406 return transport->reverse_play->handle_event();
407 case RIGHT_BUTTON: // activates popup
410 return transport->frame_forward_play->handle_event();
412 return transport->frame_reverse_play->handle_event();
415 if(canvas->get_canvas())
416 return canvas->button_press_event_base(canvas->get_canvas());
420 int VWindowGUI::cursor_leave_event()
422 if(canvas->get_canvas())
423 return canvas->cursor_leave_event_base(canvas->get_canvas());
427 int VWindowGUI::cursor_enter_event()
429 if(canvas->get_canvas())
430 return canvas->cursor_enter_event_base(canvas->get_canvas());
434 int VWindowGUI::button_release_event()
436 if(canvas->get_canvas())
437 return canvas->button_release_event();
441 int VWindowGUI::cursor_motion_event()
443 if(canvas->get_canvas())
445 canvas->get_canvas()->unhide_cursor();
446 return canvas->cursor_motion_event();
452 void VWindowGUI::drag_motion()
455 if(get_hidden()) return;
456 if(mwindow->session->current_operation != DRAG_ASSET) return;
457 int need_highlight = cursor_above() && get_cursor_over_window() ? 1 : 0;
458 if( highlighted == need_highlight ) return;
459 highlighted = need_highlight;
460 canvas->draw_refresh();
463 int VWindowGUI::drag_stop()
465 if( get_hidden() ) return 0;
468 mwindow->session->current_operation == DRAG_ASSET ) {
470 canvas->draw_refresh();
473 Indexable *indexable =
474 mwindow->session->drag_assets->size() > 0 ?
475 (Indexable *)mwindow->session->drag_assets->get(0) :
476 mwindow->session->drag_clips->size() > 0 ?
477 (Indexable *)mwindow->session->drag_clips->get(0) : 0;
479 vwindow->change_source(indexable);
481 lock_window("VWindowGUI::drag_stop");
488 void VWindowGUI::stop_transport()
490 if( !transport->is_stopped() ) {
492 transport->handle_transport(STOP, 1);
493 lock_window("VWindowGUI::panel_stop_transport");
497 void VWindowGUI::update_meters()
499 if(mwindow->edl->session->vwindow_meter != meters->visible)
501 meters->set_meters(meters->meter_count,
502 mwindow->edl->session->vwindow_meter);
503 mwindow->theme->get_vwindow_sizes(this);
504 resize_event(get_w(), get_h());
510 VWindowMeters::VWindowMeters(MWindow *mwindow,
515 : MeterPanel(mwindow,
521 mwindow->edl->session->audio_channels,
522 mwindow->edl->session->vwindow_meter,
526 this->mwindow = mwindow;
530 VWindowMeters::~VWindowMeters()
534 int VWindowMeters::change_status_event(int new_status)
536 mwindow->edl->session->vwindow_meter = new_status;
537 gui->update_meters();
542 VWindowEditing::VWindowEditing(MWindow *mwindow, VWindow *vwindow)
543 : EditPanel(mwindow, vwindow->gui, VWINDOW_ID,
544 mwindow->theme->vedit_x, mwindow->theme->vedit_y,
546 0, // use_editing_mode
563 this->mwindow = mwindow;
564 this->vwindow = vwindow;
567 VWindowEditing::~VWindowEditing()
571 #define relock_vm(s) \
572 vwindow->gui->unlock_window(); \
573 mwindow->gui->lock_window("VWindowEditing::" s)
574 #define relock_mv(s) \
575 mwindow->gui->unlock_window(); \
576 vwindow->gui->lock_window("VWindowEditing::" s)
578 double VWindowEditing::get_position()
580 EDL *edl = vwindow->get_edl();
581 double position = !edl ? 0 : edl->local_session->get_selectionstart(1);
585 void VWindowEditing::set_position(double position)
587 EDL *edl = vwindow->get_edl();
589 if( get_position() != position ) {
590 if( position < 0 ) position = 0;
591 edl->local_session->set_selectionstart(position);
592 edl->local_session->set_selectionend(position);
593 vwindow->update_position();
597 void VWindowEditing::set_click_to_play(int v)
599 click2play->update(v);
600 relock_vm("set_click_to_play");
601 mwindow->edl->session->vwindow_click2play = v;
602 mwindow->update_vwindow();
603 relock_mv("set_click_to_play");
606 void VWindowEditing::panel_stop_transport()
608 vwindow->gui->stop_transport();
611 void VWindowEditing::panel_toggle_label()
613 if( !vwindow->get_edl() ) return;
614 EDL *edl = vwindow->get_edl();
615 edl->labels->toggle_label(edl->local_session->get_selectionstart(1),
616 edl->local_session->get_selectionend(1));
617 vwindow->gui->timebar->update(1);
620 void VWindowEditing::panel_next_label(int cut)
622 if( !vwindow->get_edl() ) return;
623 vwindow->interrupt_playback(1);
625 EDL *edl = vwindow->get_edl();
626 Label *current = edl->labels->next_label(
627 edl->local_session->get_selectionstart(1));
628 double position = current ? current->position :
629 edl->tracks->total_length();
630 edl->local_session->set_selectionstart(position);
631 edl->local_session->set_selectionend(position);
632 vwindow->update_position();
633 vwindow->gui->timebar->update(1);
636 void VWindowEditing::panel_prev_label(int cut)
638 if( !vwindow->get_edl() ) return;
639 vwindow->interrupt_playback(1);
641 EDL *edl = vwindow->get_edl();
642 Label *current = edl->labels->prev_label(
643 edl->local_session->get_selectionstart(1));
644 double position = !current ? 0 : current->position;
645 edl->local_session->set_selectionstart(position);
646 edl->local_session->set_selectionend(position);
647 vwindow->update_position();
648 vwindow->gui->timebar->update(1);
651 void VWindowEditing::panel_prev_edit(int cut) {} // not used
652 void VWindowEditing::panel_next_edit(int cut) {} // not used
654 void VWindowEditing::panel_copy_selection()
656 vwindow->copy(vwindow->gui->shift_down());
659 void VWindowEditing::panel_overwrite_selection()
661 if( !vwindow->get_edl() ) return;
662 relock_vm("overwrite_selection");
663 mwindow->overwrite(vwindow->get_edl(), vwindow->gui->shift_down());
664 relock_mv("overwrite_selection");
667 void VWindowEditing::panel_splice_selection()
669 if( !vwindow->get_edl() ) return;
670 relock_vm("splice_selection");
671 mwindow->splice(vwindow->get_edl(), vwindow->gui->shift_down());
672 relock_mv("splice_selection");
675 void VWindowEditing::panel_set_inpoint()
677 vwindow->set_inpoint();
680 void VWindowEditing::panel_set_outpoint()
682 vwindow->set_outpoint();
685 void VWindowEditing::panel_unset_inoutpoint()
687 vwindow->unset_inoutpoint();
690 void VWindowEditing::panel_to_clip()
692 EDL *edl = vwindow->get_edl();
694 mwindow->to_clip(edl, _("viewer window: "), subwindow->shift_down());
698 void VWindowEditing::panel_cut() {}
699 void VWindowEditing::panel_paste() {}
700 void VWindowEditing::panel_fit_selection() {}
701 void VWindowEditing::panel_fit_autos(int all) {}
702 void VWindowEditing::panel_set_editing_mode(int mode) {}
703 void VWindowEditing::panel_set_auto_keyframes(int v) {}
704 void VWindowEditing::panel_set_labels_follow_edits(int v) {}
707 VWindowSource::VWindowSource(MWindow *mwindow, VWindowGUI *vwindow, int x, int y)
708 : BC_PopupTextBox(vwindow,
716 this->mwindow = mwindow;
717 this->vwindow = vwindow;
720 VWindowSource::~VWindowSource()
724 int VWindowSource::handle_event()
730 VWindowTransport::VWindowTransport(MWindow *mwindow,
734 : PlayTransport(mwindow,
742 EDL* VWindowTransport::get_edl()
744 return gui->vwindow->get_edl();
748 void VWindowTransport::goto_start()
750 gui->unlock_window();
751 handle_transport(REWIND, 1);
752 gui->lock_window("VWindowTransport::goto_start");
753 gui->vwindow->goto_start();
756 void VWindowTransport::goto_end()
758 gui->unlock_window();
759 handle_transport(GOTO_END, 1);
760 gui->lock_window("VWindowTransport::goto_end");
761 gui->vwindow->goto_end();
767 VWindowCanvas::VWindowCanvas(MWindow *mwindow, VWindowGUI *gui)
770 mwindow->theme->vcanvas_x,
771 mwindow->theme->vcanvas_y,
772 mwindow->theme->vcanvas_w,
773 mwindow->theme->vcanvas_h,
776 //printf("VWindowCanvas::VWindowCanvas %d %d\n", __LINE__, mwindow->theme->vcanvas_x);
777 this->mwindow = mwindow;
781 void VWindowCanvas::zoom_resize_window(float percentage)
783 EDL *edl = gui->vwindow->get_edl();
784 if(!edl) edl = mwindow->edl;
786 int canvas_w, canvas_h;
789 // Get required canvas size
790 calculate_sizes(edl->get_aspect_ratio(),
791 edl->session->output_w,
792 edl->session->output_h,
797 // Estimate window size from current borders
798 new_w = canvas_w + (gui->get_w() - mwindow->theme->vcanvas_w);
799 new_h = canvas_h + (gui->get_h() - mwindow->theme->vcanvas_h);
801 mwindow->session->vwindow_w = new_w;
802 mwindow->session->vwindow_h = new_h;
804 mwindow->theme->get_vwindow_sizes(gui);
806 // Estimate again from new borders
807 new_w = canvas_w + (mwindow->session->vwindow_w - mwindow->theme->vcanvas_w);
808 new_h = canvas_h + (mwindow->session->vwindow_h - mwindow->theme->vcanvas_h);
811 gui->resize_window(new_w, new_h);
812 gui->resize_event(new_w, new_h);
815 void VWindowCanvas::close_source()
817 gui->vwindow->interrupt_playback(1);
818 gui->vwindow->delete_source(1, 1);
822 void VWindowCanvas::draw_refresh(int flush)
824 EDL *edl = gui->vwindow->get_edl();
826 if(!get_canvas()->get_video_on()) get_canvas()->clear_box(0, 0, get_canvas()->get_w(), get_canvas()->get_h());
827 if(!get_canvas()->get_video_on() && refresh_frame && edl)
829 float in_x1, in_y1, in_x2, in_y2;
830 float out_x1, out_y1, out_x2, out_y2;
832 in_x1, in_y1, in_x2, in_y2,
833 out_x1, out_y1, out_x2, out_y2);
834 // input scaled from session to refresh frame coordinates
835 int ow = get_output_w(edl);
836 int oh = get_output_h(edl);
837 int rw = refresh_frame->get_w();
838 int rh = refresh_frame->get_h();
839 float xs = (float)rw / ow;
840 float ys = (float)rh / oh;
841 in_x1 *= xs; in_x2 *= xs;
842 in_y1 *= ys; in_y2 *= ys;
843 get_canvas()->draw_vframe(refresh_frame,
846 (int)(out_x2 - out_x1),
847 (int)(out_y2 - out_y1),
850 (int)(in_x2 - in_x1),
851 (int)(in_y2 - in_y1),
855 if(!get_canvas()->get_video_on())
858 get_canvas()->flash(flush);
862 int VWindowCanvas::need_overlays()
864 if( gui->highlighted ) return 1;
868 void VWindowCanvas::draw_overlays()
870 if( gui->highlighted )
872 get_canvas()->set_color(WHITE);
873 get_canvas()->set_inverse();
874 get_canvas()->draw_rectangle(0, 0, get_canvas()->get_w(), get_canvas()->get_h());
875 get_canvas()->draw_rectangle(1, 1, get_canvas()->get_w() - 2, get_canvas()->get_h() - 2);
876 get_canvas()->set_opaque();