channel: remove direct usage of ch_name

This is because the field can now be NULL and there were places where this
was not properly checked. So now a function call channel_get_name() should
be used instead and is garaunteed to return non-NULL.

In addition to this there is a nice added benefit. You can NOT set the name,
and it will automatically pull the name from the first available service. This
will not be persistent (part of config) unless you change that name and save
from the UI. This means if the service name changes, so will the channel name.

However on that last point there will not be, currently, any message sent to
the clients (HTSP) to inform them of such a change. So there might be some lag
in getting the update.
This commit is contained in:
Adam Sutton 2013-10-10 10:59:42 +01:00
parent a79dd7b7d8
commit db1656314f
21 changed files with 129 additions and 65 deletions

View file

@ -38,7 +38,7 @@ api_channel_list
CHANNEL_FOREACH(ch) {
e = htsmsg_create_map();
htsmsg_add_str(e, "key", idnode_uuid_as_str(&ch->ch_id));
htsmsg_add_str(e, "val", ch->ch_name ?: "");
htsmsg_add_str(e, "val", channel_get_name(ch));
htsmsg_add_msg(l, NULL, e);
}
pthread_mutex_unlock(&global_lock);

View file

@ -40,8 +40,8 @@ api_epg_entry ( epg_broadcast_t *eb, const char *lang )
m = htsmsg_create_map();
/* EPG IDs */
// Note: "id" is for UI compat, remove it?
htsmsg_add_u32(m, "id", eb->id);
// TODO: the above is for UI compat, remove it
htsmsg_add_u32(m, "eventId", eb->id);
if (ee) {
htsmsg_add_u32(m, "episodeId", ee->id);
@ -55,9 +55,9 @@ api_epg_entry ( epg_broadcast_t *eb, const char *lang )
}
/* Channel Info */
htsmsg_add_str(m, "channel", ch->ch_name ?: "");
// TODO: the above is for UI compat, remove it
htsmsg_add_str(m, "channelName", ch->ch_name ?: "");
// Note: "channel" is for UI compat, remove it?
htsmsg_add_str(m, "channel", channel_get_name(ch));
htsmsg_add_str(m, "channelName", channel_get_name(ch));
htsmsg_add_str(m, "channelUuid", channel_get_uuid(ch));
htsmsg_add_u32(m, "channelId", channel_get_id(ch));

View file

@ -186,8 +186,21 @@ channel_class_icon_notify ( void *obj )
static const char *
channel_class_get_title ( idnode_t *self )
{
channel_t *ch = (channel_t*)self;
return ch->ch_name;
return channel_get_name((channel_t*)self);
}
static const void *
channel_class_get_name ( void *p )
{
static const char *s;
s = channel_get_name(p);
return &s;
}
static int
channel_class_set_name ( void *o, const void *p )
{
return channel_set_name(o, p);
}
const idclass_t channel_class = {
@ -210,6 +223,8 @@ const idclass_t channel_class = {
.id = "name",
.name = "Name",
.off = offsetof(channel_t, ch_name),
.get = channel_class_get_name,
.set = channel_class_set_name,
},
{
.type = PT_INT,
@ -273,7 +288,7 @@ channel_find_by_name ( const char *name )
{
channel_t *ch;
CHANNEL_FOREACH(ch)
if (!strcmp(ch->ch_name ?: "", name))
if (!strcmp(channel_get_name(ch), name))
break;
return ch;
}
@ -359,6 +374,42 @@ channel_set_tags_by_list ( channel_t *ch, htsmsg_t *tags )
return save;
}
const char *
channel_get_name ( channel_t *ch )
{
static const char *blank = "";
const char *s;
channel_service_mapping_t *csm;
if (ch->ch_name) return ch->ch_name;
LIST_FOREACH(csm, &ch->ch_services, csm_chn_link)
if ((s = service_get_channel_name(csm->csm_svc)))
return s;
return blank;
}
int
channel_set_name ( channel_t *ch, const char *s )
{
if (!s || !*s) {
if (ch->ch_name) {
free(ch->ch_name);
ch->ch_name = NULL;
}
return 1; // NOTE: we always return this, else UI gets confused
// if user see's generated name clears to "" and tries to set
// and nosave is returned (so UI doesn't update)
}
if (!ch->ch_name || strcmp(ch->ch_name, s)) {
free(ch->ch_name);
ch->ch_name = strdup(s);
return 1;
}
return 0;
}
/* **************************************************************************
* Creation/Deletion
* *************************************************************************/
@ -397,7 +448,7 @@ channel_delete ( channel_t *ch )
lock_assert(&global_lock);
tvhinfo("channel", "%s - deleting", ch->ch_name);
tvhinfo("channel", "%s - deleting", channel_get_name(ch));
/* Tags */
while((ctm = LIST_FIRST(&ch->ch_ctms)) != NULL)

View file

@ -45,7 +45,7 @@ typedef struct channel
int ch_zombie;
/* Channel info */
char *ch_name;
char *ch_name; // Note: do not access directly!
int ch_number;
char *ch_icon;
struct channel_tag_mapping_list ch_ctms;
@ -146,6 +146,9 @@ int channel_tag_map(channel_t *ch, channel_tag_t *ct);
void channel_save(channel_t *ch);
const char *channel_get_name ( channel_t *ch );
int channel_set_name ( channel_t *ch, const char *s );
#define channel_get_uuid(ch) idnode_uuid_as_str(&ch->ch_id)
#define channel_get_id(ch) idnode_get_short_uuid((&ch->ch_id))

View file

@ -202,7 +202,7 @@ typedef struct dvr_entry {
} dvr_entry_t;
#define DVR_CH_NAME(e) ((e)->de_channel == NULL ? (e)->de_channel_name : (e)-> de_channel->ch_name)
#define DVR_CH_NAME(e) ((e)->de_channel == NULL ? (e)->de_channel_name : channel_get_name((e)->de_channel))
/**
* Autorec entry

View file

@ -271,7 +271,7 @@ autorec_record_build(dvr_autorec_entry_t *dae)
htsmsg_add_str(e, "comment", dae->dae_comment);
if(dae->dae_channel != NULL)
htsmsg_add_str(e, "channel", dae->dae_channel->ch_name);
htsmsg_add_str(e, "channel", channel_get_name(dae->dae_channel));
if(dae->dae_channel_tag != NULL)
htsmsg_add_str(e, "tag", dae->dae_channel_tag->ct_name);

View file

@ -825,7 +825,8 @@ dvr_event_replaced(epg_broadcast_t *e, epg_broadcast_t *new_e)
tvhtrace("dvr",
"dvr entry %d event replaced %s on %s @ %"PRItime_t
" to %"PRItime_t,
de->de_id, epg_broadcast_get_title(e, NULL), e->channel->ch_name,
de->de_id, epg_broadcast_get_title(e, NULL),
channel_get_name(e->channel),
e->start, e->stop);
/* Ignore - already in progress */
@ -847,7 +848,8 @@ dvr_event_replaced(epg_broadcast_t *e, epg_broadcast_t *new_e)
tvhtrace("dvr",
" replacement event %s on %s @ %"PRItime_t
" to %"PRItime_t,
epg_broadcast_get_title(e, NULL), e->channel->ch_name,
epg_broadcast_get_title(e, NULL),
channel_get_name(e->channel),
e->start, e->stop);
e->getref(e);
de->de_bcast = e;
@ -875,7 +877,7 @@ void dvr_event_updated ( epg_broadcast_t *e )
"dvr entry %d link to event %s on %s @ %"PRItime_t
" to %"PRItime_t,
de->de_id, epg_broadcast_get_title(e, NULL),
e->channel->ch_name,
channel_get_name(e->channel),
e->start, e->stop);
e->getref(e);
de->de_bcast = e;
@ -1048,7 +1050,7 @@ dvr_destroy_by_channel(channel_t *ch)
while((de = LIST_FIRST(&ch->ch_dvrs)) != NULL) {
LIST_REMOVE(de, de_channel_link);
de->de_channel = NULL;
de->de_channel_name = strdup(ch->ch_name);
de->de_channel_name = strdup(channel_get_name(ch));
dvr_entry_purge(de);
}
}

View file

@ -1376,7 +1376,8 @@ static void _epg_channel_timer_callback ( void *p )
/* Expire */
if ( ebc->stop <= dispatch_clock ) {
tvhlog(LOG_DEBUG, "epg", "expire event %u (%s) from %s",
ebc->id, epg_broadcast_get_title(ebc, NULL), ch->ch_name);
ebc->id, epg_broadcast_get_title(ebc, NULL),
channel_get_name(ch));
_epg_channel_rem_broadcast(ch, ebc, NULL);
continue; // skip to next
@ -1399,16 +1400,16 @@ static void _epg_channel_timer_callback ( void *p )
tvhlog(LOG_DEBUG, "epg", "now/next %u/%u set on %s",
ch->ch_epg_now ? ch->ch_epg_now->id : 0,
ch->ch_epg_next ? ch->ch_epg_next->id : 0,
ch->ch_name);
channel_get_name(ch));
tvhlog(LOG_DEBUG, "epg", "inform HTSP of now event change on %s",
ch->ch_name);
channel_get_name(ch));
htsp_channel_update_nownext(ch);
}
/* re-arm */
if ( next ) {
tvhlog(LOG_DEBUG, "epg", "arm channel timer @ %"PRItime_t" for %s",
next, ch->ch_name);
next, channel_get_name(ch));
gtimer_arm_abs(&ch->ch_epg_timer, _epg_channel_timer_callback, ch, next);
}
@ -1443,7 +1444,8 @@ static epg_broadcast_t *_epg_channel_add_broadcast
// Note: sets updated
_epg_object_getref(ret);
tvhtrace("epg", "added event %u (%s) on %s @ %"PRItime_t " to %"PRItime_t,
ret->id, epg_broadcast_get_title(ret, NULL), ch->ch_name, ret->start, ret->stop);
ret->id, epg_broadcast_get_title(ret, NULL),
channel_get_name(ch), ret->start, ret->stop);
/* Existing */
} else {
@ -1458,7 +1460,8 @@ static epg_broadcast_t *_epg_channel_add_broadcast
ret->stop = (*bcast)->stop;
_epg_object_set_updated(ret);
tvhtrace("epg", "updated event %u (%s) on %s @ %"PRItime_t " to %"PRItime_t,
ret->id, epg_broadcast_get_title(ret, NULL), ch->ch_name, ret->start, ret->stop);
ret->id, epg_broadcast_get_title(ret, NULL),
channel_get_name(ch), ret->start, ret->stop);
}
}
}
@ -1470,7 +1473,8 @@ static epg_broadcast_t *_epg_channel_add_broadcast
while ( (ebc = RB_PREV(ret, sched_link)) != NULL ) {
if ( ebc->stop <= ret->start ) break;
tvhtrace("epg", "remove overlap (b) event %u (%s) on %s @ %"PRItime_t " to %"PRItime_t,
ebc->id, epg_broadcast_get_title(ebc, NULL), ch->ch_name, ebc->start, ebc->stop);
ebc->id, epg_broadcast_get_title(ebc, NULL),
channel_get_name(ch), ebc->start, ebc->stop);
_epg_channel_rem_broadcast(ch, ebc, ret);
}
@ -1478,7 +1482,8 @@ static epg_broadcast_t *_epg_channel_add_broadcast
while ( (ebc = RB_NEXT(ret, sched_link)) != NULL ) {
if ( ebc->start >= ret->stop ) break;
tvhtrace("epg", "remove overlap (a) event %u (%s) on %s @ %"PRItime_t " to %"PRItime_t,
ebc->id, epg_broadcast_get_title(ebc, NULL), ch->ch_name, ebc->start, ebc->stop);
ebc->id, epg_broadcast_get_title(ebc, NULL),
channel_get_name(ch), ebc->start, ebc->stop);
_epg_channel_rem_broadcast(ch, ebc, ret);
}

View file

@ -38,7 +38,7 @@ int epggrab_channel_match ( epggrab_channel_t *ec, channel_t *ch )
if (!ec || !ch) return 0;
if (LIST_FIRST(&ec->channels)) return 0; // ignore already paired
if (ec->name && !strcmp(ec->name, ch->ch_name)) return 1;
if (ec->name && !strcmp(ec->name, channel_get_name(ch))) return 1;
return 0;
}
@ -53,7 +53,7 @@ void epggrab_channel_link ( epggrab_channel_t *ec, channel_t *ch )
if (ecl->channel == ch) return;
tvhlog(LOG_INFO, ec->mod->id, "linking %s to %s",
ec->id, ch->ch_name);
ec->id, channel_get_name(ch));
ecl = calloc(1, sizeof(epggrab_channel_link_t));
ecl->channel = ch;
LIST_INSERT_HEAD(&ec->channels, ecl, link);

View file

@ -516,7 +516,7 @@ htsp_build_channel(channel_t *ch, const char *method, htsp_connection_t *htsp)
htsmsg_add_u32(out, "channelId", channel_get_id(ch));
htsmsg_add_u32(out, "channelNumber", ch->ch_number);
htsmsg_add_str(out, "channelName", ch->ch_name ?: "");
htsmsg_add_str(out, "channelName", channel_get_name(ch));
if(ch->ch_icon != NULL) {
uint32_t id;
struct sockaddr_storage addr;

View file

@ -140,7 +140,7 @@ int idnode_write0 (idnode_t *self, htsmsg_t *m, int optmask, int dosave);
#define idclass_serialize(idc) idclass_serialize0(idc, 0)
#define idnode_serialize(in) idnode_serialize0(in, 0)
#define idnode_load(in, m) idnode_write0(in, m, 0, 0)
#define idnode_save(in, m) idnode_read0(in, m, PO_NOSAVE)
#define idnode_save(in, m) idnode_read0(in, m, PO_NOSAVE | PO_USERAW)
#define idnode_update(in, m) idnode_write0(in, m, PO_RDONLY | PO_WRONCE, 1)
const char *idnode_get_str (idnode_t *self, const char *key );

View file

@ -675,7 +675,8 @@ _mk_build_metadata(const dvr_entry_t *de, const epg_broadcast_t *ebc)
addtag(q, build_tag_string("CONTENT_TYPE", ctype, NULL, 0, NULL));
if(ch)
addtag(q, build_tag_string("TVCHANNEL", ch->ch_name, NULL, 0, NULL));
addtag(q, build_tag_string("TVCHANNEL",
channel_get_name(ch), NULL, 0, NULL));
if(de && de->de_desc)
ls = de->de_desc;

View file

@ -184,8 +184,9 @@ prop_read_value
return;
/* Get method */
if (p->get)
val = p->get(obj);
if (!(optmask & PO_USERAW) || !p->off)
if (p->get)
val = p->get(obj);
/* List */
if (p->islist)

View file

@ -45,6 +45,7 @@ typedef enum {
#define PO_WRONCE 0x04 // Property is write-once (i.e. on creation)
#define PO_ADVANCED 0x08 // Property is advanced
#define PO_HIDDEN 0x10 // Property is hidden (by default)
#define PO_USERAW 0x20 // Only save the RAW (off) value if it exists
/*
* Property definition

View file

@ -132,22 +132,7 @@ service_class_channel_enum
static const char *
service_class_get_title ( idnode_t *self )
{
static char *ret = NULL;
const char *str = NULL;
service_t *s = (service_t*)self;
pthread_mutex_lock(&s->s_stream_mutex);
if (ret) {
free(ret);
ret = NULL;
}
if (s->s_channel_name)
str = s->s_channel_name(s);
if (!str)
str = s->s_nicename;
if (str)
ret = strdup(str);
pthread_mutex_unlock(&s->s_stream_mutex);
return ret;
return service_get_channel_name((service_t*)self);
}
static const void *
@ -402,7 +387,7 @@ service_find_instance
/* Debug */
TAILQ_FOREACH(si, sil, si_link) {
const char *name = ch ? ch->ch_name : NULL;
const char *name = ch ? channel_get_name(ch) : NULL;
if (!name && s) name = s->s_nicename;
tvhdebug("service", "%s si %p weight %d prio %d error %d\n",
name, si, si->si_weight, si->si_prio, si->si_error);
@ -1188,6 +1173,17 @@ service_instance_list_clear(service_instance_list_t *sil)
service_instance_destroy(sil, si);
}
/*
* Get name for channel from service
*/
const char *
service_get_channel_name ( service_t *s )
{
const char *r = NULL;
if (s->s_channel_name) r = s->s_channel_name(s);
if (!r) r = s->s_nicename;
return r;
}
/**
* Get the encryption CAID from a service

View file

@ -525,4 +525,6 @@ void service_save ( service_t *s, htsmsg_t *c );
void sort_elementary_streams(service_t *t);
const char *service_get_channel_name (service_t *s);
#endif // SERVICE_H__

View file

@ -236,11 +236,13 @@ subscription_reschedule(void)
}
if (s->ths_channel)
tvhtrace("subscription", "find service for %s weight %d", s->ths_channel->ch_name, s->ths_weight);
tvhtrace("subscription", "find service for %s weight %d",
channel_get_name(s->ths_channel), s->ths_weight);
else
tvhtrace("subscription", "find instance for %s weight %d", s->ths_service->s_nicename, s->ths_weight);
si = service_find_instance(s->ths_service, s->ths_channel, &s->ths_instances, &error,
s->ths_weight);
tvhtrace("subscription", "find instance for %s weight %d",
s->ths_service->s_nicename, s->ths_weight);
si = service_find_instance(s->ths_service, s->ths_channel,
&s->ths_instances, &error, s->ths_weight);
s->ths_current_instance = si;
if(si == NULL) {
@ -378,7 +380,7 @@ subscription_unsubscribe(th_subscription_t *s)
if(s->ths_channel != NULL) {
LIST_REMOVE(s, ths_channel_link);
tvhlog(LOG_INFO, "subscription", "\"%s\" unsubscribing from \"%s\"",
s->ths_title, s->ths_channel->ch_name);
s->ths_title, channel_get_name(s->ths_channel));
} else {
tvhlog(LOG_INFO, "subscription", "\"%s\" unsubscribing",
s->ths_title);
@ -477,7 +479,7 @@ subscription_create_from_channel_or_service
if (ch)
tvhtrace("subscription", "creating subscription for %s weight %d",
ch->ch_name, weight);
channel_get_name(ch), weight);
s = subscription_create(weight, name, st, flags, subscription_input,
hostname, username, client);
s->ths_channel = ch;
@ -492,7 +494,7 @@ subscription_create_from_channel_or_service
tvhlog(LOG_NOTICE, "subscription",
"No transponder available for subscription \"%s\" "
"to channel \"%s\"",
s->ths_title, ch ? ch->ch_name : "none");
s->ths_title, ch ? channel_get_name(ch) : "none");
} else {
source_info_t si;
@ -502,7 +504,7 @@ subscription_create_from_channel_or_service
"\"%s\" subscribing on \"%s\", weight: %d, adapter: \"%s\", "
"network: \"%s\", mux: \"%s\", provider: \"%s\", "
"service: \"%s\"",
s->ths_title, ch ? ch->ch_name : "none", weight,
s->ths_title, ch ? channel_get_name(ch) : "none", weight,
si.si_adapter ?: "<N/A>",
si.si_network ?: "<N/A>",
si.si_mux ?: "<N/A>",
@ -697,7 +699,7 @@ subscription_create_msg(th_subscription_t *s)
htsmsg_add_str(m, "title", s->ths_title);
if(s->ths_channel != NULL)
htsmsg_add_str(m, "channel", s->ths_channel->ch_name ?: "");
htsmsg_add_str(m, "channel", channel_get_name(s->ths_channel));
if(s->ths_service != NULL)
htsmsg_add_str(m, "service", s->ths_service->s_nicename ?: "");

View file

@ -748,7 +748,7 @@ extjs_epg(http_connection_t *hc, const char *remain, void *opaque)
m = htsmsg_create_map();
htsmsg_add_str(m, "channel", ch->ch_name);
htsmsg_add_str(m, "channel", channel_get_name(ch));
htsmsg_add_u32(m, "channelid", channel_get_id(ch));
if(ch->ch_icon != NULL)
htsmsg_add_imageurl(m, "chicon", "imagecache/%d", ch->ch_icon);
@ -832,7 +832,7 @@ extjs_epgrelated(http_connection_t *hc, const char *remain, void *opaque)
count++;
m = htsmsg_create_map();
htsmsg_add_u32(m, "id", ebc->id);
if ( ch->ch_name ) htsmsg_add_str(m, "channel", ch->ch_name);
htsmsg_add_str(m, "channel", channel_get_name(ch));
if (ch->ch_icon)
htsmsg_add_imageurl(m, "chicon", "imagecache/%d", ch->ch_icon);
htsmsg_add_u32(m, "start", ebc->start);

View file

@ -234,7 +234,7 @@ page_einfo(http_connection_t *hc, const char *remain, void *opaque)
s = epg_episode_get_title(e->episode, lang);
htsbuf_qprintf(hq, "<hr><b>\"%s\": \"%s\"</b><br><br>",
e->channel->ch_name, s ?: "");
channel_get_name(e->channel));
dvr_status = de != NULL ? de->de_sched_state : DVR_NOSTATE;

View file

@ -57,7 +57,7 @@ dumpchannels(htsbuf_queue_t *hq)
CHANNEL_FOREACH(ch) {
htsbuf_qprintf(hq, "%s (%d)\n", ch->ch_name, ch->ch_id);
htsbuf_qprintf(hq, "%s (%d)\n", channel_get_name(ch), channel_get_id(ch));
htsbuf_qprintf(hq,
" refcount = %d\n"
" zombie = %d\n"

View file

@ -370,7 +370,7 @@ http_channel_playlist(http_connection_t *hc, channel_t *channel)
snprintf(buf, sizeof(buf), "/stream/channelid/%d", channel_get_id(channel));
htsbuf_qprintf(hq, "#EXTM3U\n");
htsbuf_qprintf(hq, "#EXTINF:-1,%s\n", channel->ch_name);
htsbuf_qprintf(hq, "#EXTINF:-1,%s\n", channel_get_name(channel));
htsbuf_qprintf(hq, "http://%s%s?ticket=%s", host, buf,
access_ticket_create(buf));
@ -419,7 +419,7 @@ http_tag_playlist(http_connection_t *hc, channel_tag_t *tag)
htsbuf_qprintf(hq, "#EXTM3U\n");
LIST_FOREACH(ctm, &tag->ct_ctms, ctm_tag_link) {
snprintf(buf, sizeof(buf), "/stream/channelid/%d", channel_get_id(ctm->ctm_channel));
htsbuf_qprintf(hq, "#EXTINF:-1,%s\n", ctm->ctm_channel->ch_name);
htsbuf_qprintf(hq, "#EXTINF:-1,%s\n", channel_get_name(ctm->ctm_channel));
htsbuf_qprintf(hq, "http://%s%s?ticket=%s\n", host, buf,
access_ticket_create(buf));
}
@ -479,7 +479,7 @@ http_channel_list_playlist(http_connection_t *hc)
CHANNEL_FOREACH(ch) {
snprintf(buf, sizeof(buf), "/stream/channelid/%d", channel_get_id(ch));
htsbuf_qprintf(hq, "#EXTINF:-1,%s\n", ch->ch_name);
htsbuf_qprintf(hq, "#EXTINF:-1,%s\n", channel_get_name(ch));
htsbuf_qprintf(hq, "http://%s%s?ticket=%s\n", host, buf,
access_ticket_create(buf));
}
@ -816,7 +816,7 @@ http_stream_channel(http_connection_t *hc, channel_t *ch)
http_arg_get(&hc->hc_args, "User-Agent"));
if(s) {
name = tvh_strdupa(ch->ch_name);
name = tvh_strdupa(channel_get_name(ch));
pthread_mutex_unlock(&global_lock);
http_stream_run(hc, &sq, name, mc, s);
pthread_mutex_lock(&global_lock);