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(BC_WindowBase *wdw, int x, int y)
46 wdw->draw_vframe(frame(), x,y, vw,vh);
49 VIcon *VIconThread::low_vicon()
51 if( !t_heap.size() ) return 0;
52 VIcon *vip = t_heap[0];
57 void VIconThread::remove_vicon(int i)
59 int sz = t_heap.size();
60 for( int k; (k=2*(i+1)) < sz; i=k ) {
61 if( t_heap[k]->age > t_heap[k-1]->age ) --k;
62 t_heap[i] = t_heap[k];
64 VIcon *last = t_heap[--sz];
65 t_heap.remove_number(sz);
66 double age = last->age;
67 for( int k; i>0 && age<t_heap[k=(i-1)/2]->age; i=k )
68 t_heap[i] = t_heap[k];
74 VIconThread(BC_WindowBase *wdw, int vw, int vh)
78 this->view_win = 0; this->vicon = 0;
79 this->view_w = vw; this->view_h = vh;
81 draw_lock = new Condition(0, "VIconThread::draw_lock", 1);
83 this->refresh_rate = VICON_RATE;
94 if( Thread::running() ) {
98 t_heap.remove_all_objects();
106 wdw->lock_window("VIconThread::start_drawing");
108 wdw->set_active_subwindow(view_win);
109 if( interrupted < 0 )
112 wdw->unlock_window();
118 wdw->lock_window("VIconThread::stop_drawing");
122 wdw->unlock_window();
125 int VIconThread::keypress_event(int key)
127 if( key != ESC ) return 0;
132 int ViewPopup::button_press_event()
134 vt->set_view_popup(0);
139 visible(VIcon *vicon, int x, int y)
141 if( vicon->hidden ) return false;
143 int my = y + vicon->vh;
144 if( my <= y0 ) return false;
145 int y1 = y0 + wdw->get_h();
146 if( y >= y1 ) return false;
148 int mx = x + vicon->vw;
149 if( mx <= x0 ) return false;
150 int x1 = x0 + wdw->get_w();
151 if( x >= x1 ) return false;
155 int ViewPopup::keypress_event()
157 int key = get_keypress();
158 return vt->keypress_event(key);
160 ViewPopup::ViewPopup(VIconThread *vt, VFrame *frame, int x, int y, int w, int h)
161 : BC_Popup(vt->wdw, x, y, w, h, BLACK)
166 ViewPopup::~ViewPopup()
168 vt->wdw->set_active_subwindow(0);
171 void ViewPopup::draw_vframe(VFrame *frame)
173 BC_WindowBase::draw_vframe(frame, 0,0, get_w(),get_h());
176 ViewPopup *VIconThread::new_view_window(VFrame *frame)
178 int wx = viewing->get_vx() - view_w, rx = 0;
179 int wy = viewing->get_vy() - view_h, ry = 0;
180 wdw->get_root_coordinates(wx, wy, &rx, &ry);
181 ViewPopup *vwin = new ViewPopup(this, frame, rx, ry, view_w, view_h);
182 wdw->set_active_subwindow(vwin);
189 for( int i=t_heap.size(); --i>=0; ) t_heap[i]->reset();
191 img_dirty = win_dirty = 0;
194 void VIconThread::add_vicon(VIcon *vip)
196 double age = vip->age;
197 int i = t_heap.size(); t_heap.append(vip);
198 for( int k; i>0 && age<t_heap[(k=(i-1)/2)]->age; i=k )
199 t_heap[i] = t_heap[k];
203 int VIconThread::del_vicon(VIcon *&vicon)
205 int i = t_heap.size();
206 while( --i >= 0 && t_heap[i] != vicon );
207 if( i < 0 ) return 0;
209 delete vicon; vicon = 0;
213 void VIconThread::set_view_popup(VIcon *vicon)
215 if( !vicon && this->vicon )
216 this->vicon->stop_audio();
223 delete view_win; view_win = 0;
224 if( (viewing=vicon) != 0 ) {
225 VFrame *frame = viewing->frame();
226 view_win = new_view_window(frame);
227 view_win->show_window();
228 vicon->start_audio();
230 wdw->set_active_subwindow(view_win);
238 for( int i=0; i<t_heap.size(); ++i )
245 if( !img_dirty && !win_dirty ) return;
246 if( img_dirty ) wdw->flash();
247 if( win_dirty && view_win ) view_win->flash();
248 win_dirty = img_dirty = 0;
254 int x = vicon->get_vx(), y = vicon->get_vy();
255 int draw_img = visible(vicon, x, y);
256 int draw_win = view_win && viewing == vicon ? 1 : 0;
257 if( !draw_img && !draw_win ) return 0;
258 if( !vicon->frame() ) return 0;
260 vicon->draw_vframe(wdw, x, y);
264 view_win->draw_vframe(vicon->frame());
274 draw_lock->lock("VIconThread::run 0");
276 wdw->lock_window("BC_WindowBase::run 1");
279 int64_t seq_no = 0, now = 0;
280 int64_t draw_flash = 1000 / refresh_rate;
281 while( !interrupted ) {
282 if( viewing != vicon )
284 VIcon *next = low_vicon();
285 while( next && next->age < draw_flash ) {
286 now = timer->get_difference();
287 if( now >= draw_flash ) break;
289 if( !next->seq_no ) {
290 next->cycle_start = now;
291 if( next->playing_audio )
294 int64_t ref_no = (now - next->cycle_start) / 1000. * refresh_rate;
295 int count = ref_no - next->seq_no;
296 if( count < 1 ) count = 1;
297 ref_no = next->seq_no + count;
298 next->age = next->cycle_start + 1000. * ref_no / refresh_rate;
299 if( !next->set_seq_no(ref_no) )
300 next->age = now + 1000.;
306 if( draw_flash < now+1 )
308 wdw->unlock_window();
309 while( !interrupted ) {
310 now = timer->get_difference();
311 int64_t ms = draw_flash - now;
313 if( ms > 100 ) ms = 100;
316 wdw->lock_window("BC_WindowBase::run 2");
317 now = timer->get_difference();
318 int64_t late = now - draw_flash;
319 if( late < 1000 ) flash();
320 int64_t ref_no = now / 1000. * refresh_rate;
321 int64_t count = ref_no - seq_no;
322 if( count < 1 ) count = 1;
324 draw_flash = seq_no * 1000. / refresh_rate;
326 if( viewing != vicon )
330 wdw->unlock_window();
335 void VIcon::init_audio(int audio_size)
337 this->audio_size = audio_size;
338 audio_data = new uint8_t[audio_size];
339 memset(audio_data, 0, audio_size);
342 void VIcon::dump(const char *dir)
345 for( int i=0; i<images.size(); ++i ) {
346 char fn[1024]; sprintf(fn,"%s/img%05d.png",dir,i);
348 VFrame *img = *images[i];