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
24 #include "awindowgui.h"
30 #include "edlsession.h"
31 #include "filesystem.h"
37 #include "localsession.h"
38 #include "mainclock.h"
40 #include "mainsession.h"
42 #include "meterpanel.h"
43 #include "mwindowgui.h"
45 #include "playtransport.h"
46 #include "preferences.h"
51 #include "vplayback.h"
53 #include "vwindowgui.h"
59 VWindowGUI::VWindowGUI(MWindow *mwindow, VWindow *vwindow)
60 : BC_Window(_(PROGRAM_NAME ": Viewer"),
61 mwindow->session->vwindow_x,
62 mwindow->session->vwindow_y,
63 mwindow->session->vwindow_w,
64 mwindow->session->vwindow_h,
71 this->mwindow = mwindow;
72 this->vwindow = vwindow;
78 strcpy(loaded_title, "");
82 VWindowGUI::~VWindowGUI()
84 vwindow->playback_engine->interrupt_playback(1);
85 sources.remove_all_objects();
86 labels.remove_all_objects();
94 void VWindowGUI::change_source(EDL *edl, const char *title)
96 //printf("VWindowGUI::change_source %d\n", __LINE__);
98 update_sources(title);
99 strcpy(loaded_title, title);
100 char string[BCTEXTLEN];
102 sprintf(string, _(PROGRAM_NAME ": %s"), title);
104 sprintf(string, _(PROGRAM_NAME ": Viewer"));
106 lock_window("VWindowGUI::change_source");
114 // Get source list from master EDL
115 void VWindowGUI::update_sources(const char *title)
117 lock_window("VWindowGUI::update_sources");
119 //printf("VWindowGUI::update_sources 1\n");
120 sources.remove_all_objects();
121 //printf("VWindowGUI::update_sources 2\n");
126 i < mwindow->edl->clips.total;
129 char *clip_title = mwindow->edl->clips.values[i]->local_session->clip_title;
132 for(int j = 0; j < sources.total; j++)
134 if(!strcasecmp(sources.values[j]->get_text(), clip_title))
142 sources.append(new BC_ListBoxItem(clip_title));
145 //printf("VWindowGUI::update_sources 3\n");
148 for(Asset *current = mwindow->edl->assets->first;
152 char clip_title[BCTEXTLEN];
153 fs.extract_name(clip_title, current->path);
156 for(int j = 0; j < sources.total; j++)
158 if(!strcasecmp(sources.values[j]->get_text(), clip_title))
166 sources.append(new BC_ListBoxItem(clip_title));
170 //printf("VWindowGUI::update_sources 4\n");
172 // source->update_list(&sources);
173 // source->update(title);
177 void VWindowGUI::create_objects()
181 lock_window("VWindowGUI::create_objects");
182 set_icon(mwindow->theme->get_image("vwindow_icon"));
184 //printf("VWindowGUI::create_objects 1\n");
185 mwindow->theme->get_vwindow_sizes(this);
186 mwindow->theme->draw_vwindow_bg(this);
189 meters = new VWindowMeters(mwindow,
191 mwindow->theme->vmeter_x,
192 mwindow->theme->vmeter_y,
193 mwindow->theme->vmeter_h);
194 meters->create_objects();
196 //printf("VWindowGUI::create_objects 1\n");
197 // Requires meters to build
198 edit_panel = new VWindowEditing(mwindow, vwindow);
199 edit_panel->set_meters(meters);
200 edit_panel->create_objects();
202 //printf("VWindowGUI::create_objects 1\n");
203 transport = new VWindowTransport(mwindow,
205 mwindow->theme->vtransport_x,
206 mwindow->theme->vtransport_y);
207 transport->create_objects();
209 //printf("VWindowGUI::create_objects 1\n");
210 // add_subwindow(fps_title = new BC_Title(mwindow->theme->vedit_x, y, ""));
211 add_subwindow(clock = new MainClock(mwindow,
212 mwindow->theme->vtime_x,
213 mwindow->theme->vtime_y,
214 mwindow->theme->vtime_w));
216 canvas = new VWindowCanvas(mwindow, this);
217 canvas->create_objects(mwindow->edl);
218 canvas->use_vwindow();
221 //printf("VWindowGUI::create_objects 1\n");
222 add_subwindow(timebar = new VTimeBar(mwindow,
224 mwindow->theme->vtimebar_x,
225 mwindow->theme->vtimebar_y,
226 mwindow->theme->vtimebar_w,
227 mwindow->theme->vtimebar_h));
228 timebar->create_objects();
229 //printf("VWindowGUI::create_objects 2\n");
232 //printf("VWindowGUI::create_objects 1\n");
233 // source = new VWindowSource(mwindow,
235 // mwindow->theme->vsource_x,
236 // mwindow->theme->vsource_y);
237 // source->create_objects();
238 update_sources(_("None"));
240 //printf("VWindowGUI::create_objects 2\n");
247 int VWindowGUI::resize_event(int w, int h)
249 mwindow->session->vwindow_x = get_x();
250 mwindow->session->vwindow_y = get_y();
251 mwindow->session->vwindow_w = w;
252 mwindow->session->vwindow_h = h;
254 mwindow->theme->get_vwindow_sizes(this);
255 mwindow->theme->draw_vwindow_bg(this);
258 //printf("VWindowGUI::resize_event %d %d\n", __LINE__, mwindow->theme->vedit_y);
259 edit_panel->reposition_buttons(mwindow->theme->vedit_x,
260 mwindow->theme->vedit_y);
262 timebar->resize_event();
263 transport->reposition_buttons(mwindow->theme->vtransport_x,
264 mwindow->theme->vtransport_y);
265 clock->reposition_window(mwindow->theme->vtime_x,
266 mwindow->theme->vtime_y,
267 mwindow->theme->vtime_w,
269 canvas->reposition_window(0,
270 mwindow->theme->vcanvas_x,
271 mwindow->theme->vcanvas_y,
272 mwindow->theme->vcanvas_w,
273 mwindow->theme->vcanvas_h);
274 //printf("VWindowGUI::resize_event %d %d\n", __LINE__, mwindow->theme->vcanvas_x);
275 // source->reposition_window(mwindow->theme->vsource_x,
276 // mwindow->theme->vsource_y);
277 meters->reposition_window(mwindow->theme->vmeter_x,
278 mwindow->theme->vmeter_y,
280 mwindow->theme->vmeter_h);
282 BC_WindowBase::resize_event(w, h);
290 int VWindowGUI::translation_event()
292 mwindow->session->vwindow_x = get_x();
293 mwindow->session->vwindow_y = get_y();
297 int VWindowGUI::close_event()
300 int i = mwindow->vwindows.size();
301 while( --i >= 0 && mwindow->vwindows.get(i)->gui != this );
307 mwindow->session->show_vwindow = 0;
310 mwindow->gui->lock_window("VWindowGUI::close_event");
311 mwindow->gui->mainmenu->show_vwindow->set_checked(0);
312 mwindow->gui->unlock_window();
314 lock_window("VWindowGUI::close_event");
315 mwindow->save_defaults();
319 int VWindowGUI::keypress_event()
322 switch(get_keypress())
330 mwindow->undo_entry(this);
333 mwindow->redo_entry(this);
337 if(mwindow->session->vwindow_fullscreen)
338 canvas->stop_fullscreen();
340 canvas->start_fullscreen();
341 lock_window("VWindowGUI::keypress_event 1");
345 if(mwindow->session->vwindow_fullscreen)
346 canvas->stop_fullscreen();
347 lock_window("VWindowGUI::keypress_event 2");
350 if(!result) result = transport->keypress_event();
351 if( result && !vwindow->playback_engine->is_playing_back )
356 void VWindowGUI::stop_transport(const char *lock_msg)
358 if( !transport->is_stopped() ) {
359 if( lock_msg ) unlock_window();
360 transport->handle_transport(STOP, 1, 0, 0);
361 if( lock_msg ) lock_window(lock_msg);
365 int VWindowGUI::button_press_event()
367 if( vwindow->get_edl() != 0 && canvas->get_canvas() &&
368 canvas->get_canvas()->get_cursor_over_window() ) {
369 switch( get_buttonpress() ) {
371 if( !vwindow->playback_engine->is_playing_back ) {
372 double length = vwindow->get_edl()->tracks->total_playable_length();
373 double position = vwindow->playback_engine->get_tracking_position();
374 if( position >= length ) transport->goto_start();
376 return transport->forward_play->handle_event();
378 if( !vwindow->playback_engine->is_playing_back ) {
379 double position = vwindow->playback_engine->get_tracking_position();
380 if( position <= 0 ) transport->goto_end();
382 return transport->reverse_play->handle_event();
383 case RIGHT_BUTTON: // activates popup
386 return transport->frame_forward_play->handle_event();
388 return transport->frame_reverse_play->handle_event();
391 if(canvas->get_canvas())
392 return canvas->button_press_event_base(canvas->get_canvas());
396 int VWindowGUI::cursor_leave_event()
398 if(canvas->get_canvas())
399 return canvas->cursor_leave_event_base(canvas->get_canvas());
403 int VWindowGUI::cursor_enter_event()
405 if(canvas->get_canvas())
406 return canvas->cursor_enter_event_base(canvas->get_canvas());
410 int VWindowGUI::button_release_event()
412 if(canvas->get_canvas())
413 return canvas->button_release_event();
417 int VWindowGUI::cursor_motion_event()
419 if(canvas->get_canvas())
421 canvas->get_canvas()->unhide_cursor();
422 return canvas->cursor_motion_event();
428 void VWindowGUI::drag_motion()
431 if(get_hidden()) return;
432 if(mwindow->session->current_operation != DRAG_ASSET) return;
433 int need_highlight = cursor_above() && get_cursor_over_window() ? 1 : 0;
434 if( highlighted == need_highlight ) return;
435 highlighted = need_highlight;
436 canvas->draw_refresh();
439 int VWindowGUI::drag_stop()
441 if(get_hidden()) return 0;
444 mwindow->session->current_operation == DRAG_ASSET)
447 canvas->draw_refresh();
450 Indexable *indexable = mwindow->session->drag_assets->size() ?
451 mwindow->session->drag_assets->get(0) :
453 EDL *edl = mwindow->session->drag_clips->size() ?
454 mwindow->session->drag_clips->get(0) :
457 vwindow->change_source(indexable);
460 vwindow->change_source(edl);
461 lock_window("VWindowGUI::drag_stop");
469 void VWindowGUI::update_meters()
471 if(mwindow->edl->session->vwindow_meter != meters->visible)
473 meters->set_meters(meters->meter_count,
474 mwindow->edl->session->vwindow_meter);
475 mwindow->theme->get_vwindow_sizes(this);
476 resize_event(get_w(), get_h());
482 VWindowMeters::VWindowMeters(MWindow *mwindow,
487 : MeterPanel(mwindow,
493 mwindow->edl->session->audio_channels,
494 mwindow->edl->session->vwindow_meter,
498 this->mwindow = mwindow;
502 VWindowMeters::~VWindowMeters()
506 int VWindowMeters::change_status_event(int new_status)
508 mwindow->edl->session->vwindow_meter = new_status;
509 gui->update_meters();
519 VWindowEditing::VWindowEditing(MWindow *mwindow, VWindow *vwindow)
522 mwindow->theme->vedit_x,
523 mwindow->theme->vedit_y,
543 this->mwindow = mwindow;
544 this->vwindow = vwindow;
547 VWindowEditing::~VWindowEditing()
551 void VWindowEditing::copy_selection()
556 void VWindowEditing::splice_selection()
558 if(vwindow->get_edl())
560 mwindow->gui->lock_window("VWindowEditing::splice_selection");
561 mwindow->splice(vwindow->get_edl());
562 mwindow->gui->unlock_window();
566 void VWindowEditing::overwrite_selection()
568 if(vwindow->get_edl())
570 mwindow->gui->lock_window("VWindowEditing::overwrite_selection");
571 mwindow->overwrite(vwindow->get_edl());
572 mwindow->gui->unlock_window();
576 void VWindowEditing::toggle_label()
578 if(vwindow->get_edl())
580 EDL *edl = vwindow->get_edl();
581 edl->labels->toggle_label(edl->local_session->get_selectionstart(1),
582 edl->local_session->get_selectionend(1));
583 vwindow->gui->timebar->update(1);
587 void VWindowEditing::prev_label()
589 if(vwindow->get_edl())
591 EDL *edl = vwindow->get_edl();
592 vwindow->gui->unlock_window();
593 vwindow->playback_engine->interrupt_playback(1);
594 vwindow->gui->lock_window("VWindowEditing::prev_label");
596 Label *current = edl->labels->prev_label(
597 edl->local_session->get_selectionstart(1));
602 edl->local_session->set_selectionstart(0);
603 edl->local_session->set_selectionend(0);
604 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
605 vwindow->gui->timebar->update(1);
609 edl->local_session->set_selectionstart(current->position);
610 edl->local_session->set_selectionend(current->position);
611 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
612 vwindow->gui->timebar->update(1);
617 void VWindowEditing::next_label()
619 if(vwindow->get_edl())
621 EDL *edl = vwindow->get_edl();
622 Label *current = edl->labels->next_label(
623 edl->local_session->get_selectionstart(1));
626 vwindow->gui->unlock_window();
627 vwindow->playback_engine->interrupt_playback(1);
628 vwindow->gui->lock_window("VWindowEditing::next_label 1");
630 double position = edl->tracks->total_length();
631 edl->local_session->set_selectionstart(position);
632 edl->local_session->set_selectionend(position);
633 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
634 vwindow->gui->timebar->update(1);
638 vwindow->gui->unlock_window();
639 vwindow->playback_engine->interrupt_playback(1);
640 vwindow->gui->lock_window("VWindowEditing::next_label 2");
642 edl->local_session->set_selectionstart(current->position);
643 edl->local_session->set_selectionend(current->position);
644 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
645 vwindow->gui->timebar->update(1);
650 double VWindowEditing::get_position()
652 EDL *edl = vwindow->get_edl();
653 double position = !edl ? 0 : edl->local_session->get_selectionstart(1);
657 void VWindowEditing::set_position(double position)
659 EDL *edl = vwindow->get_edl();
661 if( get_position() != position ) {
662 if( position < 0 ) position = 0;
663 edl->local_session->set_selectionstart(position);
664 edl->local_session->set_selectionend(position);
665 vwindow->update_position(CHANGE_NONE, 0, 1);
669 void VWindowEditing::set_inpoint()
671 vwindow->set_inpoint();
674 void VWindowEditing::set_outpoint()
676 vwindow->set_outpoint();
679 void VWindowEditing::unset_inoutpoint()
681 vwindow->unset_inoutpoint();
685 void VWindowEditing::to_clip()
687 EDL *edl = vwindow->get_edl();
689 mwindow->to_clip(edl, _("viewer window: "));
692 VWindowSource::VWindowSource(MWindow *mwindow, VWindowGUI *vwindow, int x, int y)
693 : BC_PopupTextBox(vwindow,
701 this->mwindow = mwindow;
702 this->vwindow = vwindow;
705 VWindowSource::~VWindowSource()
709 int VWindowSource::handle_event()
715 VWindowTransport::VWindowTransport(MWindow *mwindow,
719 : PlayTransport(mwindow,
727 EDL* VWindowTransport::get_edl()
729 return gui->vwindow->get_edl();
733 void VWindowTransport::goto_start()
735 gui->unlock_window();
736 handle_transport(REWIND, 1);
737 gui->lock_window("VWindowTransport::goto_start");
738 gui->vwindow->goto_start();
741 void VWindowTransport::goto_end()
743 gui->unlock_window();
744 handle_transport(GOTO_END, 1);
745 gui->lock_window("VWindowTransport::goto_end");
746 gui->vwindow->goto_end();
752 VWindowCanvas::VWindowCanvas(MWindow *mwindow, VWindowGUI *gui)
755 mwindow->theme->vcanvas_x,
756 mwindow->theme->vcanvas_y,
757 mwindow->theme->vcanvas_w,
758 mwindow->theme->vcanvas_h,
761 //printf("VWindowCanvas::VWindowCanvas %d %d\n", __LINE__, mwindow->theme->vcanvas_x);
762 this->mwindow = mwindow;
766 void VWindowCanvas::zoom_resize_window(float percentage)
768 EDL *edl = gui->vwindow->get_edl();
769 if(!edl) edl = mwindow->edl;
771 int canvas_w, canvas_h;
774 // Get required canvas size
775 calculate_sizes(edl->get_aspect_ratio(),
776 edl->session->output_w,
777 edl->session->output_h,
782 // Estimate window size from current borders
783 new_w = canvas_w + (gui->get_w() - mwindow->theme->vcanvas_w);
784 new_h = canvas_h + (gui->get_h() - mwindow->theme->vcanvas_h);
786 mwindow->session->vwindow_w = new_w;
787 mwindow->session->vwindow_h = new_h;
789 mwindow->theme->get_vwindow_sizes(gui);
791 // Estimate again from new borders
792 new_w = canvas_w + (mwindow->session->vwindow_w - mwindow->theme->vcanvas_w);
793 new_h = canvas_h + (mwindow->session->vwindow_h - mwindow->theme->vcanvas_h);
796 gui->resize_window(new_w, new_h);
797 gui->resize_event(new_w, new_h);
800 void VWindowCanvas::close_source()
802 gui->unlock_window();
803 gui->vwindow->playback_engine->interrupt_playback(1);
804 gui->lock_window("VWindowCanvas::close_source");
805 gui->vwindow->delete_source(1, 1);
809 void VWindowCanvas::draw_refresh(int flush)
811 EDL *edl = gui->vwindow->get_edl();
813 if(!get_canvas()->get_video_on()) get_canvas()->clear_box(0, 0, get_canvas()->get_w(), get_canvas()->get_h());
814 if(!get_canvas()->get_video_on() && refresh_frame && edl)
816 float in_x1, in_y1, in_x2, in_y2;
817 float out_x1, out_y1, out_x2, out_y2;
827 get_canvas()->draw_vframe(refresh_frame,
830 (int)(out_x2 - out_x1),
831 (int)(out_y2 - out_y1),
834 (int)(in_x2 - in_x1),
835 (int)(in_y2 - in_y1),
839 if(!get_canvas()->get_video_on())
842 get_canvas()->flash(flush);
846 void VWindowCanvas::draw_overlays()
848 if( gui->highlighted )
850 get_canvas()->set_color(WHITE);
851 get_canvas()->set_inverse();
852 get_canvas()->draw_rectangle(0, 0, get_canvas()->get_w(), get_canvas()->get_h());
853 get_canvas()->draw_rectangle(1, 1, get_canvas()->get_w() - 2, get_canvas()->get_h() - 2);
854 get_canvas()->set_opaque();
858 int VWindowCanvas::get_fullscreen()
860 return mwindow->session->vwindow_fullscreen;
863 void VWindowCanvas::set_fullscreen(int value)
865 mwindow->session->vwindow_fullscreen = value;
905 void VWindowGUI::update_points()
907 EDL *edl = vwindow->get_edl();
909 //printf("VWindowGUI::update_points 1\n");
912 //printf("VWindowGUI::update_points 2\n");
913 long pixel = (long)((double)edl->local_session->in_point /
914 edl->tracks->total_length() *
915 (mwindow->theme->vtimebar_w -
917 mwindow->theme->in_point[0]->get_w())) +
918 mwindow->theme->in_point[0]->get_w();
920 //printf("VWindowGUI::update_points 3 %d\n", edl->local_session->in_point);
923 //printf("VWindowGUI::update_points 3.1\n");
924 if(edl->local_session->in_point >= 0)
926 //printf("VWindowGUI::update_points 4\n");
927 if(edl->local_session->in_point != in_point->position ||
928 in_point->pixel != pixel)
930 in_point->pixel = pixel;
931 in_point->reposition();
934 //printf("VWindowGUI::update_points 5\n");
935 in_point->position = edl->local_session->in_point;
937 //printf("VWindowGUI::update_points 6\n");
938 if(edl->equivalent(in_point->position, edl->local_session->get_selectionstart(1)) ||
939 edl->equivalent(in_point->position, edl->local_session->get_selectionend(1)))
943 //printf("VWindowGUI::update_points 7\n");
952 if(edl->local_session->in_point >= 0)
954 //printf("VWindowGUI::update_points 8 %p\n", mwindow->theme->in_point);
955 add_subwindow(in_point =
956 new VWindowInPoint(mwindow,
960 edl->local_session->in_point));
961 //printf("VWindowGUI::update_points 9\n");
963 //printf("VWindowGUI::update_points 10\n");
965 pixel = (long)((double)edl->local_session->out_point /
966 (edl->tracks->total_length() + 0.5) *
967 (mwindow->theme->vtimebar_w -
969 mwindow->theme->in_point[0]->get_w())) +
970 mwindow->theme->in_point[0]->get_w() *
975 if(edl->local_session->out_point >= 0 && pixel >= 0 && pixel <= mwindow->theme->vtimebar_w)
977 if(edl->local_session->out_point != out_point->position ||
978 out_point->pixel != pixel)
980 out_point->pixel = pixel;
981 out_point->reposition();
983 out_point->position = edl->local_session->out_point;
985 if(edl->equivalent(out_point->position, edl->local_session->get_selectionstart(1)) ||
986 edl->equivalent(out_point->position, edl->local_session->get_selectionend(1)))
987 out_point->update(1);
989 out_point->update(0);
998 if(edl->local_session->out_point >= 0 && pixel >= 0 && pixel <= mwindow->theme->vtimebar_w)
1000 add_subwindow(out_point =
1001 new VWindowOutPoint(mwindow,
1005 edl->local_session->out_point));
1010 void VWindowGUI::update_labels()
1012 EDL *edl = vwindow->get_edl();
1015 for(Label *current = edl->labels->first;
1019 long pixel = (long)((current->position - edl->local_session->view_start) / edl->local_session->zoom_sample);
1021 if(pixel >= 0 && pixel < mwindow->theme->vtimebar_w)
1024 if(output >= labels.total)
1026 LabelGUI *new_label;
1027 add_subwindow(new_label = new LabelGUI(mwindow, this, pixel, 0, current->position));
1028 labels.append(new_label);
1031 // Reposition old label
1032 if(labels.values[output]->pixel != pixel)
1034 labels.values[output]->pixel = pixel;
1035 labels.values[output]->position = current->position;
1036 labels.values[output]->reposition();
1039 if(mwindow->edl->local_session->get_selectionstart(1) <= current->position &&
1040 mwindow->edl->local_session->get_selectionend(1) >= current->position)
1041 labels.values[output]->update(1);
1043 if(labels.values[output]->get_value())
1044 labels.values[output]->update(0);
1049 // Delete excess labels
1050 while(labels.total > output)
1052 labels.remove_object();
1058 VWindowInPoint::VWindowInPoint(MWindow *mwindow,
1063 : InPointGUI(mwindow,
1071 int VWindowInPoint::handle_event()
1073 EDL *edl = gui->vwindow->get_edl();
1077 double position = edl->align_to_frame(this->position, 0);
1079 edl->local_session->set_selectionstart(position);
1080 edl->local_session->set_selectionend(position);
1081 gui->timebar->update(1);
1084 mwindow->vwindow->update_position(CHANGE_NONE, 0, 1, 0);
1091 VWindowOutPoint::VWindowOutPoint(MWindow *mwindow,
1096 : OutPointGUI(mwindow,
1104 int VWindowOutPoint::handle_event()
1106 EDL *edl = gui->vwindow->get_edl();
1110 double position = edl->align_to_frame(this->position, 0);
1112 edl->local_session->set_selectionstart(position);
1113 edl->local_session->set_selectionend(position);
1114 gui->timebar->update(1);
1117 mwindow->vwindow->update_position(CHANGE_NONE, 0, 1, 0);