From 5727ee0d78d1837f744abc06e31cd19bce2e0b4d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 5 Jan 2018 17:38:31 +0100 Subject: [PATCH] channel: move channel sorting functions from webui.c to channel.c, optimize code --- src/channels.c | 133 ++++++++++++++++++++++++++++++++++++- src/channels.h | 9 +++ src/webui/webui.c | 164 +++++----------------------------------------- 3 files changed, 158 insertions(+), 148 deletions(-) diff --git a/src/channels.c b/src/channels.c index c0f7b5a0b..831fc4d65 100644 --- a/src/channels.c +++ b/src/channels.c @@ -46,9 +46,13 @@ #include "intlconv.h" #include "memoryinfo.h" +typedef int (sortfcn_t)(const void *, const void *); + struct channel_tree channels; +int channels_count; struct channel_tag_queue channel_tags; +int channel_tags_count; const char *channel_blank_name = N_("{name-not-set}"); static int channel_in_load; @@ -1156,6 +1160,7 @@ channel_create0 tvherror(LS_CHANNEL, "id collision!"); abort(); } + channels_count++; /* Defaults */ ch->ch_enabled = 1; @@ -1250,6 +1255,7 @@ channel_delete ( channel_t *ch, int delconf ) /* Free memory */ RB_REMOVE(&channels, ch, ch_link); + channels_count--; idnode_unlink(&ch->ch_id); free(ch->ch_epg_parent); free(ch->ch_name); @@ -1258,9 +1264,82 @@ channel_delete ( channel_t *ch, int delconf ) } /** - * + * sorting */ +static int +channel_cmp1(const void *a, const void *b) +{ + int r; + channel_t *c1 = *(channel_t **)a, *c2 = *(channel_t **)b; + int64_t n1 = channel_get_number(c1), n2 = channel_get_number(c2); + if (n1 > n2) + r = 1; + else if (n1 < n2) + r = -1; + else + r = strcasecmp(channel_get_name(c1, ""), channel_get_name(c2, "")); + return r; +} + +static int +channel_cmp2(const void *a, const void *b) +{ + channel_t *c1 = *(channel_t **)a, *c2 = *(channel_t **)b; + return strcasecmp(channel_get_name(c1, ""), channel_get_name(c2, "")); +} + +static sortfcn_t *channel_sort_fcn(const char *sort_type) +{ + if (sort_type) { + if (!strcmp(sort_type, "numname")) + return &channel_cmp1; + if (!strcmp(sort_type, "name")) + return &channel_cmp2; + } + return &channel_cmp1; +} + +channel_t ** +channel_get_sorted_list(const char *sort_type, int *_count) +{ + int count = 0; + channel_t *ch, **chlist = malloc(channels_count * sizeof(channel_t *)); + + CHANNEL_FOREACH(ch) + if (ch->ch_enabled) + chlist[count++] = ch; + + assert(count <= channels_count); + qsort(chlist, count, sizeof(channel_t *), channel_sort_fcn(sort_type)); + + *_count = count; + return chlist; +} + +channel_t ** +channel_get_sorted_list_for_tag + (const char *sort_type, channel_tag_t *tag, int *_count) +{ + int count = 0; + channel_t *ch, **chlist = malloc(channels_count * sizeof(channel_t *)); + idnode_list_mapping_t *ilm; + + LIST_FOREACH(ilm, &tag->ct_ctms, ilm_in1_link) { + ch = (channel_t *)ilm->ilm_in2; + if (ch->ch_enabled) + chlist[count++] = ch; + } + + assert(count <= channels_count); + qsort(chlist, count, sizeof(channel_t *), channel_sort_fcn(sort_type)); + *_count = count; + return chlist; +} + +/** + * + */ static void channels_memoryinfo_update(memoryinfo_t *my) { channel_t *ch; @@ -1293,6 +1372,7 @@ channel_init ( void ) channel_t *ch, *parent; char *s; + channels_count = 0; RB_INIT(&channels); memoryinfo_register(&channels_memoryinfo); idclass_register(&channel_class); @@ -1440,6 +1520,7 @@ channel_tag_create(const char *uuid, htsmsg_t *conf) htsp_tag_add(ct); TAILQ_INSERT_TAIL(&channel_tags, ct, ct_link); + channel_tags_count++; return ct; } @@ -1464,6 +1545,7 @@ channel_tag_destroy(channel_tag_t *ct, int delconf) htsp_tag_delete(ct); TAILQ_REMOVE(&channel_tags, ct, ct_link); + channel_tags_count--; idnode_unlink(&ct->ct_id); bouquet_destroy_by_channel_tag(ct); @@ -1723,7 +1805,55 @@ channel_tag_find_by_id(uint32_t id) { /** * */ +static int +channel_tag_cmp1(const void *a, const void *b) +{ + channel_tag_t *ct1 = *(channel_tag_t **)a, *ct2 = *(channel_tag_t **)b; + int r = ct1->ct_index - ct2->ct_index; + if (r == 0) + r = strcasecmp(ct1->ct_name, ct2->ct_name); + return r; +} +static int +channel_tag_cmp2(const void *a, const void *b) +{ + channel_tag_t *ct1 = *(channel_tag_t **)a, *ct2 = *(channel_tag_t **)b; + return strcasecmp(ct1->ct_name, ct2->ct_name); +} + +static sortfcn_t *channel_tag_sort_fcn(const char *sort_type) +{ + if (sort_type) { + if (!strcmp(sort_type, "idxname")) + return &channel_tag_cmp1; + if (!strcmp(sort_type, "name")) + return &channel_tag_cmp2; + } + return &channel_tag_cmp1; +} + +channel_tag_t ** +channel_tag_get_sorted_list(const char *sort_type, int *_count) +{ + int count = 0; + channel_tag_t *ct, **ctlist; + + ctlist = malloc(channel_tags_count * sizeof(channel_tag_t *)); + + TAILQ_FOREACH(ct, &channel_tags, ct_link) + if(ct->ct_enabled && !ct->ct_internal) + ctlist[count++] = ct; + + assert(count <= channel_tags_count); + qsort(ctlist, count, sizeof(channel_tag_t *), channel_tag_sort_fcn(sort_type)); + + *_count = count; + return ctlist; +} +/** + * + */ static void channel_tags_memoryinfo_update(memoryinfo_t *my) { channel_tag_t *ct; @@ -1756,6 +1886,7 @@ channel_tag_init ( void ) htsmsg_field_t *f; memoryinfo_register(&channel_tags_memoryinfo); + channel_tags_count = 0; TAILQ_INIT(&channel_tags); if ((c = hts_settings_load("channel/tag")) != NULL) { HTSMSG_FOREACH(f, c) { diff --git a/src/channels.h b/src/channels.h index e16804cfb..00a750844 100644 --- a/src/channels.h +++ b/src/channels.h @@ -30,7 +30,9 @@ RB_HEAD(channel_tree, channel); TAILQ_HEAD(channel_tag_queue, channel_tag); extern struct channel_tag_queue channel_tags; +extern int channel_tags_count; extern struct channel_tree channels; +extern int channels_count; #define CHANNEL_FOREACH(ch) RB_FOREACH(ch, &channels, ch_link) @@ -206,4 +208,11 @@ const char *channel_get_epgid ( channel_t *ch ); #define channel_get_id(ch) idnode_get_short_uuid((&(ch)->ch_id)) +channel_t **channel_get_sorted_list + ( const char *sort_type, int *_count ) ; +channel_t **channel_get_sorted_list_for_tag + ( const char *sort_type, channel_tag_t *tag, int *_count ); +channel_tag_t **channel_tag_get_sorted_list + ( const char *sort_type, int *_count ); + #endif /* CHANNELS_H */ diff --git a/src/webui/webui.c b/src/webui/webui.c index 0f41753cc..c3fde79cb 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -61,8 +61,6 @@ #include #endif -typedef int (sortfcn_t)(const void *, const void *); - enum { PLAYLIST_M3U, PLAYLIST_E2, @@ -71,75 +69,6 @@ enum { static int webui_xspf; -/* - * - */ -static int -http_channel_playlist_cmp(const void *a, const void *b) -{ - int r; - channel_t *c1 = *(channel_t **)a, *c2 = *(channel_t **)b; - int64_t n1 = channel_get_number(c1), n2 = channel_get_number(c2); - if (n1 > n2) - r = 1; - else if (n1 < n2) - r = -1; - else - r = strcasecmp(channel_get_name(c1, ""), channel_get_name(c2, "")); - return r; -} - -static int -http_channel_playlist_cmp2(const void *a, const void *b) -{ - channel_t *c1 = *(channel_t **)a, *c2 = *(channel_t **)b; - return strcasecmp(channel_get_name(c1, ""), channel_get_name(c2, "")); -} - -static sortfcn_t *http_channel_playlist_sfcn(http_connection_t *hc) -{ - const char *sorttype = http_arg_get(&hc->hc_req_args, "sort"); - if (sorttype) { - if (!strcmp(sorttype, "numname")) - return &http_channel_playlist_cmp; - if (!strcmp(sorttype, "name")) - return &http_channel_playlist_cmp2; - } - return &http_channel_playlist_cmp; -} - -/* - * - */ -static int -http_channel_tag_playlist_cmp(const void *a, const void *b) -{ - channel_tag_t *ct1 = *(channel_tag_t **)a, *ct2 = *(channel_tag_t **)b; - int r = ct1->ct_index - ct2->ct_index; - if (r == 0) - r = strcasecmp(ct1->ct_name, ct2->ct_name); - return r; -} - -static int -http_channel_tag_playlist_cmp2(const void *a, const void *b) -{ - channel_tag_t *ct1 = *(channel_tag_t **)a, *ct2 = *(channel_tag_t **)b; - return strcasecmp(ct1->ct_name, ct2->ct_name); -} - -static sortfcn_t *http_channel_tag_playlist_sfcn(http_connection_t *hc) -{ - const char *sorttype = http_arg_get(&hc->hc_req_args, "sort"); - if (sorttype) { - if (!strcmp(sorttype, "idxname")) - return &http_channel_tag_playlist_cmp; - if (!strcmp(sorttype, "name")) - return &http_channel_tag_playlist_cmp2; - } - return &http_channel_tag_playlist_cmp; -} - /** * */ @@ -678,40 +607,22 @@ http_tag_playlist(http_connection_t *hc, int pltype, channel_tag_t *tag) { htsbuf_queue_t *hq; char buf[255], ubuf[UUID_HEX_SIZE]; - idnode_list_mapping_t *ilm; char *profile, *hostpath; - const char *name, *blank; + const char *name, *blank, *sort; const char *lang = hc->hc_access->aa_lang_ui; channel_t *ch; channel_t **chlist; - int idx = 0, count = 0; + int idx, count = 0; if(hc->hc_access == NULL || access_verify2(hc->hc_access, ACCESS_STREAMING)) return HTTP_STATUS_UNAUTHORIZED; hq = &hc->hc_reply; - profile = profile_validate_name(http_arg_get(&hc->hc_req_args, "profile")); hostpath = http_get_hostpath(hc); - - LIST_FOREACH(ilm, &tag->ct_ctms, ilm_in1_link) { - ch = (channel_t *)ilm->ilm_in2; - if (ch->ch_enabled) - count++; - } - - chlist = malloc(count * sizeof(channel_t *)); - - LIST_FOREACH(ilm, &tag->ct_ctms, ilm_in1_link) { - ch = (channel_t *)ilm->ilm_in2; - if (ch->ch_enabled) - chlist[idx++] = ch; - } - - assert(idx == count); - - qsort(chlist, count, sizeof(channel_t *), http_channel_playlist_sfcn(hc)); + sort = http_arg_get(&hc->hc_req_args, "sort"); + chlist = channel_get_sorted_list_for_tag(sort, tag, &count); if (pltype == PLAYLIST_M3U) htsbuf_append_str(hq, "#EXTM3U\n"); @@ -738,7 +649,6 @@ http_tag_playlist(http_connection_t *hc, int pltype, channel_tag_t *tag) } free(chlist); - free(hostpath); free(profile); return 0; @@ -758,11 +668,11 @@ http_tag_list_playlist(http_connection_t *hc, int pltype) channel_t *ch; channel_t **chlist; int labelidx = 0; - int idx = 0, count = 0; - int chidx = 0, chcount = 0; + int idx, count = 0; + int chidx, chcount = 0; char *profile, *hostpath; const char *lang = hc->hc_access->aa_lang_ui; - const char *blank; + const char *blank, *sort; idnode_list_mapping_t *ilm; if(hc->hc_access == NULL || @@ -770,39 +680,13 @@ http_tag_list_playlist(http_connection_t *hc, int pltype) return HTTP_STATUS_UNAUTHORIZED; hq = &hc->hc_reply; - profile = profile_validate_name(http_arg_get(&hc->hc_req_args, "profile")); - hostpath = http_get_hostpath(hc); - - TAILQ_FOREACH(ct, &channel_tags, ct_link) - if(ct->ct_enabled && !ct->ct_internal) - count++; - - ctlist = malloc(count * sizeof(channel_tag_t *)); - - TAILQ_FOREACH(ct, &channel_tags, ct_link) - if(ct->ct_enabled && !ct->ct_internal) - ctlist[idx++] = ct; - - assert(idx == count); - - qsort(ctlist, count, sizeof(channel_tag_t *), http_channel_tag_playlist_sfcn(hc)); + sort = http_arg_get(&hc->hc_req_args, "sort"); + ctlist = channel_tag_get_sorted_list(sort, &count); if (pltype == PLAYLIST_E2 || pltype == PLAYLIST_SATIP_M3U) { - CHANNEL_FOREACH(ch) - if (ch->ch_enabled) - chcount++; - - chlist = malloc(chcount * sizeof(channel_t *)); - - CHANNEL_FOREACH(ch) - if (ch->ch_enabled) - chlist[chidx++] = ch; - - assert(chidx == chcount); - - qsort(chlist, chcount, sizeof(channel_t *), http_channel_playlist_sfcn(hc)); + chlist = channel_get_sorted_list(sort, &chcount); } else { chlist = NULL; } @@ -811,7 +695,6 @@ http_tag_list_playlist(http_connection_t *hc, int pltype) htsbuf_append_str(hq, pltype == PLAYLIST_E2 ? "#NAME Tvheadend Channels\n" : "#EXTM3U\n"); for (idx = 0; idx < count; idx++) { ct = ctlist[idx]; - if (pltype == PLAYLIST_M3U) { snprintf(buf, sizeof(buf), "/playlist/tagid/%d", idnode_get_short_uuid(&ct->ct_id)); http_m3u_playlist_add(hq, hostpath, buf, profile, ct->ct_name, @@ -859,7 +742,7 @@ http_channel_list_playlist(http_connection_t *hc, int pltype) channel_t **chlist; int idx = 0, count = 0; char *profile, *hostpath; - const char *name, *blank; + const char *name, *blank, *sort; const char *lang = hc->hc_access->aa_lang_ui; if(hc->hc_access == NULL || @@ -870,22 +753,10 @@ http_channel_list_playlist(http_connection_t *hc, int pltype) profile = profile_validate_name(http_arg_get(&hc->hc_req_args, "profile")); hostpath = http_get_hostpath(hc); - - CHANNEL_FOREACH(ch) - if (ch->ch_enabled) - count++; - - chlist = malloc(count * sizeof(channel_t *)); - - CHANNEL_FOREACH(ch) - if (ch->ch_enabled) - chlist[idx++] = ch; - - assert(idx == count); - - qsort(chlist, count, sizeof(channel_t *), http_channel_playlist_sfcn(hc)); - + sort = http_arg_get(&hc->hc_req_args, "sort"); + chlist = channel_get_sorted_list(sort, &count); blank = tvh_gettext_lang(lang, channel_blank_name); + htsbuf_append_str(hq, pltype == PLAYLIST_E2 ? "#NAME Tvheadend Channels\n" : "#EXTM3U\n"); for (idx = 0; idx < count; idx++) { ch = chlist[idx]; @@ -909,7 +780,6 @@ http_channel_list_playlist(http_connection_t *hc, int pltype) } free(chlist); - free(hostpath); free(profile); return 0; @@ -1649,7 +1519,7 @@ http_serve_file(http_connection_t *hc, const char *fname, content_len = file_end - file_start+1; sprintf(range_buf, "bytes %jd-%jd/%jd", - file_start, file_end, (intmax_t)st.st_size); + file_start, file_end, (intmax_t)st.st_size); if(file_start > 0) if (lseek(fd, file_start, SEEK_SET) != file_start) { @@ -1667,8 +1537,8 @@ http_serve_file(http_connection_t *hc, const char *fname, http_send_begin(hc); http_send_header(hc, range ? HTTP_STATUS_PARTIAL_CONTENT : HTTP_STATUS_OK, - content, content_len, NULL, NULL, 10, - range ? range_buf : NULL, disposition, NULL); + content, content_len, NULL, NULL, 10, + range ? range_buf : NULL, disposition, NULL); ret = 0; if(!hc->hc_no_output) { -- 2.47.3