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");
113 // Get source list from master EDL
114 void VWindowGUI::update_sources(const char *title)
116 lock_window("VWindowGUI::update_sources");
118 //printf("VWindowGUI::update_sources 1\n");
119 sources.remove_all_objects();
120 //printf("VWindowGUI::update_sources 2\n");
125 i < mwindow->edl->clips.total;
128 char *clip_title = mwindow->edl->clips.values[i]->local_session->clip_title;
131 for(int j = 0; j < sources.total; j++)
133 if(!strcasecmp(sources.values[j]->get_text(), clip_title))
141 sources.append(new BC_ListBoxItem(clip_title));
144 //printf("VWindowGUI::update_sources 3\n");
147 for(Asset *current = mwindow->edl->assets->first;
151 char clip_title[BCTEXTLEN];
152 fs.extract_name(clip_title, current->path);
155 for(int j = 0; j < sources.total; j++)
157 if(!strcasecmp(sources.values[j]->get_text(), clip_title))
165 sources.append(new BC_ListBoxItem(clip_title));
169 //printf("VWindowGUI::update_sources 4\n");
171 // source->update_list(&sources);
172 // source->update(title);
176 void VWindowGUI::create_objects()
180 lock_window("VWindowGUI::create_objects");
181 set_icon(mwindow->theme->get_image("vwindow_icon"));
183 //printf("VWindowGUI::create_objects 1\n");
184 mwindow->theme->get_vwindow_sizes(this);
185 mwindow->theme->draw_vwindow_bg(this);
188 meters = new VWindowMeters(mwindow,
190 mwindow->theme->vmeter_x,
191 mwindow->theme->vmeter_y,
192 mwindow->theme->vmeter_h);
193 meters->create_objects();
195 //printf("VWindowGUI::create_objects 1\n");
196 // Requires meters to build
197 edit_panel = new VWindowEditing(mwindow, vwindow);
198 edit_panel->set_meters(meters);
199 edit_panel->create_objects();
201 //printf("VWindowGUI::create_objects 1\n");
202 transport = new VWindowTransport(mwindow,
204 mwindow->theme->vtransport_x,
205 mwindow->theme->vtransport_y);
206 transport->create_objects();
208 //printf("VWindowGUI::create_objects 1\n");
209 // add_subwindow(fps_title = new BC_Title(mwindow->theme->vedit_x, y, ""));
210 add_subwindow(clock = new MainClock(mwindow,
211 mwindow->theme->vtime_x,
212 mwindow->theme->vtime_y,
213 mwindow->theme->vtime_w));
215 canvas = new VWindowCanvas(mwindow, this);
216 canvas->create_objects(mwindow->edl);
217 canvas->use_vwindow();
220 //printf("VWindowGUI::create_objects 1\n");
221 add_subwindow(timebar = new VTimeBar(mwindow,
223 mwindow->theme->vtimebar_x,
224 mwindow->theme->vtimebar_y,
225 mwindow->theme->vtimebar_w,
226 mwindow->theme->vtimebar_h));
227 timebar->create_objects();
228 //printf("VWindowGUI::create_objects 2\n");
231 //printf("VWindowGUI::create_objects 1\n");
232 // source = new VWindowSource(mwindow,
234 // mwindow->theme->vsource_x,
235 // mwindow->theme->vsource_y);
236 // source->create_objects();
237 update_sources(_("None"));
239 //printf("VWindowGUI::create_objects 2\n");
246 int VWindowGUI::resize_event(int w, int h)
248 mwindow->session->vwindow_x = get_x();
249 mwindow->session->vwindow_y = get_y();
250 mwindow->session->vwindow_w = w;
251 mwindow->session->vwindow_h = h;
253 mwindow->theme->get_vwindow_sizes(this);
254 mwindow->theme->draw_vwindow_bg(this);
257 //printf("VWindowGUI::resize_event %d %d\n", __LINE__, mwindow->theme->vedit_y);
258 edit_panel->reposition_buttons(mwindow->theme->vedit_x,
259 mwindow->theme->vedit_y);
261 timebar->resize_event();
262 transport->reposition_buttons(mwindow->theme->vtransport_x,
263 mwindow->theme->vtransport_y);
264 clock->reposition_window(mwindow->theme->vtime_x,
265 mwindow->theme->vtime_y,
266 mwindow->theme->vtime_w,
268 canvas->reposition_window(0,
269 mwindow->theme->vcanvas_x,
270 mwindow->theme->vcanvas_y,
271 mwindow->theme->vcanvas_w,
272 mwindow->theme->vcanvas_h);
273 //printf("VWindowGUI::resize_event %d %d\n", __LINE__, mwindow->theme->vcanvas_x);
274 // source->reposition_window(mwindow->theme->vsource_x,
275 // mwindow->theme->vsource_y);
276 meters->reposition_window(mwindow->theme->vmeter_x,
277 mwindow->theme->vmeter_y,
279 mwindow->theme->vmeter_h);
281 BC_WindowBase::resize_event(w, h);
289 int VWindowGUI::translation_event()
291 mwindow->session->vwindow_x = get_x();
292 mwindow->session->vwindow_y = get_y();
296 int VWindowGUI::close_event()
299 int i = mwindow->vwindows.size();
300 while( --i >= 0 && mwindow->vwindows.get(i)->gui != this );
306 mwindow->session->show_vwindow = 0;
309 mwindow->gui->lock_window("VWindowGUI::close_event");
310 mwindow->gui->mainmenu->show_vwindow->set_checked(0);
311 mwindow->gui->unlock_window();
313 lock_window("VWindowGUI::close_event");
314 mwindow->save_defaults();
318 int VWindowGUI::keypress_event()
321 switch(get_keypress())
329 mwindow->undo_entry(this);
332 mwindow->redo_entry(this);
336 if(mwindow->session->vwindow_fullscreen)
337 canvas->stop_fullscreen();
339 canvas->start_fullscreen();
340 lock_window("VWindowGUI::keypress_event 1");
344 if(mwindow->session->vwindow_fullscreen)
345 canvas->stop_fullscreen();
346 lock_window("VWindowGUI::keypress_event 2");
349 if(!result) result = transport->keypress_event();
354 int VWindowGUI::button_press_event()
356 if(canvas->get_canvas())
357 return canvas->button_press_event_base(canvas->get_canvas());
361 int VWindowGUI::cursor_leave_event()
363 if(canvas->get_canvas())
364 return canvas->cursor_leave_event_base(canvas->get_canvas());
368 int VWindowGUI::cursor_enter_event()
370 if(canvas->get_canvas())
371 return canvas->cursor_enter_event_base(canvas->get_canvas());
375 int VWindowGUI::button_release_event()
377 if(canvas->get_canvas())
378 return canvas->button_release_event();
382 int VWindowGUI::cursor_motion_event()
384 if(canvas->get_canvas())
386 canvas->get_canvas()->unhide_cursor();
387 return canvas->cursor_motion_event();
393 void VWindowGUI::drag_motion()
396 if(get_hidden()) return;
397 if(mwindow->session->current_operation != DRAG_ASSET) return;
398 int need_highlight = cursor_above() && get_cursor_over_window() ? 1 : 0;
399 if( highlighted == need_highlight ) return;
400 highlighted = need_highlight;
401 canvas->draw_refresh();
404 int VWindowGUI::drag_stop()
406 if(get_hidden()) return 0;
409 mwindow->session->current_operation == DRAG_ASSET)
412 canvas->draw_refresh();
414 Indexable *indexable = mwindow->session->drag_assets->size() ?
415 mwindow->session->drag_assets->get(0) :
417 EDL *edl = mwindow->session->drag_clips->size() ?
418 mwindow->session->drag_clips->get(0) :
422 vwindow->change_source(indexable);
425 vwindow->change_source(edl);
433 void VWindowGUI::update_meters()
435 if(mwindow->edl->session->vwindow_meter != meters->visible)
437 meters->set_meters(meters->meter_count,
438 mwindow->edl->session->vwindow_meter);
439 mwindow->theme->get_vwindow_sizes(this);
440 resize_event(get_w(), get_h());
446 VWindowMeters::VWindowMeters(MWindow *mwindow,
451 : MeterPanel(mwindow,
457 mwindow->edl->session->audio_channels,
458 mwindow->edl->session->vwindow_meter,
462 this->mwindow = mwindow;
466 VWindowMeters::~VWindowMeters()
470 int VWindowMeters::change_status_event(int new_status)
472 mwindow->edl->session->vwindow_meter = new_status;
473 gui->update_meters();
483 VWindowEditing::VWindowEditing(MWindow *mwindow, VWindow *vwindow)
486 mwindow->theme->vedit_x,
487 mwindow->theme->vedit_y,
507 this->mwindow = mwindow;
508 this->vwindow = vwindow;
511 VWindowEditing::~VWindowEditing()
515 void VWindowEditing::copy_selection()
520 void VWindowEditing::splice_selection()
522 if(vwindow->get_edl())
524 mwindow->gui->lock_window("VWindowEditing::splice_selection");
525 mwindow->splice(vwindow->get_edl());
526 mwindow->gui->unlock_window();
530 void VWindowEditing::overwrite_selection()
532 if(vwindow->get_edl())
534 mwindow->gui->lock_window("VWindowEditing::overwrite_selection");
535 mwindow->overwrite(vwindow->get_edl());
536 mwindow->gui->unlock_window();
540 void VWindowEditing::toggle_label()
542 if(vwindow->get_edl())
544 EDL *edl = vwindow->get_edl();
545 edl->labels->toggle_label(edl->local_session->get_selectionstart(1),
546 edl->local_session->get_selectionend(1));
547 vwindow->gui->timebar->update(1);
551 void VWindowEditing::prev_label()
553 if(vwindow->get_edl())
555 EDL *edl = vwindow->get_edl();
556 vwindow->gui->unlock_window();
557 vwindow->playback_engine->interrupt_playback(1);
558 vwindow->gui->lock_window("VWindowEditing::prev_label");
560 Label *current = edl->labels->prev_label(
561 edl->local_session->get_selectionstart(1));
566 edl->local_session->set_selectionstart(0);
567 edl->local_session->set_selectionend(0);
568 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
569 vwindow->gui->timebar->update(1);
573 edl->local_session->set_selectionstart(current->position);
574 edl->local_session->set_selectionend(current->position);
575 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
576 vwindow->gui->timebar->update(1);
581 void VWindowEditing::next_label()
583 if(vwindow->get_edl())
585 EDL *edl = vwindow->get_edl();
586 Label *current = edl->labels->next_label(
587 edl->local_session->get_selectionstart(1));
590 vwindow->gui->unlock_window();
591 vwindow->playback_engine->interrupt_playback(1);
592 vwindow->gui->lock_window("VWindowEditing::next_label 1");
594 double position = edl->tracks->total_length();
595 edl->local_session->set_selectionstart(position);
596 edl->local_session->set_selectionend(position);
597 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
598 vwindow->gui->timebar->update(1);
602 vwindow->gui->unlock_window();
603 vwindow->playback_engine->interrupt_playback(1);
604 vwindow->gui->lock_window("VWindowEditing::next_label 2");
606 edl->local_session->set_selectionstart(current->position);
607 edl->local_session->set_selectionend(current->position);
608 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
609 vwindow->gui->timebar->update(1);
614 double VWindowEditing::get_position()
616 EDL *edl = vwindow->get_edl();
617 double position = !edl ? 0 : edl->local_session->get_selectionstart(1) +
618 edl->session->get_frame_offset() / edl->session->frame_rate;
622 void VWindowEditing::set_position(double position)
624 EDL *edl = vwindow->get_edl();
626 if( get_position() != position ) {
627 position -= edl->session->get_frame_offset() / edl->session->frame_rate;
628 if( position < 0 ) position = 0;
629 edl->local_session->set_selectionstart(position);
630 edl->local_session->set_selectionend(position);
631 vwindow->update_position(CHANGE_NONE, 0, 1);
635 void VWindowEditing::set_inpoint()
637 vwindow->set_inpoint();
640 void VWindowEditing::set_outpoint()
642 vwindow->set_outpoint();
645 void VWindowEditing::clear_inpoint()
647 vwindow->clear_inpoint();
650 void VWindowEditing::clear_outpoint()
652 vwindow->clear_outpoint();
655 void VWindowEditing::to_clip()
657 EDL *edl = vwindow->get_edl();
659 mwindow->to_clip(edl, _("viewer window: "));
662 VWindowSource::VWindowSource(MWindow *mwindow, VWindowGUI *vwindow, int x, int y)
663 : BC_PopupTextBox(vwindow,
671 this->mwindow = mwindow;
672 this->vwindow = vwindow;
675 VWindowSource::~VWindowSource()
679 int VWindowSource::handle_event()
685 VWindowTransport::VWindowTransport(MWindow *mwindow,
689 : PlayTransport(mwindow,
697 EDL* VWindowTransport::get_edl()
699 return gui->vwindow->get_edl();
703 void VWindowTransport::goto_start()
705 gui->unlock_window();
706 handle_transport(REWIND, 1);
707 gui->lock_window("VWindowTransport::goto_start");
708 gui->vwindow->goto_start();
711 void VWindowTransport::goto_end()
713 gui->unlock_window();
714 handle_transport(GOTO_END, 1);
715 gui->lock_window("VWindowTransport::goto_end");
716 gui->vwindow->goto_end();
722 VWindowCanvas::VWindowCanvas(MWindow *mwindow, VWindowGUI *gui)
725 mwindow->theme->vcanvas_x,
726 mwindow->theme->vcanvas_y,
727 mwindow->theme->vcanvas_w,
728 mwindow->theme->vcanvas_h,
731 //printf("VWindowCanvas::VWindowCanvas %d %d\n", __LINE__, mwindow->theme->vcanvas_x);
732 this->mwindow = mwindow;
736 void VWindowCanvas::zoom_resize_window(float percentage)
738 EDL *edl = gui->vwindow->get_edl();
739 if(!edl) edl = mwindow->edl;
741 int canvas_w, canvas_h;
744 // Get required canvas size
745 calculate_sizes(edl->get_aspect_ratio(),
746 edl->session->output_w,
747 edl->session->output_h,
752 // Estimate window size from current borders
753 new_w = canvas_w + (gui->get_w() - mwindow->theme->vcanvas_w);
754 new_h = canvas_h + (gui->get_h() - mwindow->theme->vcanvas_h);
756 mwindow->session->vwindow_w = new_w;
757 mwindow->session->vwindow_h = new_h;
759 mwindow->theme->get_vwindow_sizes(gui);
761 // Estimate again from new borders
762 new_w = canvas_w + (mwindow->session->vwindow_w - mwindow->theme->vcanvas_w);
763 new_h = canvas_h + (mwindow->session->vwindow_h - mwindow->theme->vcanvas_h);
766 gui->resize_window(new_w, new_h);
767 gui->resize_event(new_w, new_h);
770 void VWindowCanvas::close_source()
772 gui->unlock_window();
773 gui->vwindow->playback_engine->interrupt_playback(1);
774 gui->lock_window("VWindowCanvas::close_source");
775 gui->vwindow->delete_source(1, 1);
779 void VWindowCanvas::draw_refresh(int flush)
781 EDL *edl = gui->vwindow->get_edl();
783 if(!get_canvas()->get_video_on()) get_canvas()->clear_box(0, 0, get_canvas()->get_w(), get_canvas()->get_h());
784 if(!get_canvas()->get_video_on() && refresh_frame && edl)
786 float in_x1, in_y1, in_x2, in_y2;
787 float out_x1, out_y1, out_x2, out_y2;
797 get_canvas()->draw_vframe(refresh_frame,
800 (int)(out_x2 - out_x1),
801 (int)(out_y2 - out_y1),
804 (int)(in_x2 - in_x1),
805 (int)(in_y2 - in_y1),
809 if(!get_canvas()->get_video_on())
812 get_canvas()->flash(flush);
816 void VWindowCanvas::draw_overlays()
818 if( gui->highlighted )
820 get_canvas()->set_color(WHITE);
821 get_canvas()->set_inverse();
822 get_canvas()->draw_rectangle(0, 0, get_canvas()->get_w(), get_canvas()->get_h());
823 get_canvas()->draw_rectangle(1, 1, get_canvas()->get_w() - 2, get_canvas()->get_h() - 2);
824 get_canvas()->set_opaque();
828 int VWindowCanvas::get_fullscreen()
830 return mwindow->session->vwindow_fullscreen;
833 void VWindowCanvas::set_fullscreen(int value)
835 mwindow->session->vwindow_fullscreen = value;
875 void VWindowGUI::update_points()
877 EDL *edl = vwindow->get_edl();
879 //printf("VWindowGUI::update_points 1\n");
882 //printf("VWindowGUI::update_points 2\n");
883 long pixel = (long)((double)edl->local_session->in_point /
884 edl->tracks->total_playable_length() *
885 (mwindow->theme->vtimebar_w -
887 mwindow->theme->in_point[0]->get_w())) +
888 mwindow->theme->in_point[0]->get_w();
890 //printf("VWindowGUI::update_points 3 %d\n", edl->local_session->in_point);
893 //printf("VWindowGUI::update_points 3.1\n");
894 if(edl->local_session->in_point >= 0)
896 //printf("VWindowGUI::update_points 4\n");
897 if(edl->local_session->in_point != in_point->position ||
898 in_point->pixel != pixel)
900 in_point->pixel = pixel;
901 in_point->reposition();
904 //printf("VWindowGUI::update_points 5\n");
905 in_point->position = edl->local_session->in_point;
907 //printf("VWindowGUI::update_points 6\n");
908 if(edl->equivalent(in_point->position, edl->local_session->get_selectionstart(1)) ||
909 edl->equivalent(in_point->position, edl->local_session->get_selectionend(1)))
913 //printf("VWindowGUI::update_points 7\n");
922 if(edl->local_session->in_point >= 0)
924 //printf("VWindowGUI::update_points 8 %p\n", mwindow->theme->in_point);
925 add_subwindow(in_point =
926 new VWindowInPoint(mwindow,
930 edl->local_session->in_point));
931 //printf("VWindowGUI::update_points 9\n");
933 //printf("VWindowGUI::update_points 10\n");
935 pixel = (long)((double)edl->local_session->out_point /
936 (edl->tracks->total_playable_length() + 0.5) *
937 (mwindow->theme->vtimebar_w -
939 mwindow->theme->in_point[0]->get_w())) +
940 mwindow->theme->in_point[0]->get_w() *
945 if(edl->local_session->out_point >= 0 && pixel >= 0 && pixel <= mwindow->theme->vtimebar_w)
947 if(edl->local_session->out_point != out_point->position ||
948 out_point->pixel != pixel)
950 out_point->pixel = pixel;
951 out_point->reposition();
953 out_point->position = edl->local_session->out_point;
955 if(edl->equivalent(out_point->position, edl->local_session->get_selectionstart(1)) ||
956 edl->equivalent(out_point->position, edl->local_session->get_selectionend(1)))
957 out_point->update(1);
959 out_point->update(0);
968 if(edl->local_session->out_point >= 0 && pixel >= 0 && pixel <= mwindow->theme->vtimebar_w)
970 add_subwindow(out_point =
971 new VWindowOutPoint(mwindow,
975 edl->local_session->out_point));
980 void VWindowGUI::update_labels()
982 EDL *edl = vwindow->get_edl();
985 for(Label *current = edl->labels->first;
989 long pixel = (long)((current->position - edl->local_session->view_start) / edl->local_session->zoom_sample);
991 if(pixel >= 0 && pixel < mwindow->theme->vtimebar_w)
994 if(output >= labels.total)
997 add_subwindow(new_label = new LabelGUI(mwindow, this, pixel, 0, current->position));
998 labels.append(new_label);
1001 // Reposition old label
1002 if(labels.values[output]->pixel != pixel)
1004 labels.values[output]->pixel = pixel;
1005 labels.values[output]->position = current->position;
1006 labels.values[output]->reposition();
1009 if(mwindow->edl->local_session->get_selectionstart(1) <= current->position &&
1010 mwindow->edl->local_session->get_selectionend(1) >= current->position)
1011 labels.values[output]->update(1);
1013 if(labels.values[output]->get_value())
1014 labels.values[output]->update(0);
1019 // Delete excess labels
1020 while(labels.total > output)
1022 labels.remove_object();
1028 VWindowInPoint::VWindowInPoint(MWindow *mwindow,
1033 : InPointGUI(mwindow,
1041 int VWindowInPoint::handle_event()
1043 EDL *edl = gui->vwindow->get_edl();
1047 double position = edl->align_to_frame(this->position, 0);
1049 edl->local_session->set_selectionstart(position);
1050 edl->local_session->set_selectionend(position);
1051 gui->timebar->update(1);
1054 mwindow->vwindow->update_position(CHANGE_NONE, 0, 1, 0);
1061 VWindowOutPoint::VWindowOutPoint(MWindow *mwindow,
1066 : OutPointGUI(mwindow,
1074 int VWindowOutPoint::handle_event()
1076 EDL *edl = gui->vwindow->get_edl();
1080 double position = edl->align_to_frame(this->position, 0);
1082 edl->local_session->set_selectionstart(position);
1083 edl->local_session->set_selectionend(position);
1084 gui->timebar->update(1);
1087 mwindow->vwindow->update_position(CHANGE_NONE, 0, 1, 0);