This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch main
in repository eradio.
View the commit online.
commit c90c124aeb0ce7be1626da47b4ffd106edaad34d
Author: politebot <[email protected]>
AuthorDate: Wed Oct 15 16:44:54 2025 -0500
Use genlist for main search result list
---
configure.ac | 2 +-
eradio.spec | 4 +-
src/appdata.h | 2 +-
src/station_list.c | 329 ++++++++++++++++++++++++-----------------------------
src/ui.c | 27 +----
src/ui.h | 2 +-
6 files changed, 161 insertions(+), 205 deletions(-)
diff --git a/configure.ac b/configure.ac
index 0336308..962eb29 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([eradio], [0.0.11], [])
+AC_INIT([eradio], [0.0.12], [])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_PROG_CC
AC_CONFIG_HEADERS([config.h])
diff --git a/eradio.spec b/eradio.spec
index f79c205..ff05471 100644
--- a/eradio.spec
+++ b/eradio.spec
@@ -1,5 +1,5 @@
Name: eradio
-Version: 0.0.11
+Version: 0.0.12
Release: 1%{?dist}
Summary: A simple EFL internet radio player
License: MIT
@@ -44,5 +44,7 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/%{name}.desktop
%doc README.md
%changelog
+* Web Oct 15 2025 1wErt3r <[email protected]> - 0.0.12
+- Use genlist for search results, clear status when clicking stop
* Sun Oct 12 2025 1wErt3r <[email protected]> - 0.0.8
- Initial package release
diff --git a/src/appdata.h b/src/appdata.h
index bced639..362654f 100644
--- a/src/appdata.h
+++ b/src/appdata.h
@@ -34,7 +34,7 @@ typedef struct _AppData
Evas_Object *separator;
Evas_Object *statusbar;
Evas_Object *search_btn;
- Evas_Object *load_more_btn;
+
Evas_Object *search_bar;
Evas_Object *filters_toggle_btn;
Evas_Object *filters_box;
diff --git a/src/station_list.c b/src/station_list.c
index 8b0351a..0a2cef2 100644
--- a/src/station_list.c
+++ b/src/station_list.c
@@ -5,6 +5,90 @@
#include "favorites.h"
#include "ui.h"
+static void _favorite_btn_clicked_cb(void *data, Evas_Object *obj, void *event_info);
+static void _favorite_remove_btn_clicked_cb(void *data, Evas_Object *obj, void *event_info);
+
+static char *
+_gl_text_get(void *data, Evas_Object *obj, const char *part)
+{
+ Station *st = data;
+ return strdup(st->name);
+}
+
+static Evas_Object *
+_gl_content_get(void *data, Evas_Object *obj, const char *part)
+{
+ Station *st = data;
+ AppData *ad = evas_object_data_get(obj, "ad");
+ if (!strcmp(part, "elm.swallow.icon"))
+ {
+ Evas_Object *icon = elm_icon_add(obj);
+ elm_icon_standard_set(icon, "media-playback-start");
+ if (st->favicon && st->favicon[0] && st->stationuuid)
+ {
+ char cache_path[PATH_MAX];
+ const char *home = getenv("HOME");
+ snprintf(cache_path, sizeof(cache_path), "%s/.cache/eradio/favicons/%s", home, st->stationuuid);
+ if (ecore_file_exists(cache_path))
+ {
+ elm_image_file_set(icon, cache_path, NULL);
+ }
+ else
+ {
+ // We can't easily get the list item here to pass to http_download_icon,
+ // so we'll just show the default icon.
+ // A more advanced implementation might trigger the download differently.
+ }
+ }
+ return icon;
+ }
+ else if (!strcmp(part, "elm.swallow.end"))
+ {
+ if (ad->view_mode == VIEW_SEARCH)
+ {
+ Evas_Object *fav_btn = elm_button_add(obj);
+ evas_object_size_hint_min_set(fav_btn, 40, 40);
+ evas_object_propagate_events_set(fav_btn, EINA_FALSE);
+ if (st->favorite)
+ elm_object_text_set(fav_btn, "★");
+ else
+ elm_object_text_set(fav_btn, "☆");
+ evas_object_smart_callback_add(fav_btn, "clicked", _favorite_btn_clicked_cb, st);
+ evas_object_data_set(fav_btn, "ad", ad);
+ return fav_btn;
+ }
+ else if (ad->view_mode == VIEW_FAVORITES)
+ {
+ Evas_Object *fav_btn = elm_button_add(obj);
+ evas_object_size_hint_min_set(fav_btn, 60, 30);
+ evas_object_propagate_events_set(fav_btn, EINA_FALSE);
+ elm_object_text_set(fav_btn, "Remove");
+ evas_object_smart_callback_add(fav_btn, "clicked", _favorite_remove_btn_clicked_cb, st);
+ evas_object_data_set(fav_btn, "ad", ad);
+ return fav_btn;
+ }
+ }
+ return NULL;
+}
+
+static Eina_Bool
+_gl_state_get(void *data, Evas_Object *obj, const char *part)
+{
+ return EINA_FALSE;
+}
+
+static void
+_gl_del(void *data, Evas_Object *obj)
+{
+ // Station data is owned by the ad->stations list, so we don't free it here.
+}
+
+static Elm_Genlist_Item_Class *itc = NULL;
+
+static void _favorite_btn_clicked_cb(void *data, Evas_Object *obj, void *event_info);
+static void _favorite_remove_btn_clicked_cb(void *data, Evas_Object *obj, void *event_info);
+
+
static void _favorite_btn_clicked_cb(void *data, Evas_Object *obj, void *event_info);
static void _favorite_remove_btn_clicked_cb(void *data, Evas_Object *obj, void *event_info);
@@ -17,6 +101,32 @@ _station_click_counter_request(AppData *ad, Station *st)
http_station_click_counter(ad, st->stationuuid);
}
+static void
+_favorite_btn_clicked_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ Station *st = data;
+ AppData *ad = evas_object_data_get(obj, "ad");
+ st->favorite = !st->favorite;
+ favorites_set(ad, st, st->favorite);
+ favorites_save(ad);
+ // Find the genlist item and update it
+ Elm_Object_Item *it = elm_genlist_selected_item_get(ad->list);
+ if (it && elm_object_item_data_get(it) == st)
+ elm_genlist_item_update(it);
+}
+
+static void
+_favorite_remove_btn_clicked_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ Station *st = data;
+ AppData *ad = evas_object_data_get(obj, "ad");
+ st->favorite = EINA_FALSE;
+ favorites_set(ad, st, EINA_FALSE);
+ favorites_save(ad);
+ favorites_rebuild_station_list(ad);
+ station_list_populate_favorites(ad);
+}
+
void
_list_item_selected_cb(void *data, Evas_Object *obj, void *event_info)
{
@@ -37,7 +147,7 @@ _list_item_selected_cb(void *data, Evas_Object *obj, void *event_info)
void
station_list_clear(AppData *ad)
{
- elm_list_clear(ad->list);
+ elm_genlist_clear(ad->list);
}
void
@@ -45,7 +155,16 @@ station_list_populate(AppData *ad, Eina_Bool new_search)
{
Eina_List *l;
Station *st;
- int i = 0;
+
+ if (!itc)
+ {
+ itc = elm_genlist_item_class_new();
+ itc->item_style = "default";
+ itc->func.text_get = _gl_text_get;
+ itc->func.content_get = _gl_content_get;
+ itc->func.state_get = _gl_state_get;
+ itc->func.del = _gl_del;
+ }
if (new_search)
{
@@ -53,135 +172,22 @@ station_list_populate(AppData *ad, Eina_Bool new_search)
ad->displayed_stations_count = 0;
}
- Eina_List *stations_to_display = eina_list_nth_list(ad->stations, ad->displayed_stations_count);
+ evas_object_data_set(ad->list, "ad", ad);
+ Eina_List *stations_to_display = ad->stations;
EINA_LIST_FOREACH(stations_to_display, l, st)
{
- if (i >= 100) break;
-
- Evas_Object *icon = elm_icon_add(ad->win);
- elm_icon_standard_set(icon, "media-playback-start");
-
- Evas_Object *fav_btn = NULL;
- if (ad->view_mode == VIEW_SEARCH)
- {
- fav_btn = elm_button_add(ad->win);
- evas_object_size_hint_min_set(fav_btn, 40, 40);
- evas_object_propagate_events_set(fav_btn, EINA_FALSE);
- if (st->favorite)
- elm_object_text_set(fav_btn, "★");
- else
- elm_object_text_set(fav_btn, "☆");
- }
- else if (ad->view_mode == VIEW_FAVORITES)
- {
- fav_btn = elm_button_add(ad->win);
- evas_object_size_hint_min_set(fav_btn, 60, 30);
- evas_object_propagate_events_set(fav_btn, EINA_FALSE);
- elm_object_text_set(fav_btn, "Remove");
- }
-
- Elm_Object_Item *li = elm_list_item_append(ad->list, st->name, icon, fav_btn, NULL, NULL);
- elm_object_item_data_set(li, st);
-
- // Attach callback only when a button exists
- if (fav_btn)
- {
- typedef struct {
- AppData *ad;
- Elm_Object_Item *li;
- } FavCtx;
- FavCtx *ctx = calloc(1, sizeof(FavCtx));
- ctx->ad = ad;
- ctx->li = li;
- if (ad->view_mode == VIEW_SEARCH)
- evas_object_smart_callback_add(fav_btn, "clicked", _favorite_btn_clicked_cb, ctx);
- else
- evas_object_smart_callback_add(fav_btn, "clicked", _favorite_remove_btn_clicked_cb, ctx);
- }
-
- if (st->favicon && st->favicon[0] && st->stationuuid)
- {
- char cache_path[PATH_MAX];
- const char *home = getenv("HOME");
- snprintf(cache_path, sizeof(cache_path), "%s/.cache/eradio/favicons/%s", home, st->stationuuid);
-
- if (ecore_file_exists(cache_path))
- {
- elm_image_file_set(icon, cache_path, NULL);
- }
- else
- {
- http_download_icon(ad, li, st->favicon);
- }
- }
- i++;
+ elm_genlist_item_append(ad->list,
+ itc,
+ st,
+ NULL,
+ ELM_GENLIST_ITEM_NONE,
+ _list_item_selected_cb,
+ ad);
}
- ad->displayed_stations_count += i;
-
- if (ad->displayed_stations_count < eina_list_count(ad->stations))
- ui_set_load_more_button_visibility(ad, EINA_TRUE);
- else
- ui_set_load_more_button_visibility(ad, EINA_FALSE);
-
-
- evas_object_smart_callback_add(ad->list, "selected", _list_item_selected_cb, ad);
- elm_list_go(ad->list);
}
-static void
-_favorite_btn_clicked_cb(void *data, Evas_Object *obj, void *event_info)
-{
- typedef struct {
- AppData *ad;
- Elm_Object_Item *li;
- } FavCtx;
- FavCtx *ctx = data;
- if (!ctx) return;
- Station *st = elm_object_item_data_get(ctx->li);
- if (!st) { free(ctx); return; }
-
- st->favorite = !st->favorite;
-
- // Update button text to reflect state; use star characters for a clear fallback
- if (st->favorite)
- elm_object_text_set(obj, "★");
- else
- elm_object_text_set(obj, "☆");
-
- favorites_set(ctx->ad, st, st->favorite);
- favorites_save(ctx->ad);
-
- // Ensure the list item doesn't get selected when clicking the favorite button
- evas_object_propagate_events_set(obj, EINA_FALSE);
-
- free(ctx);
-}
-
-static void
-_favorite_remove_btn_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
-{
- typedef struct {
- AppData *ad;
- Elm_Object_Item *li;
- } FavCtx;
-
- FavCtx *ctx = data;
- if (!ctx) return;
- Station *st = elm_object_item_data_get(ctx->li);
- if (!st) { free(ctx); return; }
-
- st->favorite = EINA_FALSE;
- favorites_set(ctx->ad, st, EINA_FALSE);
- favorites_save(ctx->ad);
-
- // Rebuild favorites list to reflect removal
- favorites_rebuild_station_list(ctx->ad);
- station_list_populate_favorites(ctx->ad);
-
- free(ctx);
-}
void
station_list_populate_favorites(AppData *ad)
@@ -189,64 +195,27 @@ station_list_populate_favorites(AppData *ad)
Eina_List *l;
Station *st;
+ if (!itc)
+ {
+ itc = elm_genlist_item_class_new();
+ itc->item_style = "default";
+ itc->func.text_get = _gl_text_get;
+ itc->func.content_get = _gl_content_get;
+ itc->func.state_get = _gl_state_get;
+ itc->func.del = _gl_del;
+ }
+
station_list_clear(ad);
+ evas_object_data_set(ad->list, "ad", ad);
EINA_LIST_FOREACH(ad->favorites_stations, l, st)
{
-
- Evas_Object *icon_box = elm_box_add(ad->win);
- elm_box_horizontal_set(icon_box, EINA_TRUE);
- evas_object_size_hint_min_set(icon_box, 64, 64);
-
- Evas_Object *icon = elm_icon_add(ad->win);
- evas_object_size_hint_min_set(icon, 64, 64);
- elm_icon_standard_set(icon, "media-playback-start");
- elm_box_pack_end(icon_box, icon);
- evas_object_show(icon);
-
- Evas_Object *fav_btn = elm_button_add(ad->win);
- evas_object_size_hint_min_set(fav_btn, 60, 30);
- evas_object_propagate_events_set(fav_btn, EINA_FALSE);
- elm_object_text_set(fav_btn, "Remove");
-
- evas_object_show(icon_box);
- Elm_Object_Item *li = elm_list_item_append(ad->list, st->name, icon_box,
- fav_btn, NULL, NULL);
- elm_object_item_data_set(li, st);
-
- typedef struct {
- AppData *ad;
- Elm_Object_Item *li;
- } FavCtx;
- FavCtx *ctx = calloc(1, sizeof(FavCtx));
- ctx->ad = ad;
- ctx->li = li;
- evas_object_smart_callback_add(fav_btn, "clicked", _favorite_remove_btn_clicked_cb, ctx);
-
- fprintf(stderr, "ICON: Station: %s, Favicon URL: %s\n", st->name, st->favicon);
- if (st->favicon && st->favicon[0] && st->stationuuid)
- {
- char cache_path[PATH_MAX];
- const char *home = getenv("HOME");
- snprintf(cache_path, sizeof(cache_path), "%s/.cache/eradio/favicons/%s", home, st->stationuuid);
-
- if (ecore_file_exists(cache_path))
- {
- fprintf(stderr, "ICON: Using cached icon for %s: %s\n", st->name, cache_path);
- elm_image_file_set(icon, cache_path, NULL);
- }
- else
- {
- fprintf(stderr, "ICON: Downloading icon for %s from %s\n", st->name, st->favicon);
- elm_icon_standard_set(icon, "emblem-unreadable");
- http_download_icon(ad, li, st->favicon);
- }
- }
- else
- {
- fprintf(stderr, "ICON: No favicon for %s\n", st->name);
- }
+ elm_genlist_item_append(ad->list,
+ itc,
+ st,
+ NULL,
+ ELM_GENLIST_ITEM_NONE,
+ _list_item_selected_cb,
+ ad);
}
- evas_object_smart_callback_add(ad->list, "selected", _list_item_selected_cb, ad);
- elm_list_go(ad->list);
-}
+}
\ No newline at end of file
diff --git a/src/ui.c b/src/ui.c
index 0718a40..acf4389 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -194,16 +194,13 @@ ui_create(AppData *ad)
evas_object_show(ad->server_hoversel);
- ad->list = elm_list_add(ad->win);
+ ad->list = elm_genlist_add(ad->win);
evas_object_size_hint_weight_set(ad->list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(ad->list, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_box_pack_end(box, ad->list);
evas_object_show(ad->list);
- ad->load_more_btn = elm_button_add(ad->win);
- elm_object_text_set(ad->load_more_btn, "Load More");
- elm_box_pack_end(box, ad->load_more_btn);
- evas_object_hide(ad->load_more_btn); // Hide by default
+
ad->controls_toolbar = elm_toolbar_add(ad->win);
elm_toolbar_shrink_mode_set(ad->controls_toolbar, ELM_TOOLBAR_SHRINK_MENU);
@@ -228,7 +225,7 @@ ui_create(AppData *ad)
evas_object_smart_callback_add(ad->search_btn, "clicked", _search_btn_clicked_cb, ad);
evas_object_smart_callback_add(ad->search_entry, "activated", _search_entry_activated_cb, ad);
evas_object_smart_callback_add(ad->list, "selected", _list_item_selected_cb, ad);
- evas_object_smart_callback_add(ad->load_more_btn, "clicked", _load_more_btn_clicked_cb, ad);
+
/* Default to Search view on startup */
ad->view_mode = VIEW_SEARCH;
@@ -328,7 +325,6 @@ _tb_favorites_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_i
elm_box_unpack(ad->main_box, ad->search_bar);
evas_object_hide(ad->search_bar);
if (ad->separator) evas_object_hide(ad->separator);
- ui_set_load_more_button_visibility(ad, EINA_FALSE);
favorites_rebuild_station_list(ad);
station_list_populate_favorites(ad);
}
@@ -345,24 +341,13 @@ _tb_search_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info
elm_box_pack_after(ad->main_box, ad->search_bar, ad->top_toolbar);
evas_object_show(ad->search_bar);
if (ad->separator) evas_object_show(ad->separator);
- ui_set_load_more_button_visibility(ad, EINA_FALSE);
+
if (ad->stations)
station_list_populate(ad, EINA_TRUE);
else
station_list_clear(ad);
}
-static void
-_load_more_btn_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
-{
- AppData *ad = data;
- station_list_populate(ad, EINA_FALSE);
-}
-void ui_set_load_more_button_visibility(AppData *ad, Eina_Bool visible)
-{
- if (visible)
- evas_object_show(ad->load_more_btn);
- else
- evas_object_hide(ad->load_more_btn);
-}
+
+
diff --git a/src/ui.h b/src/ui.h
index 3575c8b..be7b70e 100644
--- a/src/ui.h
+++ b/src/ui.h
@@ -6,6 +6,6 @@ typedef struct _AppData AppData;
void ui_create(AppData *ad);
void ui_update_server_list(AppData *ad);
-void ui_set_load_more_button_visibility(AppData *ad, Eina_Bool visible);
+
void ui_loading_start(AppData *ad);
void ui_loading_stop(AppData *ad);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.