diff --git a/src/bin/empc.c b/src/bin/empc.c index 8a7ffeb..dc8585c 100644 --- a/src/bin/empc.c +++ b/src/bin/empc.c @@ -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);