handle incremental queue version updating in the ui

this removes a number of workarounds related to deleting items from the queue
and significantly improves ui responsiveness when editing the queue

ref T3147
This commit is contained in:
Mike Blumenkrantz 2016-02-08 11:52:46 -05:00
parent 86f5a0324e
commit 39bc858b20
1 changed files with 119 additions and 84 deletions

View File

@ -32,7 +32,6 @@ static unsigned int empd_port;
static Eldbus_Pending *config_call;
static int empd_state = 0;
static int noclear = 0;
static Evas_Object *win = NULL;
static Evas_Object *bg[2] = {NULL};
@ -113,7 +112,7 @@ static size_t empc_module_size[EMPC_MODULE_TYPE_LAST] =
static void queue_list_header_image(void *data, Empc_Fetch_Request *req, Evas_Object *obj);
static void filesystem_base(Eldbus_Proxy *proxy, void *data, Eldbus_Pending *pending, Eldbus_Error_Info *error, Eina_Value *args);
static void filesystem_item_image(void *data, Empc_Fetch_Request *req, Evas_Object *obj);
static void queue_list_handler(Eina_Value *value, Eina_Bool cached);
static void queue_list_handler(Eina_Value *value, Eina_Bool update);
static void filesystem_next(void *data, Evas_Object *obj, void *event_info);
static void filesystem_prev(void);
static Evas_Object *filesystem_new(const char *uri);
@ -1864,7 +1863,7 @@ static void
queue_list_cached(Eldbus_Proxy *proxy EINA_UNUSED, void *data, Eldbus_Pending *pending EINA_UNUSED, Eldbus_Error_Info *error EINA_UNUSED, Eina_Value *value)
{
if (value)
queue_list_handler(value, EINA_TRUE);
queue_list_handler(value, EINA_FALSE);
if ((empd_songid == -1) && ((long)data == -1))
empd_empdd_status_call(empd_proxy);
}
@ -2170,23 +2169,16 @@ queue_list_item_realize(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, vo
static void
queue_list_delete_list(const Eina_List *items)
{
Eina_List *l, *headers = NULL;
Eina_List *l;
int start = -1, num = 0, total = 0;
Elm_Object_Item *it, *next, *hdr = NULL;
Elm_Object_Item *it, *next;
Eina_Bool del_playing = EINA_FALSE;
Empd_Empdd_Song *so;
unsigned int sub = 0;
if (!items) return;
l = eina_list_sort(eina_list_clone(items), 0, (Eina_Compare_Cb)queue_list_sort);
EINA_LIST_FREE(l, it)
{
if (hdr != elm_genlist_item_parent_get(it))
{
hdr = elm_genlist_item_parent_get(it);
headers = eina_list_append(headers, hdr);
sub = elm_genlist_item_subitems_count(hdr);
}
/* check for contiguous selection */
so = elm_object_item_data_get(it);
if (start == -1)
@ -2205,18 +2197,10 @@ queue_list_delete_list(const Eina_List *items)
start = -1, num = 0;
if (!del_playing)
total += num;
if (!sub)
headers = eina_list_remove(headers, hdr);
}
else
num++, sub--;
elm_object_item_del(it);
num++;
}
noclear++;
if (!sub)
headers = eina_list_remove(headers, hdr);
EINA_LIST_FREE(headers, hdr)
elm_genlist_item_fields_update(hdr, EMPC_TEXT_TIME, ELM_GENLIST_ITEM_FIELD_TEXT);
if (!num) return;
empd_empdd_delete_list_range_call(empd_proxy, start, num - 1);
if ((!del_playing) || (empd_state != MPD_STATE_PLAY)) return;
@ -2236,7 +2220,7 @@ static void
queue_list_delete_inverted(void)
{
const Eina_List *items;
Eina_List *l, *headers = NULL;
Eina_List *l;
int start = -1;
Elm_Object_Item *it, *prev, *next, *hdr = NULL;
int del_playing = -1;
@ -2265,10 +2249,7 @@ queue_list_delete_inverted(void)
EINA_LIST_FREE(l, it)
{
if (hdr != elm_genlist_item_parent_get(it))
{
hdr = elm_genlist_item_parent_get(it);
headers = eina_list_append(headers, hdr);
}
hdr = elm_genlist_item_parent_get(it);
next = elm_genlist_item_next_get(it);
prev = elm_genlist_item_prev_get(it);
so = elm_object_item_data_get(next);
@ -2299,8 +2280,6 @@ queue_list_delete_inverted(void)
start = -1;
}
}
EINA_LIST_FREE(headers, hdr)
elm_genlist_item_fields_update(hdr, EMPC_TEXT_TIME, ELM_GENLIST_ITEM_FIELD_TEXT);
if (start == -1) return;
empd_empdd_delete_list_range_call(empd_proxy, start, -1);
if ((!del_playing) || (empd_state != MPD_STATE_PLAY)) return;
@ -2692,25 +2671,24 @@ queue_list_find_insert_point(Empd_Empdd_Song *so)
Elm_Object_Item *it, *itp;
Empd_Empdd_Song *soi;
if (!elm_genlist_items_count(queue_list)) return NULL;
if ((unsigned int)so->song_pos > (elm_genlist_items_count(queue_list) / 2))
{
it = elm_genlist_last_item_get(queue_list);
if (!it) return NULL;
do
{
soi = elm_object_item_data_get(it);
if (so->song_pos > soi->song_pos) return it;
if (so->song_pos >= soi->song_pos) return it;
it = elm_genlist_item_prev_get(it);
} while (it);
return NULL;
}
itp = it = elm_genlist_first_item_get(queue_list);
if (!it) return NULL;
do
{
soi = elm_object_item_data_get(it);
if (so->song_pos < soi->song_pos) return itp;
if (so->song_pos <= soi->song_pos) return itp;
itp = it;
it = elm_genlist_item_next_get(it);
} while (it);
@ -2785,15 +2763,12 @@ queue_list_item_unselect(void *data EINA_UNUSED, Evas_Object *obj, void *event_i
}
static void
queue_list_handler(Eina_Value *value, Eina_Bool cached)
queue_list_handler(Eina_Value *value, Eina_Bool update)
{
Empd_Array_Songs *songs = NULL;
Empd_Empdd_Song *so;
const char *album = NULL, *artist = NULL;
Elm_Object_Item *itl = NULL, *ith = NULL;
int x, y, w, h;
Eina_Bool reset = EINA_FALSE;
Eina_List *sel = NULL;
static Elm_Genlist_Item_Class queue_itc = {
.item_style = "default",
.func = {
@ -2817,57 +2792,110 @@ queue_list_handler(Eina_Value *value, Eina_Bool cached)
EINA_LOG_ERR("conversion failure");
return;
}
if ((!cached) && (!noclear))
if (update && songs->songs)
{
Elm_Object_Item *it;
const Eina_List *l, *its = elm_genlist_selected_items_get(queue_list);
elm_scroller_region_get(queue_list, &x, &y, &w, &h);
if (its)
Elm_Object_Item *insert;
Empd_Empdd_Song *exist;
so = eina_list_data_get(songs->songs);
/* find existing song with first updated song's id */
insert = eina_hash_find(empd_current_queue, &so->songid);
if (insert)
{
EINA_LIST_FOREACH(its, l, it)
sel = eina_list_append(sel, Empd_Empdd_Song_copy(elm_object_item_data_get(it)));
exist = elm_object_item_data_get(insert);
if (exist->song_pos > so->song_pos)
{
/* songs removed before existing item:
* - remove items until exist has target position
*/
int target = so->song_pos;
Elm_Object_Item *prev, *next = insert;
do
{
insert = elm_genlist_item_prev_get(next);
if (elm_genlist_item_subitems_count(insert))
insert = elm_genlist_item_prev_get(insert);
if (!insert) break;
exist = elm_object_item_data_get(insert);
if (exist->song_pos < target) break;
elm_object_item_del(insert);
} while (insert);
prev = elm_genlist_item_prev_get(next);
if (prev)
{
Elm_Object_Item *parent;
Empd_Empdd_Song *a, *b;
parent = elm_genlist_item_parent_get(next);
a = elm_object_item_data_get(prev);
b = elm_object_item_data_get(parent);
/* check whether the previous album can be merged with the next one */
if ((a->artist == b->artist) && (a->album == b->album) &&
(parent != elm_genlist_item_parent_get(prev)))
elm_object_item_del(parent);
}
}
}
}
else if (update)
{
while ((unsigned int)eina_hash_population(empd_current_queue) > empd_queue_length)
{
Elm_Object_Item *it;
/* skip header item... */
it = elm_genlist_item_prev_get(elm_genlist_last_item_get(queue_list));
elm_object_item_del(it);
}
queue_list_clear();
reset = EINA_TRUE;
}
EINA_LIST_FREE(songs->songs, so)
{
Elm_Object_Item *it = NULL;
Empd_Empdd_Song *sop;
if (cached || noclear)
it = eina_hash_find(empd_current_queue, &so->songid);
if (it)
{
it = eina_hash_find(empd_current_queue, &so->songid);
if (it)
Empd_Empdd_Song *ss = elm_object_item_data_get(it);
if (Empd_Empdd_Song_eq(so, ss))
{
Empd_Empdd_Song *ss = elm_object_item_data_get(it);
if (Empd_Empdd_Song_eq(so, ss))
Empd_Empdd_Song_free(so);
so = ss;
}
else
{
Elm_Object_Item *parent;
parent = elm_genlist_item_parent_get(it);
sop = elm_object_item_data_get(parent);
if (Empd_Empdd_Song_eq(sop, ss))
{
Empd_Empdd_Song_free(so);
so = ss;
Empd_Empdd_Song_free(sop);
elm_object_item_data_set(parent, Empd_Empdd_Song_copy(so));
elm_genlist_item_update(parent);
}
else
Empd_Empdd_Song_free(ss);
elm_object_item_data_set(it, so);
elm_genlist_item_update(it);
if (so->songid == empd_songid)
{
Empd_Empdd_Song_free(ss);
elm_object_item_data_set(it, so);
elm_genlist_item_update(it);
if (so->songid == empd_songid)
if ((so->track != empd_song_track) || (empd_song_title != so->title))
{
if ((so->track != empd_song_track) || (empd_song_title != so->title))
{
empd_song_track = so->track;
eina_stringshare_refplace(&empd_song_title, so->title);
title_text_set();
elm_object_tooltip_hide(bg[background_num]);
}
empd_song_track = so->track;
eina_stringshare_refplace(&empd_song_title, so->title);
title_text_set();
elm_object_tooltip_hide(bg[background_num]);
}
}
ith = elm_genlist_item_parent_get(it);
}
ith = elm_genlist_item_parent_get(it);
}
if (!it)
{
Elm_Object_Item *itp = NULL;
Eina_Bool end = EINA_FALSE;
if (((!album) && (!artist)) || (album != so->album) || (artist != so->artist) || (!ith))
{
@ -2882,25 +2910,29 @@ queue_list_handler(Eina_Value *value, Eina_Bool cached)
{
use = EINA_TRUE;
ith = elm_genlist_item_parent_get(itp);
if (!ith) ith = itp, itp = NULL;
}
if (itp && (itp == elm_genlist_last_item_get(queue_list)))
end = EINA_TRUE;
}
}
if (!use)
{
char buf[1024];
if (itp)
ith = elm_genlist_item_insert_after(queue_list, &header_itc, Empd_Empdd_Song_copy(so), NULL, itp, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
else
if (end || (!itp))
ith = elm_genlist_item_append(queue_list, &header_itc, Empd_Empdd_Song_copy(so), NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
else
ith = elm_genlist_item_insert_after(queue_list, &header_itc, Empd_Empdd_Song_copy(so), NULL, itp, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
snprintf(buf, sizeof(buf), "%s:::%s", so->artist, so->album);
//INF("NEW HEADER(%p): %s", ith, buf);
eina_hash_list_append(empd_current_queue_headers, buf, ith);
elm_genlist_item_select_mode_set(ith, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
itp = NULL;
}
}
if (itp)
if (end || (!itp))
it = elm_genlist_item_append(queue_list, &queue_itc, so, ith, ELM_GENLIST_ITEM_NONE, queue_list_item_select, NULL);
else if (itp)
it = elm_genlist_item_insert_after(queue_list, &queue_itc, so, ith, itp, ELM_GENLIST_ITEM_NONE, queue_list_item_select, NULL);
else
it = elm_genlist_item_sorted_insert(queue_list, &queue_itc, so, ith, ELM_GENLIST_ITEM_NONE, (Eina_Compare_Cb)queue_list_sort, queue_list_item_select, NULL);
@ -2931,27 +2963,29 @@ queue_list_handler(Eina_Value *value, Eina_Bool cached)
artist = so->artist;
itl = it;
}
selecting = EINA_TRUE;
EINA_LIST_FREE(sel, so)
{
itl = eina_hash_find(empd_current_queue, &so->songid);
if (itl)
elm_genlist_item_selected_set(itl, EINA_TRUE);
Empd_Empdd_Song_free(so);
}
selecting = EINA_FALSE;
free(songs);
if (noclear)
noclear--;
if (reset)
elm_scroller_region_show(queue_list, x, y, w, h);
}
static Eina_Bool
empc_queue_list(void *d EINA_UNUSED, int t EINA_UNUSED, Empd_Empdd_QueueList_Data *ev)
{
Elm_Object_Item *it;
it = empd_song_item;
queue_list_handler(ev->value, EINA_FALSE);
if (empd_song_item)
if ((!it) || (it != empd_song_item))
elm_genlist_item_show(empd_song_item, ELM_GENLIST_ITEM_SCROLLTO_MIDDLE);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
empc_queue_list_changes(void *d EINA_UNUSED, int t EINA_UNUSED, Empd_Empdd_QueueList_Data *ev)
{
Elm_Object_Item *it;
it = empd_song_item;
queue_list_handler(ev->value, EINA_TRUE);
if ((!it) || (it != empd_song_item))
elm_genlist_item_show(empd_song_item, ELM_GENLIST_ITEM_SCROLLTO_MIDDLE);
return ECORE_CALLBACK_RENEW;
}
@ -3851,6 +3885,7 @@ main(int argc, char *argv[])
E_LIST_HANDLER_APPEND(handlers, EMPD_EMPDD_PERMISSION_FAILED_EVENT, empc_permission_fail, NULL);
E_LIST_HANDLER_APPEND(handlers, EMPD_EMPDD_STATUS_EVENT, empc_status, NULL);
E_LIST_HANDLER_APPEND(handlers, EMPD_EMPDD_QUEUE_LIST_EVENT, empc_queue_list, NULL);
E_LIST_HANDLER_APPEND(handlers, EMPD_EMPDD_QUEUE_CHANGES_META_EVENT, empc_queue_list_changes, NULL);
E_LIST_HANDLER_APPEND(handlers, EMPD_EMPDD_DATABASE_UPDATE_END_EVENT, empc_database_end, NULL);
E_LIST_HANDLER_APPEND(handlers, EMPD_EMPC_BACKGROUND_CHANGED_EVENT, empc_bg_changed, NULL);