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);
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);
}
/* 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));
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 = {
.id = "name",
.name = "Name",
.off = offsetof(channel_t, ch_name),
+ .get = channel_class_get_name,
+ .set = channel_class_set_name,
},
{
.type = PT_INT,
{
channel_t *ch;
CHANNEL_FOREACH(ch)
- if (!strcmp(ch->ch_name ?: "", name))
+ if (!strcmp(channel_get_name(ch), name))
break;
return ch;
}
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
* *************************************************************************/
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)
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;
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))
} 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
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);
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 */
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;
"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;
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);
}
}
/* 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
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);
}
// 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 {
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);
}
}
}
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);
}
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);
}
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;
}
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);
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;
#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 );
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;
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)
#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
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 *
/* 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);
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
void sort_elementary_streams(service_t *t);
+const char *service_get_channel_name (service_t *s);
+
#endif // SERVICE_H__
}
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) {
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);
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;
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;
"\"%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>",
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 ?: "");
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);
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);
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;
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"
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));
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));
}
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));
}
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);