5 #include "edlsession.h"
8 #include "mainsession.h"
15 Canvas::Canvas(MWindow *mwindow,
16 BC_WindowBase *subwindow,
32 this->mwindow = mwindow;
33 this->subwindow = subwindow;
38 this->output_w = output_w;
39 this->output_h = output_h;
40 this->use_scrollbars = use_scrollbars;
41 this->use_cwindow = use_cwindow;
42 this->use_rwindow = use_rwindow;
43 this->use_vwindow = use_vwindow;
44 this->root_w = subwindow->get_root_w(0, 0);
45 this->root_h = subwindow->get_root_h(0);
46 canvas_lock = new Mutex("Canvas::canvas_lock", 1);
51 if(refresh_frame) delete refresh_frame;
53 if(yscroll) delete yscroll;
54 if(xscroll) delete xscroll;
55 delete canvas_subwindow;
56 delete canvas_fullscreen;
69 canvas_fullscreen = 0;
74 void Canvas::lock_canvas(char *location)
76 canvas_lock->lock(location);
79 void Canvas::unlock_canvas()
81 canvas_lock->unlock();
84 int Canvas::is_locked()
86 return canvas_lock->is_locked();
90 BC_WindowBase* Canvas::get_canvas()
92 if(get_fullscreen() && canvas_fullscreen)
93 return canvas_fullscreen;
95 return canvas_subwindow;
99 // Get dimensions given a zoom
100 void Canvas::calculate_sizes(float aspect_ratio,
107 // Horizontal stretch
108 if((float)output_w / output_h <= aspect_ratio)
110 w = (int)((float)output_h * aspect_ratio * zoom);
111 h = (int)((float)output_h * zoom);
116 h = (int)((float)output_w / aspect_ratio * zoom);
117 w = (int)((float)output_w * zoom);
121 float Canvas::get_x_offset(EDL *edl,
131 // If the projection is smaller than the canvas, this forces it in the center.
132 // if(conformed_w < w_visible)
133 // return -(float)(w_visible - conformed_w) / 2;
135 return (float)get_xscroll();
138 return ((float)-get_canvas()->get_w() / zoom_x +
139 edl->session->output_w) / 2;
144 int canvas_w = get_canvas()->get_w();
145 int canvas_h = get_canvas()->get_h();
149 if((float)out_w / out_h > conformed_w / conformed_h)
151 out_w = (int)(out_h * conformed_w / conformed_h + 0.5);
155 return -(canvas_w - out_w) / 2 / zoom_x;
161 float Canvas::get_y_offset(EDL *edl,
171 // If the projection is smaller than the canvas, this forces it in the center.
172 // if(conformed_h < h_visible)
173 // return -(float)(h_visible - conformed_h) / 2;
175 return (float)get_yscroll();
178 return ((float)-get_canvas()->get_h() / zoom_y +
179 edl->session->output_h) / 2;
184 int canvas_w = get_canvas()->get_w();
185 int canvas_h = get_canvas()->get_h();
189 if((float)out_w / out_h <= conformed_w / conformed_h)
191 out_h = (int)((float)out_w / (conformed_w / conformed_h) + 0.5);
194 //printf("Canvas::get_y_offset 1 %d %d %f\n", out_h, canvas_h, -((float)canvas_h - out_h) / 2);
196 return -((float)canvas_h - out_h) / 2 / zoom_y;
202 // This may not be used anymore
203 void Canvas::check_boundaries(EDL *edl, int &x, int &y, float &zoom)
205 if(x + w_visible > w_needed) x = w_needed - w_visible;
206 if(y + h_visible > h_needed) y = h_needed - h_visible;
212 void Canvas::update_scrollbars()
216 if(xscroll) xscroll->update_length(w_needed, get_xscroll(), w_visible);
217 if(yscroll) yscroll->update_length(h_needed, get_yscroll(), h_visible);
221 void Canvas::get_zooms(EDL *edl,
228 edl->calculate_conformed_dimensions(single_channel,
234 zoom_x = get_zoom() *
236 edl->session->output_w;
237 zoom_y = get_zoom() *
239 edl->session->output_h;
244 int canvas_w = get_canvas()->get_w();
245 int canvas_h = get_canvas()->get_h();
250 if((float)out_w / out_h > conformed_w / conformed_h)
252 out_w = (int)((float)out_h * conformed_w / conformed_h + 0.5);
256 out_h = (int)((float)out_w / (conformed_w / conformed_h) + 0.5);
259 zoom_x = (float)out_w / edl->session->output_w;
260 zoom_y = (float)out_h / edl->session->output_h;
261 //printf("get zooms 2 %d %d %f %f\n", canvas_w, canvas_h, conformed_w, conformed_h);
265 // Convert a coordinate on the canvas to a coordinate on the output
266 void Canvas::canvas_to_output(EDL *edl, int single_channel, float &x, float &y)
268 float zoom_x, zoom_y, conformed_w, conformed_h;
269 get_zooms(edl, single_channel, zoom_x, zoom_y, conformed_w, conformed_h);
271 //printf("Canvas::canvas_to_output y=%f zoom_y=%f y_offset=%f\n",
272 // y, zoom_y, get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h));
274 x = (float)x / zoom_x + get_x_offset(edl, single_channel, zoom_x, conformed_w, conformed_h);
275 y = (float)y / zoom_y + get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h);
278 void Canvas::output_to_canvas(EDL *edl, int single_channel, float &x, float &y)
280 float zoom_x, zoom_y, conformed_w, conformed_h;
281 get_zooms(edl, single_channel, zoom_x, zoom_y, conformed_w, conformed_h);
283 //printf("Canvas::output_to_canvas x=%f zoom_x=%f x_offset=%f\n", x, zoom_x, get_x_offset(edl, single_channel, zoom_x, conformed_w));
285 x = (float)zoom_x * (x - get_x_offset(edl, single_channel, zoom_x, conformed_w, conformed_h));
286 y = (float)zoom_y * (y - get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h));
291 void Canvas::get_transfers(EDL *edl,
303 // printf("Canvas::get_transfers %d %d\n", canvas_w,
305 // automatic canvas size detection
306 if(canvas_w < 0) canvas_w = get_canvas()->get_w();
307 if(canvas_h < 0) canvas_h = get_canvas()->get_h();
309 // Canvas is zoomed to a portion of the output frame
312 float in_x1, in_y1, in_x2, in_y2;
313 float out_x1, out_y1, out_x2, out_y2;
314 float zoom_x, zoom_y, conformed_w, conformed_h;
316 get_zooms(edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
326 canvas_to_output(edl, 0, in_x1, in_y1);
327 canvas_to_output(edl, 0, in_x2, in_y2);
329 //printf("Canvas::get_transfers 1 %.0f %.0f %.0f %.0f -> %.0f %.0f %.0f %.0f\n",
330 //in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
334 out_x1 += -in_x1 * zoom_x;
340 out_y1 += -in_y1 * zoom_y;
344 int output_w = get_output_w(edl);
345 int output_h = get_output_h(edl);
349 out_x2 -= (in_x2 - output_w) * zoom_x;
355 out_y2 -= (in_y2 - output_h) * zoom_y;
358 // printf("Canvas::get_transfers 2 %.0f %.0f %.0f %.0f -> %.0f %.0f %.0f %.0f\n",
359 // in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
371 // if(!scrollbars_exist())
373 // out_x = canvas_w / 2 - out_w / 2;
374 // out_y = canvas_h / 2 - out_h / 2;
379 // The output frame is normalized to the canvas
381 // Default canvas coords fill the entire canvas
384 canvas_x2 = canvas_w;
385 canvas_y2 = canvas_h;
389 // Use EDL aspect ratio to shrink one of the canvas dimensions
390 float out_w = canvas_x2 - canvas_x1;
391 float out_h = canvas_y2 - canvas_y1;
392 if(out_w / out_h > edl->get_aspect_ratio())
394 out_w = (int)(out_h * edl->get_aspect_ratio() + 0.5);
395 canvas_x1 = canvas_w / 2 - out_w / 2;
399 out_h = (int)(out_w / edl->get_aspect_ratio() + 0.5);
400 canvas_y1 = canvas_h / 2 - out_h / 2;
402 canvas_x2 = canvas_x1 + out_w;
403 canvas_y2 = canvas_y1 + out_h;
405 // Get output frame coords from EDL
408 output_x2 = get_output_w(edl);
409 output_y2 = get_output_h(edl);
412 // No EDL to get aspect ratio or output frame coords from
416 output_x2 = this->output_w;
417 output_y2 = this->output_h;
421 // Clamp to minimum value
422 output_x1 = MAX(0, output_x1);
423 output_y1 = MAX(0, output_y1);
424 output_x2 = MAX(output_x1, output_x2);
425 output_y2 = MAX(output_y1, output_y2);
426 canvas_x1 = MAX(0, canvas_x1);
427 canvas_y1 = MAX(0, canvas_y1);
428 canvas_x2 = MAX(canvas_x1, canvas_x2);
429 canvas_y2 = MAX(canvas_y1, canvas_y2);
430 // printf("Canvas::get_transfers 2 %f,%f %f,%f -> %f,%f %f,%f\n",
441 int Canvas::scrollbars_exist()
443 return(use_scrollbars && (xscroll || yscroll));
446 int Canvas::get_output_w(EDL *edl)
449 return edl->session->output_w;
451 return edl->session->output_w;
454 int Canvas::get_output_h(EDL *edl)
459 return edl->session->output_h;
461 return edl->session->output_h;
467 void Canvas::get_scrollbars(EDL *edl,
473 int need_xscroll = 0;
474 int need_yscroll = 0;
476 float zoom_x, zoom_y, conformed_w, conformed_h;
480 w_needed = edl->session->output_w;
481 h_needed = edl->session->output_h;
482 w_visible = w_needed;
483 h_visible = h_needed;
485 //printf("Canvas::get_scrollbars 1 %d %d\n", get_xscroll(), get_yscroll());
489 w_needed = edl->session->output_w;
490 h_needed = edl->session->output_h;
491 get_zooms(edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
492 //printf("Canvas::get_scrollbars 2 %d %d\n", get_xscroll(), get_yscroll());
496 w_visible = (int)(canvas_w / zoom_x);
497 h_visible = (int)(canvas_h / zoom_y);
500 // if(w_needed > w_visible)
506 canvas_h -= BC_ScrollBar::get_span(SCROLL_HORIZ);
513 // if(h_needed > h_visible)
519 canvas_w -= BC_ScrollBar::get_span(SCROLL_VERT);
526 //printf("Canvas::get_scrollbars %d %d %d %d %d %d\n", canvas_w, canvas_h, w_needed, h_needed, w_visible, h_visible);
527 //printf("Canvas::get_scrollbars 3 %d %d\n", get_xscroll(), get_yscroll());
529 w_visible = (int)(canvas_w / zoom_x);
530 h_visible = (int)(canvas_h / zoom_y);
536 subwindow->add_subwindow(xscroll = new CanvasXScroll(edl,
545 xscroll->reposition_window(canvas_x, canvas_y + canvas_h, canvas_w);
547 if(xscroll->get_length() != w_needed ||
548 xscroll->get_handlelength() != w_visible)
549 xscroll->update_length(w_needed, get_xscroll(), w_visible);
553 if(xscroll) delete xscroll;
556 //printf("Canvas::get_scrollbars 4 %d %d\n", get_xscroll(), get_yscroll());
561 subwindow->add_subwindow(yscroll = new CanvasYScroll(edl,
570 yscroll->reposition_window(canvas_x + canvas_w, canvas_y, canvas_h);
572 if(yscroll->get_length() != edl->session->output_h ||
573 yscroll->get_handlelength() != h_visible)
574 yscroll->update_length(h_needed, get_yscroll(), h_visible);
578 if(yscroll) delete yscroll;
581 //printf("Canvas::get_scrollbars 5 %d %d\n", get_xscroll(), get_yscroll());
584 void Canvas::reposition_window(EDL *edl, int x, int y, int w, int h)
594 //printf("Canvas::reposition_window 1\n");
595 get_scrollbars(edl, view_x, view_y, view_w, view_h);
596 //printf("Canvas::reposition_window %d %d %d %d\n", view_x, view_y, view_w, view_h);
599 canvas_subwindow->reposition_window(view_x, view_y, view_w, view_h);
601 // Need to clear out the garbage in the back
602 if(canvas_subwindow->get_video_on())
604 canvas_subwindow->set_color(BLACK);
605 canvas_subwindow->draw_box(0,
607 get_canvas()->get_w(),
608 get_canvas()->get_h());
609 canvas_subwindow->flash();
615 //printf("Canvas::reposition_window 2\n");
618 void Canvas::set_cursor(int cursor)
620 get_canvas()->set_cursor(cursor);
623 int Canvas::get_cursor_x()
625 return get_canvas()->get_cursor_x();
628 int Canvas::get_cursor_y()
630 return get_canvas()->get_cursor_y();
633 int Canvas::get_buttonpress()
635 return get_canvas()->get_buttonpress();
639 int Canvas::create_objects(EDL *edl)
645 get_scrollbars(edl, view_x, view_y, view_w, view_h);
649 subwindow->add_subwindow(canvas_menu = new CanvasPopup(this));
650 canvas_menu->create_objects();
652 subwindow->add_subwindow(fullscreen_menu = new CanvasFullScreenPopup(this));
653 fullscreen_menu->create_objects();
658 int Canvas::button_press_event()
662 if(get_canvas()->get_buttonpress() == 3)
665 fullscreen_menu->activate_menu();
667 canvas_menu->activate_menu();
674 void Canvas::start_single()
680 void Canvas::stop_single()
686 void Canvas::start_video()
690 get_canvas()->start_video();
695 void Canvas::stop_video()
699 get_canvas()->stop_video();
705 void Canvas::start_fullscreen()
711 void Canvas::stop_fullscreen()
717 void Canvas::create_canvas()
721 lock_canvas("Canvas::create_canvas");
725 if(!get_fullscreen())
728 if(canvas_fullscreen)
730 video_on = canvas_fullscreen->get_video_on();
731 canvas_fullscreen->stop_video();
735 if(canvas_fullscreen)
737 canvas_fullscreen->hide_window();
738 // delete canvas_fullscreen;
739 // canvas_fullscreen = 0;
743 if(!canvas_subwindow)
745 subwindow->add_subwindow(canvas_subwindow = new CanvasOutput(this,
757 video_on = canvas_subwindow->get_video_on();
758 canvas_subwindow->stop_video();
760 // delete canvas_subwindow;
761 // canvas_subwindow = 0;
764 if(!canvas_fullscreen)
766 canvas_fullscreen = new CanvasFullScreen(this,
772 canvas_fullscreen->show_window();
777 if(!video_on) draw_refresh();
779 if(video_on) get_canvas()->start_video();
786 int Canvas::cursor_leave_event_base(BC_WindowBase *caller)
789 if(cursor_inside) result = cursor_leave_event();
794 int Canvas::cursor_enter_event_base(BC_WindowBase *caller)
797 if(caller->is_event_win() && caller->cursor_inside())
800 result = cursor_enter_event();
805 int Canvas::button_press_event_base(BC_WindowBase *caller)
807 if(caller->is_event_win() && caller->cursor_inside())
809 return button_press_event();
814 int Canvas::keypress_event(BC_WindowBase *caller)
816 int caller_is_canvas = (caller == get_canvas());
817 if(caller->get_keypress() == 'f')
819 caller->unlock_window();
824 if(!caller_is_canvas) caller->lock_window("Canvas::keypress_event 1");
828 if(caller->get_keypress() == ESC)
830 caller->unlock_window();
833 if(!caller_is_canvas) caller->lock_window("Canvas::keypress_event 2");
855 CanvasOutput::CanvasOutput(Canvas *canvas,
860 : BC_SubWindow(x, y, w, h, BLACK)
862 this->canvas = canvas;
865 CanvasOutput::~CanvasOutput()
869 int CanvasOutput::cursor_leave_event()
871 return canvas->cursor_leave_event_base(this);
874 int CanvasOutput::cursor_enter_event()
876 return canvas->cursor_enter_event_base(this);
879 int CanvasOutput::button_press_event()
881 return canvas->button_press_event_base(this);
884 int CanvasOutput::button_release_event()
886 return canvas->button_release_event();
889 int CanvasOutput::cursor_motion_event()
891 return canvas->cursor_motion_event();
894 int CanvasOutput::keypress_event()
896 return canvas->keypress_event(this);
911 CanvasFullScreen::CanvasFullScreen(Canvas *canvas,
914 : BC_FullScreen(canvas->subwindow,
922 this->canvas = canvas;
925 CanvasFullScreen::~CanvasFullScreen()
941 CanvasXScroll::CanvasXScroll(EDL *edl,
957 this->canvas = canvas;
960 CanvasXScroll::~CanvasXScroll()
964 int CanvasXScroll::handle_event()
966 //printf("CanvasXScroll::handle_event %d %d %d\n", get_length(), get_value(), get_handlelength());
967 canvas->update_zoom(get_value(), canvas->get_yscroll(), canvas->get_zoom());
968 canvas->draw_refresh();
977 CanvasYScroll::CanvasYScroll(EDL *edl,
993 this->canvas = canvas;
996 CanvasYScroll::~CanvasYScroll()
1000 int CanvasYScroll::handle_event()
1002 //printf("CanvasYScroll::handle_event %d %d\n", get_value(), get_length());
1003 canvas->update_zoom(canvas->get_xscroll(), get_value(), canvas->get_zoom());
1004 canvas->draw_refresh();
1013 CanvasFullScreenPopup::CanvasFullScreenPopup(Canvas *canvas)
1020 this->canvas = canvas;
1024 void CanvasFullScreenPopup::create_objects()
1026 if(canvas->use_cwindow) add_item(new CanvasPopupAuto(canvas));
1027 add_item(new CanvasSubWindowItem(canvas));
1031 CanvasSubWindowItem::CanvasSubWindowItem(Canvas *canvas)
1032 : BC_MenuItem(_("Windowed"), "f", 'f')
1034 this->canvas = canvas;
1037 int CanvasSubWindowItem::handle_event()
1039 // It isn't a problem to delete the canvas from in here because the event
1040 // dispatcher is the canvas subwindow.
1041 canvas->subwindow->unlock_window();
1042 canvas->stop_fullscreen();
1043 canvas->subwindow->lock_window("CanvasSubWindowItem::handle_event");
1054 CanvasPopup::CanvasPopup(Canvas *canvas)
1061 this->canvas = canvas;
1064 CanvasPopup::~CanvasPopup()
1068 void CanvasPopup::create_objects()
1070 add_item(new CanvasPopupSize(canvas, _("Zoom 25%"), 0.25));
1071 add_item(new CanvasPopupSize(canvas, _("Zoom 33%"), 0.33));
1072 add_item(new CanvasPopupSize(canvas, _("Zoom 50%"), 0.5));
1073 add_item(new CanvasPopupSize(canvas, _("Zoom 75%"), 0.75));
1074 add_item(new CanvasPopupSize(canvas, _("Zoom 100%"), 1.0));
1075 add_item(new CanvasPopupSize(canvas, _("Zoom 150%"), 1.5));
1076 add_item(new CanvasPopupSize(canvas, _("Zoom 200%"), 2.0));
1077 add_item(new CanvasPopupSize(canvas, _("Zoom 300%"), 3.0));
1078 add_item(new CanvasPopupSize(canvas, _("Zoom 400%"), 4.0));
1079 if(canvas->use_cwindow)
1081 add_item(new CanvasPopupAuto(canvas));
1082 add_item(new CanvasPopupResetCamera(canvas));
1083 add_item(new CanvasPopupResetProjector(canvas));
1084 add_item(toggle_controls = new CanvasToggleControls(canvas));
1086 if(canvas->use_rwindow)
1088 add_item(new CanvasPopupResetTranslation(canvas));
1090 if(canvas->use_vwindow)
1092 add_item(new CanvasPopupRemoveSource(canvas));
1094 add_item(new CanvasFullScreenItem(canvas));
1099 CanvasPopupAuto::CanvasPopupAuto(Canvas *canvas)
1100 : BC_MenuItem(_("Zoom Auto"))
1102 this->canvas = canvas;
1105 int CanvasPopupAuto::handle_event()
1107 canvas->zoom_auto();
1112 CanvasPopupSize::CanvasPopupSize(Canvas *canvas, char *text, float percentage)
1115 this->canvas = canvas;
1116 this->percentage = percentage;
1118 CanvasPopupSize::~CanvasPopupSize()
1121 int CanvasPopupSize::handle_event()
1123 canvas->zoom_resize_window(percentage);
1129 CanvasPopupResetCamera::CanvasPopupResetCamera(Canvas *canvas)
1130 : BC_MenuItem(_("Reset camera"))
1132 this->canvas = canvas;
1134 int CanvasPopupResetCamera::handle_event()
1136 canvas->reset_camera();
1142 CanvasPopupResetProjector::CanvasPopupResetProjector(Canvas *canvas)
1143 : BC_MenuItem(_("Reset projector"))
1145 this->canvas = canvas;
1147 int CanvasPopupResetProjector::handle_event()
1149 canvas->reset_projector();
1155 CanvasPopupResetTranslation::CanvasPopupResetTranslation(Canvas *canvas)
1156 : BC_MenuItem(_("Reset translation"))
1158 this->canvas = canvas;
1160 int CanvasPopupResetTranslation::handle_event()
1162 canvas->reset_translation();
1168 CanvasToggleControls::CanvasToggleControls(Canvas *canvas)
1169 : BC_MenuItem(calculate_text(canvas->get_cwindow_controls()))
1171 this->canvas = canvas;
1173 int CanvasToggleControls::handle_event()
1175 canvas->toggle_controls();
1176 set_text(calculate_text(canvas->get_cwindow_controls()));
1180 char* CanvasToggleControls::calculate_text(int cwindow_controls)
1182 if(!cwindow_controls)
1183 return _("Show controls");
1185 return _("Hide controls");
1194 CanvasFullScreenItem::CanvasFullScreenItem(Canvas *canvas)
1195 : BC_MenuItem(_("Fullscreen"), "f", 'f')
1197 this->canvas = canvas;
1199 int CanvasFullScreenItem::handle_event()
1201 canvas->subwindow->unlock_window();
1202 canvas->start_fullscreen();
1203 canvas->subwindow->lock_window("CanvasFullScreenItem::handle_event");
1215 CanvasPopupRemoveSource::CanvasPopupRemoveSource(Canvas *canvas)
1216 : BC_MenuItem(_("Close source"))
1218 this->canvas = canvas;
1220 int CanvasPopupRemoveSource::handle_event()
1222 canvas->close_source();