fix segv for plugin render_gui when plugin moved up/dn, opencv build fixes, opts...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / canvas.C
index 2b3953002d58cc03f8dc56321dd223baea9ede1e..125472aeec3b643daf2465b62497538326ab3e27 100644 (file)
 
 
 
-Canvas::Canvas(MWindow *mwindow,
-       BC_WindowBase *subwindow,
-       int x,
-       int y,
-       int w,
-       int h,
-       int output_w,
-       int output_h,
+Canvas::Canvas(MWindow *mwindow, BC_WindowBase *subwindow,
+       int x, int y, int w, int h, int output_w, int output_h,
        int use_scrollbars)
 {
        reset();
 
-       if(w < 10) w = 10;
-       if(h < 10) h = 10;
+       int xs10 = xS(10), ys10 = yS(10);
+       if(w < xs10) w = xs10;
+       if(h < ys10) h = ys10;
        this->mwindow = mwindow;
        this->subwindow = subwindow;
        this->x = x;
@@ -63,7 +58,7 @@ Canvas::Canvas(MWindow *mwindow,
        this->scr_w0 = subwindow->get_screen_w(0, 0);
        this->root_w = subwindow->get_root_w(0);
        this->root_h = subwindow->get_root_h(0);
-       canvas_lock = new Mutex("Canvas::canvas_lock", 1);
+       canvas_lock = new Condition(1, "Canvas::canvas_lock", 1);
 }
 
 Canvas::~Canvas()
@@ -88,25 +83,25 @@ void Canvas::reset()
        canvas_subwindow = 0;
        canvas_fullscreen = 0;
        is_processing = 0;
+       is_fullscreen = 0;
        cursor_inside = 0;
 }
 
-void Canvas::lock_canvas(const char *location)
+BC_WindowBase *Canvas::lock_canvas(const char *loc)
 {
-       canvas_lock->lock(location);
+       canvas_lock->lock(loc);
+       BC_WindowBase *wdw = get_canvas();
+       if( wdw ) wdw->lock_window(loc);
+       return wdw;
 }
 
 void Canvas::unlock_canvas()
 {
+       BC_WindowBase *wdw = get_canvas();
+       if( wdw ) wdw->unlock_window();
        canvas_lock->unlock();
 }
 
-int Canvas::is_locked()
-{
-       return canvas_lock->is_locked();
-}
-
-
 BC_WindowBase* Canvas::get_canvas()
 {
        if(get_fullscreen() && canvas_fullscreen)
@@ -135,6 +130,16 @@ void Canvas::use_vwindow()
        canvas_menu->use_vwindow();
 }
 
+int Canvas::get_fullscreen()
+{
+       return is_fullscreen;
+}
+
+void Canvas::set_fullscreen(int value)
+{
+       is_fullscreen = value;
+}
+
 // Get dimensions given a zoom
 void Canvas::calculate_sizes(float aspect_ratio,
        int output_w,
@@ -576,6 +581,22 @@ void Canvas::get_scrollbars(EDL *edl,
 //printf("Canvas::get_scrollbars 5 %d %d\n", get_xscroll(), get_yscroll());
 }
 
+
+void Canvas::update_geometry(EDL *edl, int x, int y, int w, int h)
+{
+       int redraw = 0;
+       if( this->x != x || this->y != y ||
+           this->w != w || this->h != h ) redraw = 1;
+       if( !redraw ) {
+               int vx = x, vy = y, vw = w, vh = h;
+               get_scrollbars(edl, vx, vy, vw, vh);
+               if( vx != view_x || vy != view_y ||
+                   vw != view_w || vh != view_h ) redraw = 1;
+       }
+       if( !redraw ) return;
+       reposition_window(edl, x, y, w, h);
+}
+
 void Canvas::reposition_window(EDL *edl, int x, int y, int w, int h)
 {
        this->x = view_x = x;  this->y = view_y = y;
@@ -596,9 +617,28 @@ void Canvas::reposition_window(EDL *edl, int x, int y, int w, int h)
                        canvas_subwindow->flash(0);
                }
        }
+       refresh(0);
+}
 
-
-       draw_refresh(0);
+// must hold window lock
+int Canvas::refresh(int flush)
+{
+       BC_WindowBase *window = get_canvas();
+       if( !window ) return 0;
+// relock in lock order to prevent deadlock
+       window->unlock_window();
+       lock_canvas("Canvas::refresh");
+       draw_refresh(flush);
+       canvas_lock->unlock();
+       return 1;
+}
+// must not hold locks
+int Canvas::redraw(int flush)
+{
+       lock_canvas("Canvas::redraw");
+       draw_refresh(flush);
+       unlock_canvas();
+       return 1;
 }
 
 void Canvas::set_cursor(int cursor)
@@ -703,47 +743,35 @@ void Canvas::stop_fullscreen()
 
 void Canvas::create_canvas()
 {
+       canvas_lock->lock("Canvas::create_canvas");
        int video_on = 0;
-       lock_canvas("Canvas::create_canvas");
-
-
-       if(!get_fullscreen())
+       BC_WindowBase *wdw = 0;
+       if( !get_fullscreen() ) {
 // Enter windowed
-       {
-               if(canvas_fullscreen)
-               {
+               if( canvas_fullscreen ) {
+                       canvas_fullscreen->lock_window("Canvas::create_canvas 1");
                        video_on = canvas_fullscreen->get_video_on();
-                       canvas_fullscreen->stop_video();
-                       canvas_fullscreen->lock_window("Canvas::create_canvas 2");
+                       if( video_on ) canvas_fullscreen->stop_video();
                        canvas_fullscreen->hide_window();
                        canvas_fullscreen->unlock_window();
                }
-
-               if(!canvas_auxwindow && !canvas_subwindow)
-               {
+               if( !canvas_auxwindow && !canvas_subwindow ) {
                        subwindow->add_subwindow(canvas_subwindow = new CanvasOutput(this,
-                               view_x,
-                               view_y,
-                               view_w,
-                               view_h));
+                               view_x, view_y, view_w, view_h));
                }
+               wdw = get_canvas();
+               wdw->lock_window("Canvas::create_canvas 2");
        }
-       else
+       else {
 // Enter fullscreen
-       {
-               BC_WindowBase *wdw = canvas_auxwindow ?
-                       canvas_auxwindow : canvas_subwindow;
-               if(wdw)
-               {
-                       video_on = wdw->get_video_on();
-                       wdw->stop_video();
-               }
-
+               wdw = canvas_auxwindow ? canvas_auxwindow : canvas_subwindow;
+               wdw->lock_window("Canvas::create_canvas 3");
+               video_on = wdw->get_video_on();
+               if( video_on ) wdw->stop_video();
                int x, y, w, h;
                wdw->get_fullscreen_geometry(x, y, w, h);
-
-               if( canvas_fullscreen )
-               {
+               wdw->unlock_window();
+               if( canvas_fullscreen ) {
                        if( x != canvas_fullscreen->get_x() ||
                            y != canvas_fullscreen->get_y() ||
                            w != canvas_fullscreen->get_w() ||
@@ -752,32 +780,22 @@ void Canvas::create_canvas()
                                canvas_fullscreen = 0;
                        }
                }
-               if(!canvas_fullscreen)
-               {
+               if( !canvas_fullscreen )
                        canvas_fullscreen = new CanvasFullScreen(this, w, h);
-               }
-               else
-               {
-                       canvas_fullscreen->reposition_window(x, y);
-                       canvas_fullscreen->show_window();
-               }
-       }
-
-
-       if(!video_on)
-       {
-               get_canvas()->lock_window("Canvas::create_canvas 1");
-               draw_refresh();
-               get_canvas()->unlock_window();
+               wdw = canvas_fullscreen;
+               wdw->lock_window("Canvas::create_canvas 4");
+               wdw->show_window();
+               wdw->sync_display();
+               wdw->reposition_window(x, y);
        }
 
-       if(video_on) get_canvas()->start_video();
-
-       get_canvas()->lock_window("Canvas::create_canvas 2");
-       get_canvas()->focus();
-       get_canvas()->unlock_window();
-
-       unlock_canvas();
+       if( !video_on )
+               draw_refresh(1);
+       else
+               wdw->start_video();
+       wdw->focus();
+       wdw->unlock_window();
+       canvas_lock->unlock();
 }
 
 
@@ -870,36 +888,26 @@ void Canvas::update_refresh(VideoDevice *device, VFrame *output_frame)
        }
 
        if( use_opengl ) {
-               get_canvas()->unlock_window();
                unlock_canvas();
-
                mwindow->playback_3d->copy_from(this, refresh_frame, output_frame, 0);
-               lock_canvas(" Canvas::output_refresh");
-               get_canvas()->lock_window(" Canvas::output_refresh");
+               lock_canvas("Canvas::update_refresh");
        }
        else
                refresh_frame->transfer_from(output_frame, -1);
 }
 
-
-void Canvas::clear(int flush)
+void Canvas::clear(int flash)
 {
-       if( refresh_frame )
-               refresh_frame->clear_frame();
-       BC_WindowBase *wdw = get_canvas();
-       if( !wdw ) return;
-       wdw->set_bg_color(BLACK);
-       wdw->clear_box(0,0, wdw->get_w(), wdw->get_h());
-       wdw->flash(flush);
+       BC_WindowBase *cwdw = get_canvas();
+       if( !cwdw )  return;
+       cwdw->set_bg_color(get_clear_color());
+       cwdw->clear_box(0,0, cwdw->get_w(), cwdw->get_h());
+       if( flash ) cwdw->flash();
 }
 
 
-
 CanvasOutput::CanvasOutput(Canvas *canvas,
-    int x,
-    int y,
-    int w,
-    int h)
+    int x, int y, int w, int h)
  : BC_SubWindow(x, y, w, h, BLACK)
 {
        this->canvas = canvas;
@@ -965,10 +973,8 @@ CanvasXScroll::~CanvasXScroll()
 
 int CanvasXScroll::handle_event()
 {
-//printf("CanvasXScroll::handle_event %d %d %d\n", get_length(), get_value(), get_handlelength());
        canvas->update_zoom(get_value(), canvas->get_yscroll(), canvas->get_zoom());
-       canvas->draw_refresh();
-       return 1;
+       return canvas->refresh(1);
 }
 
 
@@ -985,10 +991,8 @@ CanvasYScroll::~CanvasYScroll()
 
 int CanvasYScroll::handle_event()
 {
-//printf("CanvasYScroll::handle_event %d %d\n", get_value(), get_length());
        canvas->update_zoom(canvas->get_xscroll(), get_value(), canvas->get_zoom());
-       canvas->draw_refresh();
-       return 1;
+       return canvas->refresh(1);
 }
 
 
@@ -1036,19 +1040,36 @@ CanvasPopup::~CanvasPopup()
 {
 }
 
+CanvasZoomSize::CanvasZoomSize(Canvas *canvas)
+ : BC_MenuItem(_("Zoom..."))
+{
+       this->canvas = canvas;
+}
+
+CanvasSizeSubMenu::CanvasSizeSubMenu(CanvasZoomSize *zoom_size)
+{
+       this->zoom_size = zoom_size;
+}
+
 void CanvasPopup::create_objects()
 {
        add_item(new BC_MenuItem("-"));
        add_item(new CanvasFullScreenItem(canvas));
-       add_item(new CanvasPopupSize(canvas, _("Zoom 25%"), 0.25));
-       add_item(new CanvasPopupSize(canvas, _("Zoom 33%"), 0.33));
-       add_item(new CanvasPopupSize(canvas, _("Zoom 50%"), 0.5));
-       add_item(new CanvasPopupSize(canvas, _("Zoom 75%"), 0.75));
-       add_item(new CanvasPopupSize(canvas, _("Zoom 100%"), 1.0));
-       add_item(new CanvasPopupSize(canvas, _("Zoom 150%"), 1.5));
-       add_item(new CanvasPopupSize(canvas, _("Zoom 200%"), 2.0));
-       add_item(new CanvasPopupSize(canvas, _("Zoom 300%"), 3.0));
-       add_item(new CanvasPopupSize(canvas, _("Zoom 400%"), 4.0));
+
+       CanvasZoomSize *zoom_size = new CanvasZoomSize(canvas);
+       add_item(zoom_size);
+       CanvasSizeSubMenu *submenu = new CanvasSizeSubMenu(zoom_size);
+       zoom_size->add_submenu(submenu);
+
+       submenu->add_submenuitem(new CanvasPopupSize(canvas, _("Zoom 25%"), 0.25));
+       submenu->add_submenuitem(new CanvasPopupSize(canvas, _("Zoom 33%"), 0.33));
+       submenu->add_submenuitem(new CanvasPopupSize(canvas, _("Zoom 50%"), 0.5));
+       submenu->add_submenuitem(new CanvasPopupSize(canvas, _("Zoom 75%"), 0.75));
+       submenu->add_submenuitem(new CanvasPopupSize(canvas, _("Zoom 100%"), 1.0));
+       submenu->add_submenuitem(new CanvasPopupSize(canvas, _("Zoom 150%"), 1.5));
+       submenu->add_submenuitem(new CanvasPopupSize(canvas, _("Zoom 200%"), 2.0));
+       submenu->add_submenuitem(new CanvasPopupSize(canvas, _("Zoom 300%"), 3.0));
+       submenu->add_submenuitem(new CanvasPopupSize(canvas, _("Zoom 400%"), 4.0));
 }
 
 void CanvasPopup::use_cwindow()
@@ -1056,6 +1077,8 @@ void CanvasPopup::use_cwindow()
        add_item(new CanvasPopupAuto(canvas));
        add_item(new CanvasPopupResetCamera(canvas));
        add_item(new CanvasPopupResetProjector(canvas));
+       add_item(new CanvasPopupCameraKeyframe(canvas));
+       add_item(new CanvasPopupProjectorKeyframe(canvas));
        add_item(toggle_controls = new CanvasToggleControls(canvas));
 }
 
@@ -1099,9 +1122,8 @@ int CanvasPopupSize::handle_event()
 }
 
 
-
 CanvasPopupResetCamera::CanvasPopupResetCamera(Canvas *canvas)
- : BC_MenuItem(_("Reset camera"), "F11", KEY_F11)
+ : BC_MenuItem(_("Reset camera"), _("F11"), KEY_F11)
 {
        this->canvas = canvas;
 }
@@ -1111,10 +1133,8 @@ int CanvasPopupResetCamera::handle_event()
        return 1;
 }
 
-
-
 CanvasPopupResetProjector::CanvasPopupResetProjector(Canvas *canvas)
- : BC_MenuItem(_("Reset projector"), "F12", KEY_F12)
+ : BC_MenuItem(_("Reset projector"), _("F12"), KEY_F12)
 {
        this->canvas = canvas;
 }
@@ -1125,6 +1145,31 @@ int CanvasPopupResetProjector::handle_event()
 }
 
 
+CanvasPopupCameraKeyframe::CanvasPopupCameraKeyframe(Canvas *canvas)
+ : BC_MenuItem(_("Camera keyframe"), _("Shift-F11"), KEY_F11)
+{
+       this->canvas = canvas;
+       set_shift(1);
+}
+int CanvasPopupCameraKeyframe::handle_event()
+{
+       canvas->camera_keyframe();
+       return 1;
+}
+
+CanvasPopupProjectorKeyframe::CanvasPopupProjectorKeyframe(Canvas *canvas)
+ : BC_MenuItem(_("Projector keyframe"), _("Shift-F12"), KEY_F12)
+{
+       this->canvas = canvas;
+       set_shift(1);
+}
+int CanvasPopupProjectorKeyframe::handle_event()
+{
+       canvas->projector_keyframe();
+       return 1;
+}
+
+
 
 CanvasPopupResetTranslation::CanvasPopupResetTranslation(Canvas *canvas)
  : BC_MenuItem(_("Reset translation"))