X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fguicast%2Fvicon.C;h=e0b4d1b8f7eb1b57e210b894a97d287262601761;hp=f9978b26ebf0e917b1d7f6852a26b72dbf670c6d;hb=refs%2Fheads%2Fmaster;hpb=7fd85fb66168f6b518c5f2d73e04036e87faa0e1 diff --git a/cinelerra-5.1/guicast/vicon.C b/cinelerra-5.1/guicast/vicon.C index f9978b26..e0b4d1b8 100644 --- a/cinelerra-5.1/guicast/vicon.C +++ b/cinelerra-5.1/guicast/vicon.C @@ -1,3 +1,24 @@ +/* + * CINELERRA + * Copyright (C) 2016-2020 William Morrow + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + #include "vicon.h" #include "bctimer.h" @@ -8,10 +29,10 @@ #include "condition.h" VIcon:: -VIcon(int vw, int vh, double rate) +VIcon(int w, int h, double rate) { - this->vw = vw; - this->vh = vh; + this->w = w; + this->h = h; this->frame_rate = rate; cycle_start = 0; @@ -35,8 +56,7 @@ void VIcon:: add_image(VFrame *frm, int ww, int hh, int vcmdl) { VIFrame *vifrm = new VIFrame(ww, hh, vcmdl); - VFrame *img = *vifrm; - img->transfer_from(frm); + vifrm->vfrm->transfer_from(frm); images.append(vifrm); } @@ -45,20 +65,31 @@ draw_vframe(VIconThread *vt, BC_WindowBase *wdw, int x, int y) { VFrame *vfrm = frame(); if( !vfrm ) return; - int sx0 = 0, sx1 = sx0 + vt->view_w; - int sy0 = 0, sy1 = sy0 + vt->view_h; - int dx0 = x, dx1 = dx0 + vw; - int dy0 = y, dy1 = dy0 + vh; - if( (x=vt->draw_x0-dx0) > 0 ) { sx0 += (x*vt->view_w)/vw; dx0 = vt->draw_x0; } - if( (x=dx1-vt->draw_x1) > 0 ) { sx1 -= (x*vt->view_w)/vw; dx1 = vt->draw_x1; } - if( (y=vt->draw_y0-dy0) > 0 ) { sy0 += (y*vt->view_h)/vh; dy0 = vt->draw_y0; } - if( (y=dy1-vt->draw_y1) > 0 ) { sy1 -= (y*vt->view_h)/vh; dy1 = vt->draw_y1; } + int sx0 = 0, sx1 = sx0 + vt->vw; + int sy0 = 0, sy1 = sy0 + vt->vh; + int dx0 = x, dx1 = dx0 + w; + int dy0 = y, dy1 = dy0 + h; + if( (x=vt->draw_x0-dx0) > 0 ) { sx0 += (x*vt->vw)/w; dx0 = vt->draw_x0; } + if( (x=dx1-vt->draw_x1) > 0 ) { sx1 -= (x*vt->vw)/w; dx1 = vt->draw_x1; } + if( (y=vt->draw_y0-dy0) > 0 ) { sy0 += (y*vt->vh)/h; dy0 = vt->draw_y0; } + if( (y=dy1-vt->draw_y1) > 0 ) { sy1 -= (y*vt->vh)/h; dy1 = vt->draw_y1; } int sw = sx1 - sx0, sh = sy1 - sy0; int dw = dx1 - dx0, dh = dy1 - dy0; if( dw > 0 && dh > 0 && sw > 0 && sh > 0 ) wdw->draw_vframe(vfrm, dx0,dy0, dw,dh, sx0,sy0, sw,sh); } + +int VIconThread::cursor_inside(int x, int y) +{ + if( !viewing ) return 0; + int vx = viewing->get_vx(); + if( x < vx || x >= vx+vw ) return 0; + int vy = viewing->get_vy(); + if( y < vy || y >= vy+vh ) return 0; + return 1; +} + void VIconThread:: set_drawing_area(int x0, int y0, int x1, int y1) { @@ -76,6 +107,7 @@ VIcon *VIconThread::low_vicon() void VIconThread::remove_vicon(int i) { + if( t_heap[i] == solo ) solo = 0; int sz = t_heap.size(); for( int k; (k=2*(i+1)) < sz; i=k ) { if( t_heap[k]->age > t_heap[k-1]->age ) --k; @@ -91,18 +123,22 @@ void VIconThread::remove_vicon(int i) VIconThread:: -VIconThread(BC_WindowBase *wdw, int vw, int vh) +VIconThread(BC_WindowBase *wdw, int vw, int vh, int view_w, int view_h) : Thread(1, 0, 0) { this->wdw = wdw; - this->view_win = 0; this->vicon = 0; - this->view_w = vw; this->view_h = vh; - this->viewing = 0; - this->draw_x0 = 0; this->draw_x1 = wdw->get_w(); - this->draw_y0 = 0; this->draw_y1 = wdw->get_h(); + this->vw = vw; this->vh = vh; + this->view_w = view_w; this->view_h = view_h; + this->view_win = 0; this->vicon = 0; + this->viewing = 0; this->solo = 0; + this->draw_x0 = 0; this->draw_x1 = wdw->get_w(); + this->draw_y0 = 0; this->draw_y1 = wdw->get_h(); draw_lock = new Condition(0, "VIconThread::draw_lock", 1); timer = new Timer(); this->refresh_rate = VICON_RATE; + this->draw_flash = 0; + this->seq_no = 0; + this->now = 0; done = 0; interrupted = -1; stop_age = 0; @@ -141,17 +177,26 @@ void VIconThread:: stop_drawing() { wdw->lock_window("VIconThread::stop_drawing"); - set_view_popup(0); + close_view_popup(); if( !interrupted ) interrupted = 1; stop_age = timer->get_difference(); wdw->unlock_window(); } +void VIconThread:: +stop_viewing() +{ + if( viewing ) { + viewing->stop_audio(); + viewing = 0; + } +} + int VIconThread::keypress_event(int key) { if( key != ESC ) return 0; - set_view_popup(0); + close_view_popup(); return 1; } @@ -159,9 +204,9 @@ bool VIconThread:: visible(VIcon *vicon, int x, int y) { if( vicon->hidden ) return false; - if( y+vicon->vh <= draw_y0 ) return false; + if( y+vicon->h <= draw_y0 ) return false; if( y >= draw_y1 ) return false; - if( x+vicon->vw <= draw_x0 ) return false; + if( x+vicon->w <= draw_x0 ) return false; if( x >= draw_x1 ) return false; return true; } @@ -172,7 +217,8 @@ int ViewPopup::keypress_event() return vt->keypress_event(key); } -ViewPopup::ViewPopup(VIconThread *vt, VFrame *frame, int x, int y, int w, int h) + +ViewPopup::ViewPopup(VIconThread *vt, int x, int y, int w, int h) : BC_Popup(vt->wdw, x, y, w, h, BLACK) { this->vt = vt; @@ -183,13 +229,7 @@ ViewPopup::~ViewPopup() vt->wdw->set_active_subwindow(0); } -void ViewPopup::draw_vframe(VFrame *frame) -{ - if( !frame ) return; - BC_WindowBase::draw_vframe(frame, 0,0, get_w(),get_h()); -} - -ViewPopup *VIconThread::new_view_window(VFrame *frame) +ViewPopup *VIconThread::new_view_window(ViewPopup *vpopup) { BC_WindowBase *parent = wdw->get_parent(); XineramaScreenInfo *info = parent->get_xinerama_info(-1); @@ -198,13 +238,17 @@ ViewPopup *VIconThread::new_view_window(VFrame *frame) int vx = viewing->get_vx(), rx = 0; int vy = viewing->get_vy(), ry = 0; wdw->get_root_coordinates(vx, vy, &rx, &ry); - rx += (rx >= cx ? -view_w : viewing->vw); - ry += (ry >= cy ? -view_h : viewing->vh); - ViewPopup *vwin = new ViewPopup(this, frame, rx, ry, view_w, view_h); - wdw->set_active_subwindow(vwin); - return vwin; + rx += (rx >= cx ? -view_w+viewing->w/4 : viewing->w-viewing->w/4); + ry += (ry >= cy ? -view_h+viewing->h/4 : viewing->h-viewing->h/4); + if( vpopup ) + vpopup->reposition_window(rx, ry, view_w, view_h); + else + vpopup = new ViewPopup(this, rx, ry, view_w, view_h); + wdw->set_active_subwindow(vpopup); + return vpopup; } + void VIconThread:: reset_images() { @@ -222,36 +266,66 @@ void VIconThread::add_vicon(VIcon *vip) t_heap[i] = vip; } -int VIconThread::del_vicon(VIcon *&vicon) +int VIconThread::del_vicon(VIcon *vicon) { int i = t_heap.size(); while( --i >= 0 && t_heap[i] != vicon ); if( i < 0 ) return 0; remove_vicon(i); - delete vicon; vicon = 0; return 1; } +void ViewPopup::draw_vframe(VFrame *frame) +{ + if( !frame ) return; + BC_WindowBase::draw_vframe(frame, 0,0, get_w(),get_h()); +} + void VIconThread::set_view_popup(VIcon *vicon) { + if( viewing == vicon && !this->vicon ) return; this->vicon = vicon; + if( interrupted ) update_view(vicon ? 1 : 0); + +} + +void VIconThread::close_view_popup() +{ + set_view_popup(0); } int VIconThread:: -update_view() +update_view(int do_audio) { if( viewing ) viewing->stop_audio(); delete view_win; view_win = 0; - if( (viewing=vicon) != 0 ) { - VFrame *frame = viewing->frame(); - view_win = new_view_window(frame); + VFrame *vfrm; + if( (viewing=vicon) != 0 && (vfrm=viewing->frame()) != 0 ) { + view_win = new_view_window(0); + view_win->draw_vframe(vfrm); + view_win->flash(0); view_win->show_window(); - vicon->start_audio(); + if( do_audio ) vicon->start_audio(); } wdw->set_active_subwindow(view_win); return 1; } +int VIconThread::zoom_scale(int dir) +{ + VFrame *vfrm; + if( !viewing || !view_win || !(vfrm=viewing->frame()) ) return 0; + int view_h = this->view_h; + view_h += dir*view_h/10 + dir; + bclamp(view_h, 16,512); + this->view_h = view_h; + this->view_w = view_h * vw/vh; + new_view_window(view_win); + view_win->draw_vframe(vfrm); + view_win->flash(1); + return 1; +} + void VIconThread:: draw_images() @@ -276,13 +350,14 @@ draw(VIcon *vicon) int draw_img = visible(vicon, x, y); int draw_win = view_win && viewing == vicon ? 1 : 0; if( !draw_img && !draw_win ) return 0; - if( !vicon->frame() ) return 0; + VFrame *vfrm = vicon->frame(); + if( !vfrm ) return 0; if( draw_img ) { vicon->draw_vframe(this, wdw, x, y); img_dirty = 1; } if( draw_win ) { - view_win->draw_vframe(vicon->frame()); + view_win->draw_vframe(vfrm); win_dirty = 1; } return 1; @@ -296,6 +371,26 @@ void VIconThread::hide_vicons(int v) } } +int VIconThread::show_vicon(VIcon *next) +{ + now = timer->get_difference(); + if( now >= draw_flash ) return 1; + draw(next); + if( !next->seq_no ) { + next->cycle_start = now; + if( next->playing_audio > 0 ) + next->start_audio(); + } + int64_t ref_no = (now - next->cycle_start) / 1000. * refresh_rate; + int count = ref_no - next->seq_no; + if( count < 1 ) count = 1; + ref_no = next->seq_no + count; + next->age = next->cycle_start + 1000. * ref_no / refresh_rate; + if( !next->set_seq_no(ref_no) ) + next->age = now + 1000.; + return 0; +} + void VIconThread:: run() { @@ -305,35 +400,25 @@ run() wdw->lock_window("BC_WindowBase::run 1"); drawing_started(); reset_images(); - int64_t seq_no = 0, now = 0; - int64_t draw_flash = 1000 / refresh_rate; + draw_flash = 1000 / refresh_rate; + seq_no = 0; now = 0; while( !interrupted ) { if( viewing != vicon ) - update_view(); - VIcon *next = low_vicon(); - while( next && next->age < draw_flash ) { - now = timer->get_difference(); - if( now >= draw_flash ) break; - draw(next); - if( !next->seq_no ) { - next->cycle_start = now; - if( next->playing_audio ) - next->start_audio(); + update_view(1); + if( !solo ) { + VIcon *next = low_vicon(); + while( !interrupted && next && next->age < draw_flash ) { + if( show_vicon(next) ) break; + add_vicon(next); + next = low_vicon(); } - int64_t ref_no = (now - next->cycle_start) / 1000. * refresh_rate; - int count = ref_no - next->seq_no; - if( count < 1 ) count = 1; - ref_no = next->seq_no + count; - next->age = next->cycle_start + 1000. * ref_no / refresh_rate; - if( !next->set_seq_no(ref_no) ) - next->age = now + 1000.; + if( !next ) break; add_vicon(next); - next = low_vicon(); + if( draw_flash < now+1 ) + draw_flash = now+1; } - if( !next ) break; - add_vicon(next); - if( draw_flash < now+1 ) - draw_flash = now+1; + else + show_vicon(solo); wdw->unlock_window(); while( !interrupted ) { now = timer->get_difference(); @@ -353,7 +438,7 @@ run() draw_flash = seq_no * 1000. / refresh_rate; } if( viewing != vicon ) - update_view(); + update_view(1); drawing_stopped(); interrupted = -1; wdw->unlock_window(); @@ -372,10 +457,11 @@ void VIcon::dump(const char *dir) { mkdir(dir,0777); for( int i=0; ivfrm; + if( !vfrm ) continue; char fn[1024]; sprintf(fn,"%s/img%05d.png",dir,i); printf("\r%s",fn); - VFrame *img = *images[i]; - img->write_png(fn); + vfrm->write_png(fn); } printf("\n"); }