prevent popup deactivation while button_down
[goodguy/history.git] / cinelerra-5.0 / cinelerra / dbwindow.C
index 8d026822bd2671761f20a72f2ff495abb63a9880..2a6395cfe24d3a47d6db699d389135bd6c2c1d8f 100644 (file)
@@ -19,6 +19,16 @@ static inline int max(int a,int b) { return a>b ? a : b; }
 
 #define MAX_SEARCH 100
 
+DbSearchItem::DbSearchItem(const char *text, int color)
+ : BC_ListBoxItem(text, color)
+{
+       vicon = 0;
+}
+
+DbSearchItem::~DbSearchItem()
+{
+}
+
 DbWindow::
 DbWindow(MWindow *mwindow)
  : Thread(1, 0, 0)
@@ -87,7 +97,7 @@ run()
        gui->lock_window("DbWindow::run");
        gui->create_objects();
        gui->search(MAX_SEARCH,"");
-       gui->start_drawing();
+       gui->start_drawing(0);
        gui->unlock_window();
        gui->run_window();
        window_lock->lock("DbWindow::stop");
@@ -98,7 +108,7 @@ run()
 
 DbWindowTitleText::
 DbWindowTitleText(DbWindowGUI *gui, int x, int y)
- : BC_CheckBox(x, y, &gui->title_text_enable, "titles")
+ : BC_CheckBox(x, y, &gui->title_text_enable, _("titles"))
 {
        this->gui = gui;
 }
@@ -118,7 +128,7 @@ handle_event()
 
 DbWindowInfoText::
 DbWindowInfoText(DbWindowGUI *gui, int x, int y)
- : BC_CheckBox(x, y, &gui->info_text_enable, "info")
+ : BC_CheckBox(x, y, &gui->info_text_enable, _("info"))
 {
        this->gui = gui;
 }
@@ -138,7 +148,7 @@ handle_event()
 
 DbWindowMatchCase::
 DbWindowMatchCase(DbWindowGUI *gui, int x, int y)
- : BC_CheckBox(x, y, &gui->match_case_enable, "match case")
+ : BC_CheckBox(x, y, &gui->match_case_enable, _("match case"))
 {
        this->gui = gui;
 }
@@ -189,7 +199,7 @@ keypress_event()
 
 DbWindowScan::
 DbWindowScan(MWindow *mwindow)
- : BC_MenuItem("Media DB", "Shift-M", 'M')
+ : BC_MenuItem(_("Media DB"), _("Shift-M"), 'M')
 {
        set_shift();
        this->mwindow = mwindow;
@@ -209,7 +219,7 @@ handle_event()
 
 DbWindowStart::
 DbWindowStart(DbWindowGUI *gui, int x, int y)
- : BC_GenericButton(x, y, "Search")
+ : BC_GenericButton(x, y, _("Search"))
 {
        this->gui = gui;
 }
@@ -227,7 +237,7 @@ handle_event()
 
 DbWindowDeleteItems::
 DbWindowDeleteItems(DbWindowGUI *gui, int x, int y)
- : BC_GenericButton(x, y, "Delete")
+ : BC_GenericButton(x, y, _("Delete"))
 {
        this->gui = gui;
 }
@@ -239,7 +249,7 @@ DbWindowDeleteItems::~DbWindowDeleteItems()
 int DbWindowDeleteItems::
 handle_event()
 {
-       gui->search_list->stop_view_popup();
+       gui->search_list->set_view_popup(0);
        gui->delete_items();
        return 1;
 }
@@ -266,15 +276,12 @@ handle_event()
 
 DbWindowList::
 DbWindowList(DbWindowGUI *gui, int x, int y, int w, int h)
- : BC_ListBox(x, y, w, h, LISTBOX_TEXT, &gui->search_items[0],
+ : BC_ListBox(x, y, w, h, LISTBOX_TEXT,
+       (ArrayList<BC_ListBoxItem*> *) &gui->search_items[0],
        &gui->search_column_titles[0], &gui->search_column_widths[0],
        sizeof_col, 0, 0, LISTBOX_MULTIPLE)
 {
        this->gui = gui;
-       this->thread = gui->ticon_thread;
-       this->view_popup = 0;
-       this->view_idx = -1;
-       view_ticon = new DbWindowTIcon(gui, &DbWindowTIcon::draw_popup);
        set_sort_column(gui->sort_column);
        set_sort_order(gui->sort_order);
        set_allow_drag_column(1);
@@ -282,8 +289,6 @@ DbWindowList(DbWindowGUI *gui, int x, int y, int w, int h)
 
 DbWindowList::~DbWindowList()
 {
-       delete view_ticon;
-       delete view_popup;
 }
 
 int DbWindowList::
@@ -292,15 +297,10 @@ handle_event()
        return 1;
 }
 
-int DbWindowList::
-stop_view_popup()
+void DbWindowList::
+set_view_popup(DbWindowVIcon *vicon)
 {
-       if( !view_popup ) return 0;
-       BC_Popup *vp = view_popup;
-       view_popup = 0;
-       delete vp;
-       view_idx = -1;
-       return 1;
+       gui->vicon_thread->set_view_popup(vicon);
 }
 
 int DbWindowList::
@@ -308,77 +308,199 @@ keypress_event()
 {
        switch(get_keypress()) {
        case ESC:
-               if( stop_view_popup() ) return 1;
+               set_view_popup(0);
                break;
        case DELETE:
                gui->del_items->handle_event();
                break;
+       default:
+               return 0;
        }
-       return 0;
+       return 1;
 }
 
 int DbWindowList::
 sort_order_event()
 {
-       gui->stop_drawing(1);
+       gui->stop_drawing();
        gui->sort_events(get_sort_column(), get_sort_order());
-       gui->start_drawing(1);
+       gui->start_drawing();
        return 1;
 }
 
 int DbWindowList::
 move_column_event()
 {
-       gui->stop_drawing(1);
+       gui->stop_drawing();
        gui->move_column(get_from_column(), get_to_column());
-       gui->start_drawing(1);
+       gui->start_drawing();
        return 1;
 }
 
+DbWindowVIcon::DbWindowVIcon()
+ : VIcon(SWIDTH, SHEIGHT, VICON_RATE)
+{
+       lbox = 0;
+       item = 0;
+}
+
+DbWindowVIcon::~DbWindowVIcon()
+{
+}
+
+DbWindowVIconThread::
+DbWindowVIconThread(DbWindowGUI *gui)
+ : VIconThread(gui->search_list, 4*SWIDTH, 4*SHEIGHT)
+{
+       this->gui = gui;
+       list_update = 0;
+}
+
+DbWindowVIconThread::
+~DbWindowVIconThread()
+{
+       t_heap.remove_all();
+       vicons.remove_all_objects();
+}
+
+DbWindowVIcon *DbWindowVIconThread::get_vicon(int i, DbSearchItem *item)
+{
+        while( i >= vicons.size() ) {
+                DbWindowVIcon *vicon = new DbWindowVIcon();
+                vicons.append(vicon);
+        }
+       DbWindowVIcon *vicon = vicons[i];
+        vicon->lbox = gui->search_list;
+        vicon->item = item;
+       item->vicon = vicon;
+        return vicon;
+}
+
+void DbWindowVIconThread::drawing_started()
+{
+       if( !list_update ) return;
+       list_update = 0;
+       gui->update();
+       gui->search_list->update_images();
+       reset_images();
+}
+
+VFrame *DbWindowVIcon::frame()
+{
+       if( seq_no >= images.size() )
+               load_frames(lbox->gui->dwindow->mdb);
+       return *images[seq_no];
+}
+
+int64_t DbWindowVIcon::set_seq_no(int64_t no)
+{
+       if( no >= clip_size ) no = 0;
+       return seq_no = no;
+}
+
+
+void DbWindowVIcon::load_frames(DbWindow::MDb *mdb)
+{
+       if( !mdb->attach_rd() ) {
+               read_frames(mdb);
+               mdb->detach();
+       }
+}
+
+void DbWindowVIcon::read_frames(DbWindow::MDb *mdb)
+{
+       while( seq_no >= images.size() ) {
+               int no = images.size();
+               if( no >= prefix_size ) no += suffix_offset;
+               if( mdb->get_sequences(clip_id, no) ) continue;
+               if( mdb->timeline_sequence_no() != no ) continue;
+               int frame_id = mdb->timeline_frame_id();
+               if( frame_id < 0 ) continue;
+               int swidth = (SWIDTH+1) & ~1, sheight = (SHEIGHT+1) & ~1;
+               VIFrame *vifrm = new VIFrame(swidth, sheight, BC_YUV420P);
+               VFrame *img = *vifrm;
+               memset(img->get_y(),0x00,swidth * sheight);
+               memset(img->get_u(),0x80,swidth/2 * sheight/2);
+               memset(img->get_v(),0x80,swidth/2 * sheight/2);
+               uint8_t *yp = img->get_y();  int sw = -1, sh = -1;
+               mdb->get_image(frame_id, yp, sw, sh);
+               images.append(vifrm);
+       }
+}
+
+int DbWindowVIcon::get_vx()
+{
+        return lbox->get_item_x(item);
+}
+int DbWindowVIcon::get_vy()
+{
+        return lbox->get_item_y(item);
+}
+
+void DbWindowVIcon::
+update_image(DbWindowGUI *gui, int clip_id)
+{
+       DbWindow::MDb *mdb = gui->dwindow->mdb;
+       if( !mdb->attach_rd() ) {
+               if( !mdb->clip_id(clip_id) ) {
+                       this->clip_id = clip_id;
+                       this->clip_size = mdb->clip_size();;
+                       this->prefix_size = mdb->clip_prefix_size();
+                       this->suffix_offset = mdb->clip_frames() - clip_size;
+                       double framerate = mdb->clip_framerate();
+                       this->frame_rate = framerate > 0 ? framerate : VICON_RATE;
+                       gui->vicon_thread->add_vicon(this);
+               }
+               mdb->detach();
+       }
+}
+
+
 int DbWindowList::update_images()
 {
+       DbWindowVIconThread *thread = gui->vicon_thread;
        thread->t_heap.remove_all();
-       if( view_popup ) {
-               view_ticon->age = 0;
-               thread->t_heap.append(view_ticon);
-       }
 
        int i = get_first_visible();
        int k = sizeof_col;
-       while( --k >= 0 && gui->search_columns[k] != col_ticon );
+       while( --k >= 0 && gui->search_columns[k] != col_vicon );
        if( k >= 0 && i >= 0 ) {
                int sz = gui->search_results.size();
                int last = get_last_visible();
                if( last < sz ) sz = last+1;
                for( int n=0; i<sz; ++i, ++n ) {
-                       BC_ListBoxItem *item = gui->search_items[k][i];
-                       int x = item->get_text_x() - get_xposition() + 7;
-                       int y = item->get_text_y() + get_title_h() - get_yposition() + 5;
-                       DbWindowTIcon *ticon = thread->get_ticon(n);
-                       ticon->update_image(gui->search_results[i]->id, x, y);
+                       DbSearchItem *item = gui->search_items[k][i];
+                       DbWindowVIcon *vicon = thread->get_vicon(n, item);
+                       vicon->update_image(gui, gui->search_results[i]->id);
                }
        }
        return 0;
 }
 
-int DbWindowList::draw_images()
+int DbWindowList::
+update()
 {
-       DbWindowTIconThread *thread = gui->ticon_thread;
-       thread->image_update = 1;
-       thread->start_drawing();
+       BC_ListBox::update((ArrayList<BC_ListBoxItem*>*)gui->search_items,
+                       &gui->search_column_titles[0], &gui->search_column_widths[0],
+                       sizeof_col);
        return 0;
 }
 
 int DbWindowList::
-update()
+selection_changed()
 {
-       BC_ListBox::update(gui->search_items, &gui->search_column_titles[0],
-                       &gui->search_column_widths[0], sizeof_col);
+       gui->stop_drawing();
+       set_view_popup(0);
+       int idx = get_selection_number(0, 0);
+       if( idx >= 0 && get_selection_number(0, 1) < 0 ) {
+               DbSearchItem *item = gui->search_items[0][idx];
+               set_view_popup(item->vicon);
+       }
+       gui->start_drawing(0);
        return 0;
 }
 
 
-
 void DbWindowGUI::
 create_objects()
 {
@@ -386,7 +508,7 @@ create_objects()
        int padx = BC_Title::calculate_w(this, (char*)"X", MEDIUMFONT);
        int x = padx/2, y = pady/4;
        text_x = x;  text_y = y;
-       BC_Title *title = new BC_Title(text_x, text_y, "Text:", MEDIUMFONT, YELLOW);
+       BC_Title *title = new BC_Title(text_x, text_y, _("Text:"), MEDIUMFONT, YELLOW);
        add_subwindow(title);  x += title->get_w();
        search_text = new DbWindowText(this, x, y, get_w()-x-10);
        add_subwindow(search_text);
@@ -412,12 +534,13 @@ create_objects()
        cancel_y = get_h() - cancel_h - 10;
        cancel = new DbWindowCancel(this, cancel_x, cancel_y);
        add_subwindow(cancel);
-       ticon_thread = new DbWindowTIconThread(this);
        list_x = x;  list_y = y;
        int list_w = get_w()-10 - list_x;
        int list_h = min(search_y, cancel_y)-10 - list_y;
        search_list = new DbWindowList(this, list_x, list_y, list_w, list_h);
        add_subwindow(search_list);
+       vicon_thread = new DbWindowVIconThread(this);
+       vicon_thread->start();
        search_list->show_window();
        canvas_x = 0;
        canvas_y = search_list->get_title_h();
@@ -432,7 +555,7 @@ create_objects()
 
 DbWindowGUI::
 DbWindowGUI(DbWindow *dwindow)
- : BC_Window(PROGRAM_NAME ": DbWindow",
+ : BC_Window(_(PROGRAM_NAME ": DbWindow"),
        dwindow->mwindow->gui->get_abs_cursor_x(1) - 900 / 2,
        dwindow->mwindow->gui->get_abs_cursor_y(1) - 600 / 2,
        900, 600, 400, 400)
@@ -453,7 +576,7 @@ DbWindowGUI(DbWindow *dwindow)
        info_text_enable = 1;
        match_case_enable = 1;
 
-       search_columns[col_ticon] = col_ticon;
+       search_columns[col_vicon] = col_vicon;
        search_columns[col_id] = col_id;
        search_columns[col_length] = col_length;
        search_columns[col_source] = col_source;
@@ -461,15 +584,15 @@ DbWindowGUI(DbWindow *dwindow)
        search_columns[col_start_time] = col_start_time;
        search_columns[col_access_time] = col_access_time;
        search_columns[col_access_count] = col_access_count;
-       search_column_titles[col_ticon] = "ticon";
-       search_column_titles[col_id] = "Id";
-       search_column_titles[col_length] = "length";
-       search_column_titles[col_source] = "Source";
-       search_column_titles[col_title] = "Title";
-       search_column_titles[col_start_time] = "Start time";
-       search_column_titles[col_access_time] = "Access time";
-       search_column_titles[col_access_count] = "count";
-       search_column_widths[col_ticon] = 90;
+       search_column_titles[col_vicon] = _("vicon");
+       search_column_titles[col_id] = _("Id");
+       search_column_titles[col_length] = _("length");
+       search_column_titles[col_source] = _("Source");
+       search_column_titles[col_title] = _("Title");
+       search_column_titles[col_start_time] = _("Start time");
+       search_column_titles[col_access_time] = _("Access time");
+       search_column_titles[col_access_count] = _("count");
+       search_column_widths[col_vicon] = 90;
        search_column_widths[col_id] = 60;
        search_column_widths[col_length] = 80;
        search_column_widths[col_source] = 50;
@@ -487,14 +610,14 @@ DbWindowGUI::~DbWindowGUI()
 {
        for( int i=0; i<sizeof_col; ++i )
                search_items[i].remove_all_objects();
-       delete ticon_thread;
+       delete vicon_thread;
        delete canvas;
 }
 
 int DbWindowGUI::
 resize_event(int w, int h)
 {
-       stop_drawing(1);
+       stop_drawing();
        int cancel_x = w - BC_CancelButton::calculate_w() - 10;
        int cancel_y = h - BC_CancelButton::calculate_h() - 10;
        cancel->reposition_window(cancel_x, cancel_y);
@@ -515,7 +638,7 @@ resize_event(int w, int h)
 //             if( i != col_title ) wd += search_column_widths[i];
 //     search_column_widths[col_title] = w - wd - 40;
        search_list->reposition_window(list_x, list_y, list_w, list_h);
-       start_drawing(1);
+       start_drawing();
        return 1;
 }
 
@@ -527,19 +650,18 @@ close_event()
 }
 
 int DbWindowGUI::
-stop_drawing(int locked)
+stop_drawing()
 {
-       if( locked ) unlock_window();
-       ticon_thread->stop_drawing();
-       if( locked ) lock_window("DbWindowGUI::");
+       vicon_thread->stop_drawing();
        return 0;
 }
 
 int DbWindowGUI::
 start_drawing(int update)
 {
-       if( update ) ticon_thread->list_update = 1;
-       ticon_thread->start_drawing();
+       if( update )
+               vicon_thread->list_update = 1;
+       vicon_thread->start_drawing();
        return 0;
 }
 
@@ -580,14 +702,14 @@ void DbWindowGUI::search_clips(MediaDb *mdb, int n, const char *text)
 
 void DbWindowGUI::search(int n, const char *text)
 {
-       stop_drawing(1);
+       stop_drawing();
         search_results.remove_all();
        DbWindow::MDb *mdb = dwindow->mdb;
        if( !mdb->attach_rd() ) {
                search_clips(mdb, n, text);
                mdb->detach();
        }
-       start_drawing(1);
+       start_drawing();
 }
 
 int DbWindowGUI::delete_selection(MediaDb *mdb)
@@ -597,7 +719,7 @@ int DbWindowGUI::delete_selection(MediaDb *mdb)
                if( !search_items[0][k]->get_selected() ) continue;
                int id = search_results[k]->id;
                if( mdb->del_clip_set(id) ) {
-                       printf("failed delete clip id %d\n",id);
+                       printf(_("failed delete clip id %d\n"),id);
                        continue;
                }
                search_results.remove_object_number(k);
@@ -617,7 +739,7 @@ void DbWindowGUI::delete_items()
                delete_selection(mdb);
                mdb->detach();
        }
-       start_drawing(1);
+       start_drawing();
 }
 
 void DbWindowGUI::
@@ -634,7 +756,7 @@ update()
                for( int k=0; k<sizeof_col; ++k ) {
                        const char *cp = 0;  text[0] = 0;
                        switch( search_columns[k] ) {
-                       case col_ticon:
+                       case col_vicon:
                                cp = "";
                                break;
                        case col_id: {
@@ -677,8 +799,8 @@ update()
                                break; }
                        }
                        if( !cp ) continue;
-                       BC_ListBoxItem *item = new BC_ListBoxItem(cp, LTYELLOW);
-                       if( search_columns[k] == col_ticon ) {
+                       DbSearchItem *item = new DbSearchItem(cp, LTYELLOW);
+                       if( search_columns[k] == col_vicon ) {
                                item->set_text_w(SWIDTH+10);
                                item->set_text_h(SHEIGHT+5);
                                item->set_searchable(0);
@@ -750,7 +872,7 @@ void DbWindowGUI::
 sort_events(int column, int order)
 {
        sort_column = column;  sort_order = order;
-       if( search_columns[sort_column] == col_ticon ) return;
+       if( search_columns[sort_column] == col_vicon ) return;
        int n = search_results.size();
        if( !n ) return;
        DbWindowItem **items = &search_results[0];
@@ -813,7 +935,7 @@ move_column(int src, int dst)
        search_column_titles[dst] = src_column_title;
        search_column_widths[dst] = src_column_width;
        int k = sizeof_col;
-       while( --k >= 0 && search_columns[k] != col_ticon );
+       while( --k >= 0 && search_columns[k] != col_vicon );
        if( k >= 0 ) search_list->set_master_column(k,0);
 }
 
@@ -861,264 +983,3 @@ draw_frame(VFrame *frame, int x, int y, int w, int h)
 }
 
 
-DbWindowTIconThread::
-DbWindowTIconThread(DbWindowGUI *gui)
- : Thread(1, 0, 0)
-{
-       this->gui = gui;
-       mdb = gui->dwindow->mdb;
-       mdb->add_user();
-       ticon_lock = new Mutex("DbWindowTIconThread::ticon_lock");
-       draw_lock = new Condition(0, "DbWindowTIconThread::draw_lock", 0);
-       stop_lock = new Condition(0, "DbWindowTIconThread::stop_lock", 0);
-       timer = new Timer();
-       done = 0;  interrupted = 1;
-       list_update = image_update = 0;
-       Thread::start();
-}
-
-DbWindowTIconThread::
-~DbWindowTIconThread()
-{
-       stop_drawing();
-       done = 1;
-       draw_lock->unlock();
-       if( Thread::running() ) {
-               Thread::cancel();
-               Thread::join();
-       }
-       mdb->remove_user();
-       t_heap.remove_all();
-       ticons.remove_all_objects();
-       delete draw_lock;
-       delete stop_lock;
-}
-
-void DbWindowTIconThread::start_drawing()
-{
-        if( interrupted ) {
-               interrupted = 0;
-               draw_lock->unlock();
-       }
-}
-
-void DbWindowTIconThread::stop_drawing()
-{
-        if( !interrupted ) {
-                interrupted = 1;
-                stop_lock->lock("DbWindowTIconThread::stop_draw");
-        }
-}
-
-
-DbWindowTIcon::
-DbWindowTIcon(DbWindowGUI *gui, int (DbWindowTIcon::*draw)() )
-{
-       this->gui = gui;
-       this->draw = draw;
-       age = 0;  x = y = 0;
-        swidth = (SWIDTH+1) & ~1;
-        sheight = (SHEIGHT+1) & ~1;
-       frame = new VFrame(swidth, sheight, BC_YUV420P);
-       memset(frame->get_y(),0,swidth * sheight);
-       memset(frame->get_u(),0x80,swidth/2 * sheight/2);
-       memset(frame->get_v(),0x80,swidth/2 * sheight/2);
-        clip_id = -1;  clip_size = 0;
-        frame_id = frames = -1;
-        seq_no = 0;
-        prefix_size = suffix_offset = -1;
-       framerate = frame_period = 0;
-}
-
-DbWindowTIcon::
-~DbWindowTIcon()
-{
-       delete frame;
-}
-
-
-void DbWindowTIcon::
-update_image(int clip_id, int x, int y)
-{
-       DbWindowTIconThread *thread = gui->ticon_thread;
-       DbWindow::MDb *mdb = gui->dwindow->mdb;
-       if( !mdb->attach_rd() ) {
-               if( !mdb->clip_id(clip_id) ) {
-                       this->clip_id = clip_id;
-                       this->x = x;  this->y = y;
-                       this->clip_size = mdb->clip_size();;
-                       this->prefix_size = mdb->clip_prefix_size();
-                       this->suffix_offset = mdb->clip_frames() - clip_size;
-                       this->framerate = mdb->clip_framerate();;
-                       this->frame_period = 1000. / framerate;
-                       thread->add_ticon(this, 0);
-               }
-               mdb->detach();
-       }
-}
-
-int DbWindowTIcon::
-get_seq_frame()
-{
-       int ret, no = seq_no++;
-       if( seq_no >= clip_size ) seq_no = 0;
-       DbWindow::MDb *mdb = gui->dwindow->mdb;
-       if( !mdb->attach_rd() ) {
-               if( !no ) frame_id = -1;
-               else if( no >= prefix_size ) no += suffix_offset;
-               if( !(ret=mdb->get_sequences(clip_id, no)) ) {
-                       if( mdb->timeline_sequence_no() == no )
-                               frame_id = mdb->timeline_frame_id();
-                       uint8_t *yp = frame->get_y();
-                       if( frame_id >= 0 ) {
-                               int sw, sh;
-                               ret = mdb->get_image(frame_id, yp, sw, sh);
-                       }
-                       else
-                               memset(yp,0,swidth*sheight);
-               }
-               else if( no > 0 ) ret = 0;
-               mdb->detach();
-       }
-       return ret;
-}
-
-int DbWindowTIcon::
-draw_frame()
-{
-       gui->canvas->draw_frame(frame, x, y, swidth, sheight);
-       return 0;
-}
-
-int DbWindowTIcon::
-draw_popup()
-{
-       BC_Popup *vpopup = gui->search_list->view_popup;
-       if( !vpopup ) return 1;
-       vpopup->lock_window("DbWindowTIcon::draw_popup");
-       vpopup->draw_vframe(frame, 0,0,vpopup->get_w(),vpopup->get_h(), 0,0,swidth,sheight, 0);
-       vpopup->flash();
-       vpopup->unlock_window();
-       return 0;
-}
-
-DbWindowTIcon *DbWindowTIconThread::get_ticon(int i)
-{
-       while( i >= ticons.size() ) {
-               DbWindowTIcon *ticon = new DbWindowTIcon(gui, &DbWindowTIcon::draw_frame);
-               ticons.append(ticon);
-       }
-       return ticons[i];
-}
-
-DbWindowTIcon *DbWindowTIconThread::low_ticon()
-{
-       mLock by(ticon_lock);
-       int sz = t_heap.size();
-       if( !sz ) return 0;
-       DbWindowTIcon *ticon = t_heap[0];
-       int i = 0;
-       for( int k; (k=2*(i+1)) < sz; i=k ) {
-               if( t_heap[k]->age > t_heap[k-1]->age ) --k;
-               t_heap[i] = t_heap[k];
-       }
-       DbWindowTIcon *last = t_heap[--sz];
-       t_heap.remove_number(sz);
-       double age = last->age;
-       for( int k; i>0 && age<t_heap[k=(i-1)/2]->age; i=k )
-               t_heap[i] = t_heap[k];
-       t_heap[i] = last;
-       return ticon;
-}
-
-void DbWindowTIconThread::add_ticon(DbWindowTIcon *ticon, double age)
-{
-       mLock by(ticon_lock);
-       ticon->age = age;
-       int i = t_heap.size();  t_heap.append(ticon);
-       for( int k; i>0 && age<t_heap[(k=(i-1)/2)]->age; i=k )
-               t_heap[i] = t_heap[k];
-       t_heap[i] = ticon;
-}
-
-int DbWindowList::
-selection_changed()
-{
-       gui->stop_drawing(1);
-       delete view_popup;
-       view_popup = 0;
-       int idx = get_selection_number(0, 0);
-       if( idx >= 0 && get_selection_number(0, 1) < 0 ) {
-               if( view_idx != idx ) {
-                       view_idx = idx;
-                       BC_ListBoxItem *item = gui->search_items[0][idx];
-                       int x = item->get_text_x() - get_xposition();
-                       int y = item->get_text_y() + get_title_h() - get_yposition();
-                       int w = 4*SWIDTH, h = 4*SHEIGHT;
-                       x += gui->get_x() - 2*SWIDTH;
-                       y += gui->get_y() - 4*SHEIGHT;
-                       view_popup = new BC_Popup(this, x, y, w, h, BLACK);
-                       view_ticon->update_image(gui->search_results[idx]->id, 0, 0);
-               }
-       }
-       else
-               view_idx = -1;
-       gui->start_drawing(0);
-       return 0;
-}
-
-void DbWindowTIconThread::
-run()
-{
-
-       while(!done) {
-               draw_lock->lock("DbWindowTIcon::run");
-               if( done ) break;
-               int do_flash = 0;
-               int64_t last_flash = 0;
-               while( !interrupted && !done ) {
-                       double period = 0;
-                       gui->lock_window("DbWindowTIconThread::run");
-                       if( list_update ) {
-                               list_update = 0;
-                               gui->update();
-                       }
-                       if( image_update ) {
-                               image_update = 0;
-                               gui->search_list->update_images();
-                               timer->update();
-                               do_flash = 0;  last_flash = 0;
-
-                       }
-                       gui->unlock_window();
-                       DbWindowTIcon *ticon = low_ticon();
-                       if( !ticon ) interrupted = 1;
-                       if( interrupted ) break;
-                       int64_t past = timer->get_difference();
-                       int64_t delay = ticon->age - past;
-//printf("delay %6ld  clip %3d  seq %d\n",delay,ticon->clip_id, ticon->seq_no);
-                       if( delay < 10 ) {
-                               if( !ticon->get_seq_frame() ) ticon->draw_image();
-                               period = !ticon->seq_no ? 2000 : ticon->frame_period;
-                               if( past > last_flash + 100 ) do_flash = 1;
-                       }
-                       else
-                               do_flash = 1;
-                       if( do_flash ) {
-                               do_flash = 0;
-                               last_flash = past;
-                               gui->canvas->flash_canvas();
-                       }
-                       add_ticon(ticon, ticon->age + period);
-                       if( delay > 0 )
-                               Timer::delay(delay > 333 ? 333 : delay);
-               }
-               stop_lock->unlock();
-       }
-
-       t_heap.remove_all();
-       ticons.remove_all_objects();
-}
-
-
-