3 #include "bcmenuitem.h"
5 #include "commercials.h"
10 #include "mwindowgui.h"
17 static inline int min(int a,int b) { return a<b ? a : b; }
18 static inline int max(int a,int b) { return a>b ? a : b; }
20 #define MAX_SEARCH 100
23 DbWindow(MWindow *mwindow)
26 this->mwindow = mwindow;
27 window_lock = new Mutex("DbWindow::window_lock");
28 db_lock = new Mutex("DbWindow::db_lock");
33 DbWindow::MDb::MDb(DbWindow *d)
34 : Garbage("DbWindow::MDb"), dwin(d)
36 if( !d->mwindow->has_commercials() ) return;
57 window_lock->lock("DbWindow::start1");
58 if( Thread::running() ) {
59 gui->lock_window("DbWindow::start2");
65 gui = new DbWindowGUI(this);
68 window_lock->unlock();
75 if( Thread::running() ) {
76 window_lock->lock("DbWindow::stop");
77 if( gui ) gui->set_done(1);
78 window_lock->unlock();
87 gui->lock_window("DbWindow::run");
88 gui->create_objects();
89 gui->search(MAX_SEARCH,"");
93 window_lock->lock("DbWindow::stop");
95 window_lock->unlock();
100 DbWindowTitleText(DbWindowGUI *gui, int x, int y)
101 : BC_CheckBox(x, y, &gui->title_text_enable, _("titles"))
106 DbWindowTitleText::~DbWindowTitleText()
110 int DbWindowTitleText::
113 gui->title_text_enable = get_value();
114 if( !gui->title_text_enable ) gui->info_text->update(1);
120 DbWindowInfoText(DbWindowGUI *gui, int x, int y)
121 : BC_CheckBox(x, y, &gui->info_text_enable, _("info"))
126 DbWindowInfoText::~DbWindowInfoText()
130 int DbWindowInfoText::
133 gui->info_text_enable = get_value();
134 if( !gui->info_text_enable ) gui->title_text->update(1);
140 DbWindowMatchCase(DbWindowGUI *gui, int x, int y)
141 : BC_CheckBox(x, y, &gui->match_case_enable, _("match case"))
146 DbWindowMatchCase::~DbWindowMatchCase()
150 int DbWindowMatchCase::
153 gui->match_case_enable = get_value();
159 DbWindowText(DbWindowGUI *gui, int x, int y, int w)
160 : BC_TextBox(x, y, w, 1, "")
165 DbWindowText::~DbWindowText()
179 switch(get_keypress())
182 gui->search(MAX_SEARCH, get_text());
186 return BC_TextBox::keypress_event();
191 DbWindowScan(MWindow *mwindow)
192 : BC_MenuItem(_("Media DB"), _("Shift-M"), 'M')
195 this->mwindow = mwindow;
198 DbWindowScan::~DbWindowScan()
205 mwindow->commit_commercial();
206 mwindow->gui->db_window->start();
211 DbWindowStart(DbWindowGUI *gui, int x, int y)
212 : BC_GenericButton(x, y, _("Search"))
217 DbWindowStart::~DbWindowStart()
224 gui->search(MAX_SEARCH,"");
228 DbWindowDeleteItems::
229 DbWindowDeleteItems(DbWindowGUI *gui, int x, int y)
230 : BC_GenericButton(x, y, _("Delete"))
235 DbWindowDeleteItems::~DbWindowDeleteItems()
239 int DbWindowDeleteItems::
242 gui->search_list->stop_view_popup();
249 DbWindowCancel(DbWindowGUI *gui, int x, int y)
250 : BC_CancelButton(x, y)
255 DbWindowCancel::~DbWindowCancel()
268 DbWindowList(DbWindowGUI *gui, int x, int y, int w, int h)
269 : BC_ListBox(x, y, w, h, LISTBOX_TEXT, &gui->search_items[0],
270 &gui->search_column_titles[0], &gui->search_column_widths[0],
271 sizeof_col, 0, 0, LISTBOX_MULTIPLE)
274 this->thread = gui->ticon_thread;
275 this->view_popup = 0;
277 view_ticon = new DbWindowTIcon(gui, &DbWindowTIcon::draw_popup);
278 set_sort_column(gui->sort_column);
279 set_sort_order(gui->sort_order);
280 set_allow_drag_column(1);
283 DbWindowList::~DbWindowList()
298 if( !view_popup ) return 0;
299 BC_Popup *vp = view_popup;
309 switch(get_keypress()) {
311 if( stop_view_popup() ) return 1;
314 gui->del_items->handle_event();
323 gui->stop_drawing(1);
324 gui->sort_events(get_sort_column(), get_sort_order());
325 gui->start_drawing(1);
332 gui->stop_drawing(1);
333 gui->move_column(get_from_column(), get_to_column());
334 gui->start_drawing(1);
338 int DbWindowList::update_images()
340 thread->t_heap.remove_all();
343 thread->t_heap.append(view_ticon);
346 int i = get_first_visible();
348 while( --k >= 0 && gui->search_columns[k] != col_ticon );
349 if( k >= 0 && i >= 0 ) {
350 int sz = gui->search_results.size();
351 int last = get_last_visible();
352 if( last < sz ) sz = last+1;
353 for( int n=0; i<sz; ++i, ++n ) {
354 BC_ListBoxItem *item = gui->search_items[k][i];
355 int x = item->get_text_x() - get_xposition() + 7;
356 int y = item->get_text_y() + get_title_h() - get_yposition() + 5;
357 DbWindowTIcon *ticon = thread->get_ticon(n);
358 ticon->update_image(gui->search_results[i]->id, x, y);
364 int DbWindowList::draw_images()
366 DbWindowTIconThread *thread = gui->ticon_thread;
367 thread->image_update = 1;
368 thread->start_drawing();
375 BC_ListBox::update(gui->search_items, &gui->search_column_titles[0],
376 &gui->search_column_widths[0], sizeof_col);
385 int pady = BC_TextBox::calculate_h(this, MEDIUMFONT, 0, 1) + 5;
386 int padx = BC_Title::calculate_w(this, (char*)"X", MEDIUMFONT);
387 int x = padx/2, y = pady/4;
388 text_x = x; text_y = y;
389 BC_Title *title = new BC_Title(text_x, text_y, _("Text:"), MEDIUMFONT, YELLOW);
390 add_subwindow(title); x += title->get_w();
391 search_text = new DbWindowText(this, x, y, get_w()-x-10);
392 add_subwindow(search_text);
393 x = padx; y += pady + 5;
394 title_text = new DbWindowTitleText(this, x, y);
395 add_subwindow(title_text); x += title_text->get_w() + padx;
396 info_text = new DbWindowInfoText(this, x, y);
397 add_subwindow(info_text); x += title_text->get_w() + padx;
398 match_case = new DbWindowMatchCase(this, x, y);
399 add_subwindow(match_case); x += match_case->get_w() + padx;
400 x = padx; y += pady + 5;
402 search_y = get_h() - DbWindowStart::calculate_h() - 10;
403 search_start = new DbWindowStart(this, search_x, search_y);
404 add_subwindow(search_start);
405 del_items_x = search_x + DbWindowStart::calculate_w(this, search_start->get_text()) + 15;
406 del_items_y = search_y;
407 del_items = new DbWindowDeleteItems(this, del_items_x, del_items_y);
408 add_subwindow(del_items);
409 cancel_w = DbWindowCancel::calculate_w();
410 cancel_h = DbWindowCancel::calculate_h();
411 cancel_x = get_w() - cancel_w - 10;
412 cancel_y = get_h() - cancel_h - 10;
413 cancel = new DbWindowCancel(this, cancel_x, cancel_y);
414 add_subwindow(cancel);
415 ticon_thread = new DbWindowTIconThread(this);
416 list_x = x; list_y = y;
417 int list_w = get_w()-10 - list_x;
418 int list_h = min(search_y, cancel_y)-10 - list_y;
419 search_list = new DbWindowList(this, list_x, list_y, list_w, list_h);
420 add_subwindow(search_list);
421 search_list->show_window();
423 canvas_y = search_list->get_title_h();
424 canvas_w = search_list->get_w();
425 canvas_h = search_list->get_h() - canvas_y;
426 canvas = new DbWindowCanvas(this, canvas_x, canvas_y, canvas_w, canvas_h);
427 canvas->use_auxwindow(search_list);
428 canvas->create_objects(0);
429 set_icon(dwindow->mwindow->theme->get_image("record_icon"));
434 DbWindowGUI(DbWindow *dwindow)
435 : BC_Window(_(PROGRAM_NAME ": DbWindow"),
436 dwindow->mwindow->gui->get_abs_cursor_x(1) - 900 / 2,
437 dwindow->mwindow->gui->get_abs_cursor_y(1) - 600 / 2,
440 this->dwindow = dwindow;
446 search_x = search_y = 0;
447 cancel_x = cancel_y = cancel_w = cancel_h = 0;
448 del_items_x = del_items_y = 0;
449 list_x = list_y = list_w = list_h = 0;
450 sort_column = 1; sort_order = 0;
452 title_text_enable = 1;
453 info_text_enable = 1;
454 match_case_enable = 1;
456 search_columns[col_ticon] = col_ticon;
457 search_columns[col_id] = col_id;
458 search_columns[col_length] = col_length;
459 search_columns[col_source] = col_source;
460 search_columns[col_title] = col_title;
461 search_columns[col_start_time] = col_start_time;
462 search_columns[col_access_time] = col_access_time;
463 search_columns[col_access_count] = col_access_count;
464 search_column_titles[col_ticon] = _("ticon");
465 search_column_titles[col_id] = _("Id");
466 search_column_titles[col_length] = _("length");
467 search_column_titles[col_source] = _("Source");
468 search_column_titles[col_title] = _("Title");
469 search_column_titles[col_start_time] = _("Start time");
470 search_column_titles[col_access_time] = _("Access time");
471 search_column_titles[col_access_count] = _("count");
472 search_column_widths[col_ticon] = 90;
473 search_column_widths[col_id] = 60;
474 search_column_widths[col_length] = 80;
475 search_column_widths[col_source] = 50;
476 search_column_widths[col_title] = 160;
477 search_column_widths[col_start_time] = 140;
478 search_column_widths[col_access_time] = 140;
479 search_column_widths[col_access_count] = 60;
481 for( int i=0; i<sizeof_col; ++i )
482 if( i != col_title ) wd += search_column_widths[i];
483 search_column_widths[col_title] = get_w() - wd - 40;
486 DbWindowGUI::~DbWindowGUI()
488 for( int i=0; i<sizeof_col; ++i )
489 search_items[i].remove_all_objects();
495 resize_event(int w, int h)
498 int cancel_x = w - BC_CancelButton::calculate_w() - 10;
499 int cancel_y = h - BC_CancelButton::calculate_h() - 10;
500 cancel->reposition_window(cancel_x, cancel_y);
502 search_y = h - BC_GenericButton::calculate_h() - 10;
503 search_start->reposition_window(search_x, search_y);
504 del_items_x = search_x + DbWindowStart::calculate_w(this, search_start->get_text()) + 15;
505 del_items_y = search_y;
506 del_items->reposition_window(del_items_x,del_items_y);
507 int list_w = w-10 - list_x;
508 int list_h = min(search_y, cancel_y)-10 - list_y;
509 canvas_w = SWIDTH; canvas_h = SHEIGHT;
510 canvas_x = cancel_x - canvas_w - 15;
511 canvas_y = get_h() - canvas_h - 10;
512 canvas->reposition_window(0, canvas_x, canvas_y, canvas_w, canvas_h);
514 // for( int i=0; i<sizeof_col; ++i )
515 // if( i != col_title ) wd += search_column_widths[i];
516 // search_column_widths[col_title] = w - wd - 40;
517 search_list->reposition_window(list_x, list_y, list_w, list_h);
530 stop_drawing(int locked)
532 if( locked ) unlock_window();
533 ticon_thread->stop_drawing();
534 if( locked ) lock_window("DbWindowGUI::");
539 start_drawing(int update)
541 if( update ) ticon_thread->list_update = 1;
542 ticon_thread->start_drawing();
546 int DbWindowGUI::search_string(const char *text, const char *sp)
549 int n = strlen(text);
550 for( const char *cp=sp; *cp!=0; ++cp ) {
551 if( match_case_enable ? !strncmp(text, cp, n) :
552 !strncasecmp(text, cp, n) ) return 1;
558 void DbWindowGUI::search_clips(MediaDb *mdb, int n, const char *text)
560 //Db::write_blocked by(mdb->db.Clip_set);
561 if( !mdb->clips_first_id() ) do {
562 if( (title_text_enable && search_string(text, mdb->clip_title())) ||
563 (info_text_enable && search_string(text, mdb->clip_path())) ) {
564 int id = mdb->clip_id();
565 double system_time = mdb->clip_system_time();
566 double start_time = 0;
567 if( system_time > 0 )
568 start_time = system_time + mdb->clip_position();
569 double access_time = 0; int access_count = 0;
570 if( !mdb->views_clip_id(id) ) {
571 access_time = mdb->views_access_time();
572 access_count = mdb->views_access_count();
574 double length = mdb->clip_frames() / mdb->clip_framerate();
575 search_results.append(new DbWindowItem(id, mdb->clip_title(),
576 mdb->clip_path(), length, start_time, access_time, access_count));
578 } while( --n >= 0 && !mdb->clips_next_id() );
581 void DbWindowGUI::search(int n, const char *text)
584 search_results.remove_all();
585 DbWindow::MDb *mdb = dwindow->mdb;
586 if( !mdb->attach_rd() ) {
587 search_clips(mdb, n, text);
593 int DbWindowGUI::delete_selection(MediaDb *mdb)
596 for( int k=0; k<search_results.size(); ++k ) {
597 if( !search_items[0][k]->get_selected() ) continue;
598 int id = search_results[k]->id;
599 if( mdb->del_clip_set(id) ) {
600 printf(_("failed delete clip id %d\n"),id);
603 search_results.remove_object_number(k);
604 for( int i=0; i<sizeof_col; ++i )
605 search_items[i].remove_object_number(k);
608 if( n > 0 ) mdb->commitDb();
612 void DbWindowGUI::delete_items()
615 DbWindow::MDb *mdb = dwindow->mdb;
616 if( !mdb->attach_wr() ) {
617 delete_selection(mdb);
627 for( int i=0; i<sizeof_col; ++i )
628 search_items[i].remove_all_objects();
630 char text[BCTEXTLEN];
631 int n = search_results.size();
632 for( int i=0; i<n; ++i ) {
633 DbWindowItem *item = search_results[i];
634 for( int k=0; k<sizeof_col; ++k ) {
635 const char *cp = 0; text[0] = 0;
636 switch( search_columns[k] ) {
641 sprintf(text,"%4d", item->id);
645 sprintf(text, "%8.3f", item->length);
654 case col_start_time: {
655 time_t st = item->start_time;
657 struct tm stm; localtime_r(&st,&stm);
658 sprintf(text,"%02d:%02d:%02d %02d/%02d/%02d",
659 stm.tm_hour, stm.tm_min, stm.tm_sec,
660 stm.tm_year%100, stm.tm_mon, stm.tm_mday);
664 case col_access_time: {
665 time_t at = item->access_time;
667 struct tm atm; localtime_r(&at,&atm);
668 sprintf(text,"%02d/%02d/%02d %02d:%02d:%02d",
669 atm.tm_year%100, atm.tm_mon, atm.tm_mday,
670 atm.tm_hour, atm.tm_min, atm.tm_sec);
674 case col_access_count: {
675 sprintf(text,"%4d", item->access_count);
680 BC_ListBoxItem *item = new BC_ListBoxItem(cp, LTYELLOW);
681 if( search_columns[k] == col_ticon ) {
682 item->set_text_w(SWIDTH+10);
683 item->set_text_h(SHEIGHT+5);
684 item->set_searchable(0);
686 search_items[k].append(item);
690 search_list->update();
695 DbWindowItem(int id, const char *source, const char *title,
696 double length, double start_time,
697 double access_time, int access_count)
700 if( !source ) source = "";
701 this->source = new char[strlen(source)+1];
702 strcpy(this->source,source);
703 if( !title ) title = "";
704 this->title = new char[strlen(title)+1];
705 strcpy(this->title,title);
706 this->length = length;
707 this->start_time = start_time;
708 this->access_time = access_time;
709 this->access_count = access_count;
719 #define CmprFn(nm,key) int DbWindowGUI:: \
720 cmpr_##nm(const void *a, const void *b) { \
721 DbWindowItem *&ap = *(DbWindowItem **)a; \
722 DbWindowItem *&bp = *(DbWindowItem **)b; \
723 int n = key; if( !n ) n = ap->no-bp->no; \
727 extern long timezone;
729 CmprFn(id_dn, ap->id - bp->id)
730 CmprFn(id_up, bp->id - ap->id)
731 CmprFn(length_dn, ap->length - bp->length)
732 CmprFn(length_up, bp->length - ap->length)
733 CmprFn(Source_dn, strcasecmp(ap->source, bp->source))
734 CmprFn(source_dn, strcmp(ap->source, bp->source))
735 CmprFn(Source_up, strcasecmp(bp->source, ap->source))
736 CmprFn(source_up, strcmp(bp->source, ap->source))
737 CmprFn(Title_dn, strcasecmp(ap->title, bp->title))
738 CmprFn(title_dn, strcmp(ap->title, bp->title))
739 CmprFn(Title_up, strcasecmp(bp->title, ap->title))
740 CmprFn(title_up, strcmp(bp->title, ap->title))
741 CmprFn(start_time_dn, fmod(ap->start_time-timezone,24*3600) - fmod(bp->start_time-timezone,24*3600))
742 CmprFn(start_time_up, fmod(bp->start_time-timezone,24*3600) - fmod(ap->start_time-timezone,24*3600))
743 CmprFn(access_time_dn, ap->access_time - bp->access_time)
744 CmprFn(access_time_up, bp->access_time - ap->access_time)
745 CmprFn(access_count_dn, ap->access_count - bp->access_count)
746 CmprFn(access_count_up, bp->access_count - ap->access_count)
750 sort_events(int column, int order)
752 sort_column = column; sort_order = order;
753 if( search_columns[sort_column] == col_ticon ) return;
754 int n = search_results.size();
756 DbWindowItem **items = &search_results[0];
757 for( int i=0; i<n; ++i ) items[i]->no = i;
759 int(*cmpr)(const void *, const void *) = 0;
760 switch( search_columns[sort_column] ) {
762 cmpr = sort_order ? cmpr_id_up : cmpr_id_dn;
765 cmpr = sort_order ? cmpr_length_up : cmpr_length_dn;
768 cmpr = match_case_enable ?
769 (sort_order ? cmpr_Source_up : cmpr_Source_dn) :
770 (sort_order ? cmpr_source_up : cmpr_source_dn) ;
773 cmpr = match_case_enable ?
774 (sort_order ? cmpr_Title_up : cmpr_Title_dn) :
775 (sort_order ? cmpr_title_up : cmpr_title_dn) ;
778 cmpr = sort_order ? cmpr_start_time_up : cmpr_start_time_dn;
780 case col_access_time:
781 cmpr = sort_order ? cmpr_access_time_up : cmpr_access_time_dn;
783 case col_access_count:
784 cmpr = sort_order ? cmpr_access_count_up : cmpr_access_count_dn;
788 if( cmpr ) qsort(items, n, sizeof(*items), cmpr);
792 move_column(int src, int dst)
794 if( src == dst ) return;
795 int src_column = search_columns[src];
796 const char *src_column_title = search_column_titles[src];
797 int src_column_width = search_column_widths[src];
799 for( int i=src; i<dst; ++i ) {
800 search_columns[i] = search_columns[i+1];
801 search_column_titles[i] = search_column_titles[i+1];
802 search_column_widths[i] = search_column_widths[i+1];
806 for( int i=src; i>dst; --i ) {
807 search_columns[i] = search_columns[i-1];
808 search_column_titles[i] = search_column_titles[i-1];
809 search_column_widths[i] = search_column_widths[i-1];
812 search_columns[dst] = src_column;
813 search_column_titles[dst] = src_column_title;
814 search_column_widths[dst] = src_column_width;
816 while( --k >= 0 && search_columns[k] != col_ticon );
817 if( k >= 0 ) search_list->set_master_column(k,0);
822 DbWindowCanvas(DbWindowGUI *gui, int x, int y, int w, int h)
823 : Canvas(gui->dwindow->mwindow, gui, x, y, w, h, w, h, 0)
826 this->is_fullscreen = 0;
834 void DbWindowCanvas::
837 BC_WindowBase* wdw = get_canvas();
838 wdw->lock_window("DbWindowCanvas::flash_canvas");
840 wdw->unlock_window();
843 void DbWindowCanvas::
844 draw_frame(VFrame *frame, int x, int y, int w, int h)
846 BC_WindowBase* wdw = get_canvas();
847 int min_y = gui->search_list->get_title_h();
848 int max_y = gui->search_list->get_view_h()+min_y;
849 min_y += 2; max_y -= 2;
850 int sx = 0, sy = 0, sw = frame->get_w(), sh = frame->get_h();
852 if( dy > 0 ) { sy += dy; y = min_y; sh -= dy; h -= dy; }
854 if( dy > 0 ) { sh -= dy; h -= dy; }
857 //wdw->lock_window("DbWindowCanvas::draw_frame");
858 wdw->draw_vframe(frame, x,y,w,(h&~1), sx,sy,sw,sh, 0);
859 //wdw->unlock_window();
864 DbWindowTIconThread::
865 DbWindowTIconThread(DbWindowGUI *gui)
869 mdb = gui->dwindow->mdb;
871 ticon_lock = new Mutex("DbWindowTIconThread::ticon_lock");
872 draw_lock = new Condition(0, "DbWindowTIconThread::draw_lock", 0);
873 stop_lock = new Condition(0, "DbWindowTIconThread::stop_lock", 0);
875 done = 0; interrupted = 1;
876 list_update = image_update = 0;
880 DbWindowTIconThread::
881 ~DbWindowTIconThread()
886 if( Thread::running() ) {
892 ticons.remove_all_objects();
897 void DbWindowTIconThread::start_drawing()
905 void DbWindowTIconThread::stop_drawing()
909 stop_lock->lock("DbWindowTIconThread::stop_draw");
915 DbWindowTIcon(DbWindowGUI *gui, int (DbWindowTIcon::*draw)() )
920 swidth = (SWIDTH+1) & ~1;
921 sheight = (SHEIGHT+1) & ~1;
922 frame = new VFrame(swidth, sheight, BC_YUV420P);
923 memset(frame->get_y(),0,swidth * sheight);
924 memset(frame->get_u(),0x80,swidth/2 * sheight/2);
925 memset(frame->get_v(),0x80,swidth/2 * sheight/2);
926 clip_id = -1; clip_size = 0;
927 frame_id = frames = -1;
929 prefix_size = suffix_offset = -1;
930 framerate = frame_period = 0;
941 update_image(int clip_id, int x, int y)
943 DbWindowTIconThread *thread = gui->ticon_thread;
944 DbWindow::MDb *mdb = gui->dwindow->mdb;
945 if( !mdb->attach_rd() ) {
946 if( !mdb->clip_id(clip_id) ) {
947 this->clip_id = clip_id;
948 this->x = x; this->y = y;
949 this->clip_size = mdb->clip_size();;
950 this->prefix_size = mdb->clip_prefix_size();
951 this->suffix_offset = mdb->clip_frames() - clip_size;
952 this->framerate = mdb->clip_framerate();;
953 this->frame_period = 1000. / framerate;
954 thread->add_ticon(this, 0);
963 int ret, no = seq_no++;
964 if( seq_no >= clip_size ) seq_no = 0;
965 DbWindow::MDb *mdb = gui->dwindow->mdb;
966 if( !mdb->attach_rd() ) {
967 if( !no ) frame_id = -1;
968 else if( no >= prefix_size ) no += suffix_offset;
969 if( !(ret=mdb->get_sequences(clip_id, no)) ) {
970 if( mdb->timeline_sequence_no() == no )
971 frame_id = mdb->timeline_frame_id();
972 uint8_t *yp = frame->get_y();
973 if( frame_id >= 0 ) {
975 ret = mdb->get_image(frame_id, yp, sw, sh);
978 memset(yp,0,swidth*sheight);
980 else if( no > 0 ) ret = 0;
989 gui->canvas->draw_frame(frame, x, y, swidth, sheight);
996 BC_Popup *vpopup = gui->search_list->view_popup;
997 if( !vpopup ) return 1;
998 vpopup->lock_window("DbWindowTIcon::draw_popup");
999 vpopup->draw_vframe(frame, 0,0,vpopup->get_w(),vpopup->get_h(), 0,0,swidth,sheight, 0);
1001 vpopup->unlock_window();
1005 DbWindowTIcon *DbWindowTIconThread::get_ticon(int i)
1007 while( i >= ticons.size() ) {
1008 DbWindowTIcon *ticon = new DbWindowTIcon(gui, &DbWindowTIcon::draw_frame);
1009 ticons.append(ticon);
1014 DbWindowTIcon *DbWindowTIconThread::low_ticon()
1016 mLock by(ticon_lock);
1017 int sz = t_heap.size();
1019 DbWindowTIcon *ticon = t_heap[0];
1021 for( int k; (k=2*(i+1)) < sz; i=k ) {
1022 if( t_heap[k]->age > t_heap[k-1]->age ) --k;
1023 t_heap[i] = t_heap[k];
1025 DbWindowTIcon *last = t_heap[--sz];
1026 t_heap.remove_number(sz);
1027 double age = last->age;
1028 for( int k; i>0 && age<t_heap[k=(i-1)/2]->age; i=k )
1029 t_heap[i] = t_heap[k];
1034 void DbWindowTIconThread::add_ticon(DbWindowTIcon *ticon, double age)
1036 mLock by(ticon_lock);
1038 int i = t_heap.size(); t_heap.append(ticon);
1039 for( int k; i>0 && age<t_heap[(k=(i-1)/2)]->age; i=k )
1040 t_heap[i] = t_heap[k];
1047 gui->stop_drawing(1);
1050 int idx = get_selection_number(0, 0);
1051 if( idx >= 0 && get_selection_number(0, 1) < 0 ) {
1052 if( view_idx != idx ) {
1054 BC_ListBoxItem *item = gui->search_items[0][idx];
1055 int x = item->get_text_x() - get_xposition();
1056 int y = item->get_text_y() + get_title_h() - get_yposition();
1057 int w = 4*SWIDTH, h = 4*SHEIGHT;
1058 x += gui->get_x() - 2*SWIDTH;
1059 y += gui->get_y() - 4*SHEIGHT;
1060 view_popup = new BC_Popup(this, x, y, w, h, BLACK);
1061 view_ticon->update_image(gui->search_results[idx]->id, 0, 0);
1066 gui->start_drawing(0);
1070 void DbWindowTIconThread::
1075 draw_lock->lock("DbWindowTIcon::run");
1078 int64_t last_flash = 0;
1079 while( !interrupted && !done ) {
1081 gui->lock_window("DbWindowTIconThread::run");
1086 if( image_update ) {
1088 gui->search_list->update_images();
1090 do_flash = 0; last_flash = 0;
1093 gui->unlock_window();
1094 DbWindowTIcon *ticon = low_ticon();
1095 if( !ticon ) interrupted = 1;
1096 if( interrupted ) break;
1097 int64_t past = timer->get_difference();
1098 int64_t delay = ticon->age - past;
1099 //printf("delay %6ld clip %3d seq %d\n",delay,ticon->clip_id, ticon->seq_no);
1101 if( !ticon->get_seq_frame() ) ticon->draw_image();
1102 period = !ticon->seq_no ? 2000 : ticon->frame_period;
1103 if( past > last_flash + 100 ) do_flash = 1;
1110 gui->canvas->flash_canvas();
1112 add_ticon(ticon, ticon->age + period);
1114 Timer::delay(delay > 333 ? 333 : delay);
1116 stop_lock->unlock();
1119 t_heap.remove_all();
1120 ticons.remove_all_objects();