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;
80 VWindowGUI::~VWindowGUI()
82 vwindow->playback_engine->interrupt_playback(1);
83 sources.remove_all_objects();
84 labels.remove_all_objects();
92 void VWindowGUI::change_source(EDL *edl, const char *title)
94 //printf("VWindowGUI::change_source %d\n", __LINE__);
96 update_sources(title);
97 char string[BCTEXTLEN];
100 sprintf(string, _(PROGRAM_NAME ": %s"), title);
102 sprintf(string, _(PROGRAM_NAME ": Viewer"));
104 lock_window("VWindowGUI::change_source");
111 // Get source list from master EDL
112 void VWindowGUI::update_sources(const char *title)
114 lock_window("VWindowGUI::update_sources");
116 //printf("VWindowGUI::update_sources 1\n");
117 sources.remove_all_objects();
118 //printf("VWindowGUI::update_sources 2\n");
123 i < mwindow->edl->clips.total;
126 char *clip_title = mwindow->edl->clips.values[i]->local_session->clip_title;
129 for(int j = 0; j < sources.total; j++)
131 if(!strcasecmp(sources.values[j]->get_text(), clip_title))
139 sources.append(new BC_ListBoxItem(clip_title));
142 //printf("VWindowGUI::update_sources 3\n");
145 for(Asset *current = mwindow->edl->assets->first;
149 char clip_title[BCTEXTLEN];
150 fs.extract_name(clip_title, current->path);
153 for(int j = 0; j < sources.total; j++)
155 if(!strcasecmp(sources.values[j]->get_text(), clip_title))
163 sources.append(new BC_ListBoxItem(clip_title));
167 //printf("VWindowGUI::update_sources 4\n");
169 // source->update_list(&sources);
170 // source->update(title);
174 void VWindowGUI::create_objects()
178 lock_window("VWindowGUI::create_objects");
179 set_icon(mwindow->theme->get_image("vwindow_icon"));
181 //printf("VWindowGUI::create_objects 1\n");
182 mwindow->theme->get_vwindow_sizes(this);
183 mwindow->theme->draw_vwindow_bg(this);
186 meters = new VWindowMeters(mwindow,
188 mwindow->theme->vmeter_x,
189 mwindow->theme->vmeter_y,
190 mwindow->theme->vmeter_h);
191 meters->create_objects();
193 //printf("VWindowGUI::create_objects 1\n");
194 // Requires meters to build
195 edit_panel = new VWindowEditing(mwindow, vwindow);
196 edit_panel->set_meters(meters);
197 edit_panel->create_objects();
199 //printf("VWindowGUI::create_objects 1\n");
200 transport = new VWindowTransport(mwindow,
202 mwindow->theme->vtransport_x,
203 mwindow->theme->vtransport_y);
204 transport->create_objects();
206 //printf("VWindowGUI::create_objects 1\n");
207 // add_subwindow(fps_title = new BC_Title(mwindow->theme->vedit_x, y, ""));
208 add_subwindow(clock = new MainClock(mwindow,
209 mwindow->theme->vtime_x,
210 mwindow->theme->vtime_y,
211 mwindow->theme->vtime_w));
213 canvas = new VWindowCanvas(mwindow, this);
214 canvas->create_objects(mwindow->edl);
215 canvas->use_vwindow();
218 //printf("VWindowGUI::create_objects 1\n");
219 add_subwindow(timebar = new VTimeBar(mwindow,
221 mwindow->theme->vtimebar_x,
222 mwindow->theme->vtimebar_y,
223 mwindow->theme->vtimebar_w,
224 mwindow->theme->vtimebar_h));
225 timebar->create_objects();
226 //printf("VWindowGUI::create_objects 2\n");
229 //printf("VWindowGUI::create_objects 1\n");
230 // source = new VWindowSource(mwindow,
232 // mwindow->theme->vsource_x,
233 // mwindow->theme->vsource_y);
234 // source->create_objects();
235 update_sources(_("None"));
237 //printf("VWindowGUI::create_objects 2\n");
244 int VWindowGUI::resize_event(int w, int h)
246 mwindow->session->vwindow_x = get_x();
247 mwindow->session->vwindow_y = get_y();
248 mwindow->session->vwindow_w = w;
249 mwindow->session->vwindow_h = h;
251 mwindow->theme->get_vwindow_sizes(this);
252 mwindow->theme->draw_vwindow_bg(this);
255 //printf("VWindowGUI::resize_event %d %d\n", __LINE__, mwindow->theme->vedit_y);
256 edit_panel->reposition_buttons(mwindow->theme->vedit_x,
257 mwindow->theme->vedit_y);
259 timebar->resize_event();
260 transport->reposition_buttons(mwindow->theme->vtransport_x,
261 mwindow->theme->vtransport_y);
262 clock->reposition_window(mwindow->theme->vtime_x,
263 mwindow->theme->vtime_y,
264 mwindow->theme->vtime_w,
266 canvas->reposition_window(0,
267 mwindow->theme->vcanvas_x,
268 mwindow->theme->vcanvas_y,
269 mwindow->theme->vcanvas_w,
270 mwindow->theme->vcanvas_h);
271 //printf("VWindowGUI::resize_event %d %d\n", __LINE__, mwindow->theme->vcanvas_x);
272 // source->reposition_window(mwindow->theme->vsource_x,
273 // mwindow->theme->vsource_y);
274 meters->reposition_window(mwindow->theme->vmeter_x,
275 mwindow->theme->vmeter_y,
277 mwindow->theme->vmeter_h);
279 BC_WindowBase::resize_event(w, h);
287 int VWindowGUI::translation_event()
289 mwindow->session->vwindow_x = get_x();
290 mwindow->session->vwindow_y = get_y();
294 int VWindowGUI::close_event()
297 int i = mwindow->vwindows.size();
298 while( --i >= 0 && mwindow->vwindows.get(i)->gui != this );
304 mwindow->session->show_vwindow = 0;
307 mwindow->gui->lock_window("VWindowGUI::close_event");
308 mwindow->gui->mainmenu->show_vwindow->set_checked(0);
309 mwindow->gui->unlock_window();
311 lock_window("VWindowGUI::close_event");
312 mwindow->save_defaults();
316 int VWindowGUI::keypress_event()
319 switch(get_keypress())
327 mwindow->undo_entry(this);
330 mwindow->redo_entry(this);
334 if(mwindow->session->vwindow_fullscreen)
335 canvas->stop_fullscreen();
337 canvas->start_fullscreen();
338 lock_window("VWindowGUI::keypress_event 1");
342 if(mwindow->session->vwindow_fullscreen)
343 canvas->stop_fullscreen();
344 lock_window("VWindowGUI::keypress_event 2");
347 if(!result) result = transport->keypress_event();
352 int VWindowGUI::button_press_event()
354 if(canvas->get_canvas())
355 return canvas->button_press_event_base(canvas->get_canvas());
359 int VWindowGUI::cursor_leave_event()
361 if(canvas->get_canvas())
362 return canvas->cursor_leave_event_base(canvas->get_canvas());
366 int VWindowGUI::cursor_enter_event()
368 if(canvas->get_canvas())
369 return canvas->cursor_enter_event_base(canvas->get_canvas());
373 int VWindowGUI::button_release_event()
375 if(canvas->get_canvas())
376 return canvas->button_release_event();
380 int VWindowGUI::cursor_motion_event()
382 if(canvas->get_canvas())
384 canvas->get_canvas()->unhide_cursor();
385 return canvas->cursor_motion_event();
391 void VWindowGUI::drag_motion()
394 if(get_hidden()) return;
395 if(mwindow->session->current_operation != DRAG_ASSET) return;
397 int old_status = mwindow->session->vcanvas_highlighted;
399 int cursor_x = get_relative_cursor_x();
400 int cursor_y = get_relative_cursor_y();
402 mwindow->session->vcanvas_highlighted = (get_cursor_over_window() &&
403 cursor_x >= canvas->x &&
404 cursor_x < canvas->x + canvas->w &&
405 cursor_y >= canvas->y &&
406 cursor_y < canvas->y + canvas->h);
409 //printf("VWindowGUI::drag_motion 1 %d %d %d %d %d\n", __LINE__,
410 // mwindow->session->vcanvas_highlighted, get_cursor_over_window(), cursor_x, cursor_y);
412 if(old_status != mwindow->session->vcanvas_highlighted)
413 canvas->draw_refresh();
416 int VWindowGUI::drag_stop()
418 if(get_hidden()) return 0;
420 if(mwindow->session->vcanvas_highlighted &&
421 mwindow->session->current_operation == DRAG_ASSET)
423 mwindow->session->vcanvas_highlighted = 0;
424 canvas->draw_refresh();
426 Indexable *indexable = mwindow->session->drag_assets->size() ?
427 mwindow->session->drag_assets->get(0) :
429 EDL *edl = mwindow->session->drag_clips->size() ?
430 mwindow->session->drag_clips->get(0) :
434 vwindow->change_source(indexable);
437 vwindow->change_source(edl);
445 void VWindowGUI::update_meters()
447 if(mwindow->edl->session->vwindow_meter != meters->visible)
449 meters->set_meters(meters->meter_count,
450 mwindow->edl->session->vwindow_meter);
451 mwindow->theme->get_vwindow_sizes(this);
452 resize_event(get_w(), get_h());
458 VWindowMeters::VWindowMeters(MWindow *mwindow,
463 : MeterPanel(mwindow,
469 mwindow->edl->session->audio_channels,
470 mwindow->edl->session->vwindow_meter,
474 this->mwindow = mwindow;
478 VWindowMeters::~VWindowMeters()
482 int VWindowMeters::change_status_event(int new_status)
484 mwindow->edl->session->vwindow_meter = new_status;
485 gui->update_meters();
495 VWindowEditing::VWindowEditing(MWindow *mwindow, VWindow *vwindow)
498 mwindow->theme->vedit_x,
499 mwindow->theme->vedit_y,
518 this->mwindow = mwindow;
519 this->vwindow = vwindow;
522 VWindowEditing::~VWindowEditing()
526 void VWindowEditing::copy_selection()
531 void VWindowEditing::splice_selection()
533 if(vwindow->get_edl())
535 mwindow->gui->lock_window("VWindowEditing::splice_selection");
536 mwindow->splice(vwindow->get_edl());
537 mwindow->gui->unlock_window();
541 void VWindowEditing::overwrite_selection()
543 if(vwindow->get_edl())
545 mwindow->gui->lock_window("VWindowEditing::overwrite_selection");
546 mwindow->overwrite(vwindow->get_edl());
547 mwindow->gui->unlock_window();
551 void VWindowEditing::toggle_label()
553 if(vwindow->get_edl())
555 EDL *edl = vwindow->get_edl();
556 edl->labels->toggle_label(edl->local_session->get_selectionstart(1),
557 edl->local_session->get_selectionend(1));
558 vwindow->gui->timebar->update(1);
562 void VWindowEditing::prev_label()
564 if(vwindow->get_edl())
566 EDL *edl = vwindow->get_edl();
567 vwindow->gui->unlock_window();
568 vwindow->playback_engine->interrupt_playback(1);
569 vwindow->gui->lock_window("VWindowEditing::prev_label");
571 Label *current = edl->labels->prev_label(
572 edl->local_session->get_selectionstart(1));
577 edl->local_session->set_selectionstart(0);
578 edl->local_session->set_selectionend(0);
579 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
580 vwindow->gui->timebar->update(1);
584 edl->local_session->set_selectionstart(current->position);
585 edl->local_session->set_selectionend(current->position);
586 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
587 vwindow->gui->timebar->update(1);
592 void VWindowEditing::next_label()
594 if(vwindow->get_edl())
596 EDL *edl = vwindow->get_edl();
597 Label *current = edl->labels->next_label(
598 edl->local_session->get_selectionstart(1));
601 vwindow->gui->unlock_window();
602 vwindow->playback_engine->interrupt_playback(1);
603 vwindow->gui->lock_window("VWindowEditing::next_label 1");
605 double position = edl->tracks->total_length();
606 edl->local_session->set_selectionstart(position);
607 edl->local_session->set_selectionend(position);
608 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
609 vwindow->gui->timebar->update(1);
613 vwindow->gui->unlock_window();
614 vwindow->playback_engine->interrupt_playback(1);
615 vwindow->gui->lock_window("VWindowEditing::next_label 2");
617 edl->local_session->set_selectionstart(current->position);
618 edl->local_session->set_selectionend(current->position);
619 vwindow->update_position(CHANGE_NONE, 0, 1, 0);
620 vwindow->gui->timebar->update(1);
625 void VWindowEditing::set_inpoint()
627 vwindow->set_inpoint();
630 void VWindowEditing::set_outpoint()
632 vwindow->set_outpoint();
635 void VWindowEditing::clear_inpoint()
637 vwindow->clear_inpoint();
640 void VWindowEditing::clear_outpoint()
642 vwindow->clear_outpoint();
645 void VWindowEditing::to_clip()
647 if(vwindow->get_edl())
650 EDL *edl = vwindow->get_edl();
651 double start = edl->local_session->get_selectionstart();
652 double end = edl->local_session->get_selectionend();
654 if(EQUIV(start, end))
656 end = edl->tracks->total_length();
674 EDL *new_edl = new EDL(mwindow->edl);
675 new_edl->create_objects();
676 new_edl->load_xml(&file, LOAD_ALL);
677 sprintf(new_edl->local_session->clip_title, _("Clip %d"), mwindow->session->clip_number++);
678 new_edl->local_session->set_selectionstart(0);
679 new_edl->local_session->set_selectionend(0);
682 //printf("VWindowEditing::to_clip 1 %s\n", edl->local_session->clip_title);
684 vwindow->clip_edit->create_clip(new_edl);
694 VWindowSource::VWindowSource(MWindow *mwindow, VWindowGUI *vwindow, int x, int y)
695 : BC_PopupTextBox(vwindow,
703 this->mwindow = mwindow;
704 this->vwindow = vwindow;
707 VWindowSource::~VWindowSource()
711 int VWindowSource::handle_event()
722 VWindowTransport::VWindowTransport(MWindow *mwindow,
726 : PlayTransport(mwindow,
734 EDL* VWindowTransport::get_edl()
736 return gui->vwindow->get_edl();
740 void VWindowTransport::goto_start()
742 gui->unlock_window();
743 handle_transport(REWIND, 1);
744 gui->lock_window("VWindowTransport::goto_start");
745 gui->vwindow->goto_start();
748 void VWindowTransport::goto_end()
750 gui->unlock_window();
751 handle_transport(GOTO_END, 1);
752 gui->lock_window("VWindowTransport::goto_end");
753 gui->vwindow->goto_end();
759 VWindowCanvas::VWindowCanvas(MWindow *mwindow, VWindowGUI *gui)
762 mwindow->theme->vcanvas_x,
763 mwindow->theme->vcanvas_y,
764 mwindow->theme->vcanvas_w,
765 mwindow->theme->vcanvas_h,
768 //printf("VWindowCanvas::VWindowCanvas %d %d\n", __LINE__, mwindow->theme->vcanvas_x);
769 this->mwindow = mwindow;
773 void VWindowCanvas::zoom_resize_window(float percentage)
775 EDL *edl = gui->vwindow->get_edl();
776 if(!edl) edl = mwindow->edl;
778 int canvas_w, canvas_h;
781 // Get required canvas size
782 calculate_sizes(edl->get_aspect_ratio(),
783 edl->session->output_w,
784 edl->session->output_h,
789 // Estimate window size from current borders
790 new_w = canvas_w + (gui->get_w() - mwindow->theme->vcanvas_w);
791 new_h = canvas_h + (gui->get_h() - mwindow->theme->vcanvas_h);
793 mwindow->session->vwindow_w = new_w;
794 mwindow->session->vwindow_h = new_h;
796 mwindow->theme->get_vwindow_sizes(gui);
798 // Estimate again from new borders
799 new_w = canvas_w + (mwindow->session->vwindow_w - mwindow->theme->vcanvas_w);
800 new_h = canvas_h + (mwindow->session->vwindow_h - mwindow->theme->vcanvas_h);
803 gui->resize_window(new_w, new_h);
804 gui->resize_event(new_w, new_h);
807 void VWindowCanvas::close_source()
809 gui->unlock_window();
810 gui->vwindow->playback_engine->interrupt_playback(1);
811 gui->lock_window("VWindowCanvas::close_source");
812 gui->vwindow->delete_source(1, 1);
816 void VWindowCanvas::draw_refresh(int flush)
818 EDL *edl = gui->vwindow->get_edl();
820 if(!get_canvas()->get_video_on()) get_canvas()->clear_box(0, 0, get_canvas()->get_w(), get_canvas()->get_h());
821 if(!get_canvas()->get_video_on() && refresh_frame && edl)
823 float in_x1, in_y1, in_x2, in_y2;
824 float out_x1, out_y1, out_x2, out_y2;
834 get_canvas()->draw_vframe(refresh_frame,
837 (int)(out_x2 - out_x1),
838 (int)(out_y2 - out_y1),
841 (int)(in_x2 - in_x1),
842 (int)(in_y2 - in_y1),
846 if(!get_canvas()->get_video_on())
849 get_canvas()->flash(flush);
853 void VWindowCanvas::draw_overlays()
855 if(mwindow->session->vcanvas_highlighted)
857 get_canvas()->set_color(WHITE);
858 get_canvas()->set_inverse();
859 get_canvas()->draw_rectangle(0, 0, get_canvas()->get_w(), get_canvas()->get_h());
860 get_canvas()->draw_rectangle(1, 1, get_canvas()->get_w() - 2, get_canvas()->get_h() - 2);
861 get_canvas()->set_opaque();
865 int VWindowCanvas::get_fullscreen()
867 return mwindow->session->vwindow_fullscreen;
870 void VWindowCanvas::set_fullscreen(int value)
872 mwindow->session->vwindow_fullscreen = value;
912 void VWindowGUI::update_points()
914 EDL *edl = vwindow->get_edl();
916 //printf("VWindowGUI::update_points 1\n");
919 //printf("VWindowGUI::update_points 2\n");
920 long pixel = (long)((double)edl->local_session->in_point /
921 edl->tracks->total_playable_length() *
922 (mwindow->theme->vtimebar_w -
924 mwindow->theme->in_point[0]->get_w())) +
925 mwindow->theme->in_point[0]->get_w();
927 //printf("VWindowGUI::update_points 3 %d\n", edl->local_session->in_point);
930 //printf("VWindowGUI::update_points 3.1\n");
931 if(edl->local_session->in_point >= 0)
933 //printf("VWindowGUI::update_points 4\n");
934 if(edl->local_session->in_point != in_point->position ||
935 in_point->pixel != pixel)
937 in_point->pixel = pixel;
938 in_point->reposition();
941 //printf("VWindowGUI::update_points 5\n");
942 in_point->position = edl->local_session->in_point;
944 //printf("VWindowGUI::update_points 6\n");
945 if(edl->equivalent(in_point->position, edl->local_session->get_selectionstart(1)) ||
946 edl->equivalent(in_point->position, edl->local_session->get_selectionend(1)))
950 //printf("VWindowGUI::update_points 7\n");
959 if(edl->local_session->in_point >= 0)
961 //printf("VWindowGUI::update_points 8 %p\n", mwindow->theme->in_point);
962 add_subwindow(in_point =
963 new VWindowInPoint(mwindow,
967 edl->local_session->in_point));
968 //printf("VWindowGUI::update_points 9\n");
970 //printf("VWindowGUI::update_points 10\n");
972 pixel = (long)((double)edl->local_session->out_point /
973 (edl->tracks->total_playable_length() + 0.5) *
974 (mwindow->theme->vtimebar_w -
976 mwindow->theme->in_point[0]->get_w())) +
977 mwindow->theme->in_point[0]->get_w() *
982 if(edl->local_session->out_point >= 0 && pixel >= 0 && pixel <= mwindow->theme->vtimebar_w)
984 if(edl->local_session->out_point != out_point->position ||
985 out_point->pixel != pixel)
987 out_point->pixel = pixel;
988 out_point->reposition();
990 out_point->position = edl->local_session->out_point;
992 if(edl->equivalent(out_point->position, edl->local_session->get_selectionstart(1)) ||
993 edl->equivalent(out_point->position, edl->local_session->get_selectionend(1)))
994 out_point->update(1);
996 out_point->update(0);
1005 if(edl->local_session->out_point >= 0 && pixel >= 0 && pixel <= mwindow->theme->vtimebar_w)
1007 add_subwindow(out_point =
1008 new VWindowOutPoint(mwindow,
1012 edl->local_session->out_point));
1017 void VWindowGUI::update_labels()
1019 EDL *edl = vwindow->get_edl();
1022 for(Label *current = edl->labels->first;
1026 long pixel = (long)((current->position - edl->local_session->view_start) / edl->local_session->zoom_sample);
1028 if(pixel >= 0 && pixel < mwindow->theme->vtimebar_w)
1031 if(output >= labels.total)
1033 LabelGUI *new_label;
1034 add_subwindow(new_label = new LabelGUI(mwindow, this, pixel, 0, current->position));
1035 labels.append(new_label);
1038 // Reposition old label
1039 if(labels.values[output]->pixel != pixel)
1041 labels.values[output]->pixel = pixel;
1042 labels.values[output]->position = current->position;
1043 labels.values[output]->reposition();
1046 if(mwindow->edl->local_session->get_selectionstart(1) <= current->position &&
1047 mwindow->edl->local_session->get_selectionend(1) >= current->position)
1048 labels.values[output]->update(1);
1050 if(labels.values[output]->get_value())
1051 labels.values[output]->update(0);
1056 // Delete excess labels
1057 while(labels.total > output)
1059 labels.remove_object();
1065 VWindowInPoint::VWindowInPoint(MWindow *mwindow,
1070 : InPointGUI(mwindow,
1078 int VWindowInPoint::handle_event()
1080 EDL *edl = gui->vwindow->get_edl();
1084 double position = edl->align_to_frame(this->position, 0);
1086 edl->local_session->set_selectionstart(position);
1087 edl->local_session->set_selectionend(position);
1088 gui->timebar->update(1);
1091 mwindow->vwindow->update_position(CHANGE_NONE, 0, 1, 0);
1098 VWindowOutPoint::VWindowOutPoint(MWindow *mwindow,
1103 : OutPointGUI(mwindow,
1111 int VWindowOutPoint::handle_event()
1113 EDL *edl = gui->vwindow->get_edl();
1117 double position = edl->align_to_frame(this->position, 0);
1119 edl->local_session->set_selectionstart(position);
1120 edl->local_session->set_selectionend(position);
1121 gui->timebar->update(1);
1124 mwindow->vwindow->update_position(CHANGE_NONE, 0, 1, 0);