11 VIcon(int vw, int vh, double rate)
15 this->frame_rate = rate;
35 add_image(VFrame *frm, int ww, int hh, int vcmdl)
37 VIFrame *vifrm = new VIFrame(ww, hh, vcmdl);
39 img->transfer_from(frm);
44 draw_vframe(VIconThread *vt, BC_WindowBase *wdw, int x, int y)
46 VFrame *vfrm = frame();
48 int sx0 = 0, sx1 = sx0 + vt->view_w;
49 int sy0 = 0, sy1 = sy0 + vt->view_h;
50 int dx0 = x, dx1 = dx0 + vw;
51 int dy0 = y, dy1 = dy0 + vh;
52 if( (x=vt->draw_x0-dx0) > 0 ) { sx0 += (x*vt->view_w)/vw; dx0 = vt->draw_x0; }
53 if( (x=dx1-vt->draw_x1) > 0 ) { sx1 -= (x*vt->view_w)/vw; dx1 = vt->draw_x1; }
54 if( (y=vt->draw_y0-dy0) > 0 ) { sy0 += (y*vt->view_h)/vh; dy0 = vt->draw_y0; }
55 if( (y=dy1-vt->draw_y1) > 0 ) { sy1 -= (y*vt->view_h)/vh; dy1 = vt->draw_y1; }
56 int sw = sx1 - sx0, sh = sy1 - sy0;
57 int dw = dx1 - dx0, dh = dy1 - dy0;
58 if( dw > 0 && dh > 0 && sw > 0 && sh > 0 )
59 wdw->draw_vframe(vfrm, dx0,dy0, dw,dh, sx0,sy0, sw,sh);
63 set_drawing_area(int x0, int y0, int x1, int y1)
65 draw_x0 = x0; draw_y0 = y0;
66 draw_x1 = x1; draw_y1 = y1;
69 VIcon *VIconThread::low_vicon()
71 if( !t_heap.size() ) return 0;
72 VIcon *vip = t_heap[0];
77 void VIconThread::remove_vicon(int i)
79 int sz = t_heap.size();
80 for( int k; (k=2*(i+1)) < sz; i=k ) {
81 if( t_heap[k]->age > t_heap[k-1]->age ) --k;
82 t_heap[i] = t_heap[k];
84 VIcon *last = t_heap[--sz];
85 t_heap.remove_number(sz);
86 double age = last->age;
87 for( int k; i>0 && age<t_heap[k=(i-1)/2]->age; i=k )
88 t_heap[i] = t_heap[k];
94 VIconThread(BC_WindowBase *wdw, int vw, int vh)
98 this->view_win = 0; this->vicon = 0;
99 this->view_w = vw; this->view_h = vh;
101 this->draw_x0 = 0; this->draw_x1 = wdw->get_w();
102 this->draw_y0 = 0; this->draw_y1 = wdw->get_h();
103 draw_lock = new Condition(0, "VIconThread::draw_lock", 1);
105 this->refresh_rate = VICON_RATE;
117 if( Thread::running() ) {
121 t_heap.remove_all_objects();
129 wdw->lock_window("VIconThread::start_drawing");
131 wdw->set_active_subwindow(view_win);
132 if( interrupted < 0 )
135 timer->subtract(-stop_age);
137 wdw->unlock_window();
143 wdw->lock_window("VIconThread::stop_drawing");
147 stop_age = timer->get_difference();
148 wdw->unlock_window();
151 int VIconThread::keypress_event(int key)
153 if( key != ESC ) return 0;
159 visible(VIcon *vicon, int x, int y)
161 if( vicon->hidden ) return false;
162 if( y+vicon->vh <= draw_y0 ) return false;
163 if( y >= draw_y1 ) return false;
164 if( x+vicon->vw <= draw_x0 ) return false;
165 if( x >= draw_x1 ) return false;
169 int ViewPopup::keypress_event()
171 int key = get_keypress();
172 return vt->keypress_event(key);
175 int ViewPopup::button_press_event()
177 return vt->popup_button_press(get_cursor_x(), get_cursor_y());
179 int ViewPopup::button_release_event()
181 return vt->popup_button_release(get_cursor_x(), get_cursor_y());
183 int ViewPopup::cursor_motion_event()
185 return vt->popup_cursor_motion(get_cursor_x(), get_cursor_y());
189 ViewPopup::ViewPopup(VIconThread *vt, VFrame *frame, int x, int y, int w, int h)
190 : BC_Popup(vt->wdw, x, y, w, h, BLACK)
195 ViewPopup::~ViewPopup()
197 vt->wdw->set_active_subwindow(0);
200 ViewPopup *VIconThread::new_view_window(VFrame *frame)
202 BC_WindowBase *parent = wdw->get_parent();
203 XineramaScreenInfo *info = parent->get_xinerama_info(-1);
204 int cx = info ? info->x_org + info->width/2 : parent->get_root_w(0)/2;
205 int cy = info ? info->y_org + info->height/2 : parent->get_root_h(0)/2;
206 int vx = viewing->get_vx(), rx = 0;
207 int vy = viewing->get_vy(), ry = 0;
208 wdw->get_root_coordinates(vx, vy, &rx, &ry);
209 rx += (rx >= cx ? -view_w : viewing->vw);
210 ry += (ry >= cy ? -view_h : viewing->vh);
211 ViewPopup *vwin = new ViewPopup(this, frame, rx, ry, view_w, view_h);
212 wdw->set_active_subwindow(vwin);
219 for( int i=t_heap.size(); --i>=0; ) t_heap[i]->reset();
221 img_dirty = win_dirty = 0;
224 void VIconThread::add_vicon(VIcon *vip)
226 double age = vip->age;
227 int i = t_heap.size(); t_heap.append(vip);
228 for( int k; i>0 && age<t_heap[(k=(i-1)/2)]->age; i=k )
229 t_heap[i] = t_heap[k];
233 int VIconThread::del_vicon(VIcon *vicon)
235 int i = t_heap.size();
236 while( --i >= 0 && t_heap[i] != vicon );
237 if( i < 0 ) return 0;
242 void VIconThread::draw_vframe(BC_WindowBase *wdw, VFrame *frame)
244 if( !wdw || !frame ) return;
245 wdw->draw_vframe(frame, 0,0, wdw->get_w(),wdw->get_h());
248 void VIconThread::set_view_popup(VIcon *vicon, VIconDrawVFrame *draw_vfrm)
251 this->draw_vfrm = vicon && !draw_vfrm ? VIconThread::draw_vframe : draw_vfrm;
254 void VIconThread::close_view_popup()
262 if( viewing ) viewing->stop_audio();
263 delete view_win; view_win = 0;
264 if( (viewing=vicon) != 0 ) {
265 VFrame *frame = viewing->frame();
266 view_win = new_view_window(frame);
267 view_win->show_window();
268 vicon->start_audio();
270 wdw->set_active_subwindow(view_win);
278 for( int i=0; i<t_heap.size(); ++i )
285 if( !img_dirty && !win_dirty ) return;
286 if( img_dirty ) wdw->flash();
287 if( win_dirty && view_win ) view_win->flash();
288 win_dirty = img_dirty = 0;
294 int x = vicon->get_vx(), y = vicon->get_vy();
295 int draw_img = visible(vicon, x, y);
296 int draw_win = view_win && viewing == vicon ? 1 : 0;
297 if( !draw_img && !draw_win ) return 0;
298 if( !vicon->frame() ) return 0;
300 vicon->draw_vframe(this, wdw, x, y);
304 draw_vfrm(view_win, vicon->frame());
310 void VIconThread::hide_vicons(int v)
312 for( int i=0; i<t_heap.size(); ++i ) {
313 t_heap[i]->hidden = v;
322 draw_lock->lock("VIconThread::run 0");
324 wdw->lock_window("BC_WindowBase::run 1");
327 int64_t seq_no = 0, now = 0;
328 int64_t draw_flash = 1000 / refresh_rate;
329 while( !interrupted ) {
330 if( viewing != vicon )
332 VIcon *next = low_vicon();
333 while( next && next->age < draw_flash ) {
334 now = timer->get_difference();
335 if( now >= draw_flash ) break;
337 if( !next->seq_no ) {
338 next->cycle_start = now;
339 if( next->playing_audio > 0 )
342 int64_t ref_no = (now - next->cycle_start) / 1000. * refresh_rate;
343 int count = ref_no - next->seq_no;
344 if( count < 1 ) count = 1;
345 ref_no = next->seq_no + count;
346 next->age = next->cycle_start + 1000. * ref_no / refresh_rate;
347 if( !next->set_seq_no(ref_no) )
348 next->age = now + 1000.;
354 if( draw_flash < now+1 )
356 wdw->unlock_window();
357 while( !interrupted ) {
358 now = timer->get_difference();
359 int64_t ms = draw_flash - now;
361 if( ms > 100 ) ms = 100;
364 wdw->lock_window("BC_WindowBase::run 2");
365 now = timer->get_difference();
366 int64_t late = now - draw_flash;
367 if( late < 1000 ) flash();
368 int64_t ref_no = now / 1000. * refresh_rate;
369 int64_t count = ref_no - seq_no;
370 if( count < 1 ) count = 1;
372 draw_flash = seq_no * 1000. / refresh_rate;
374 if( viewing != vicon )
378 wdw->unlock_window();
383 void VIcon::init_audio(int audio_size)
385 this->audio_size = audio_size;
386 audio_data = new uint8_t[audio_size];
387 memset(audio_data, 0, audio_size);
390 void VIcon::dump(const char *dir)
393 for( int i=0; i<images.size(); ++i ) {
394 char fn[1024]; sprintf(fn,"%s/img%05d.png",dir,i);
396 VFrame *img = *images[i];