channel: tags - move to idnode system
This commit is contained in:
parent
a958fd749e
commit
3c088cb271
13 changed files with 213 additions and 303 deletions
|
@ -78,27 +78,50 @@ api_channel_create
|
|||
}
|
||||
|
||||
static int
|
||||
api_channeltag_enum
|
||||
api_channel_tag_list
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
channel_tag_t *ct;
|
||||
htsmsg_t *l, *e;
|
||||
|
||||
int _enum = htsmsg_get_bool_or_default(args, "enum", 0);
|
||||
|
||||
if (_enum) {
|
||||
l = htsmsg_create_list();
|
||||
TAILQ_FOREACH(ct, &channel_tags, ct_link) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_u32(e, "key", ct->ct_identifier);
|
||||
htsmsg_add_str(e, "val", ct->ct_name);
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
}
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
} else {
|
||||
// TODO: support full listing v enum
|
||||
l = htsmsg_create_list();
|
||||
TAILQ_FOREACH(ct, &channel_tags, ct_link) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "key", idnode_uuid_as_str(&ct->ct_id));
|
||||
htsmsg_add_str(e, "val", ct->ct_name);
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
}
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
api_channel_tag_grid
|
||||
( idnode_set_t *ins, api_idnode_grid_conf_t *conf )
|
||||
{
|
||||
channel_tag_t *ct;
|
||||
|
||||
TAILQ_FOREACH(ct, &channel_tags, ct_link)
|
||||
idnode_set_add(ins, (idnode_t*)ct, &conf->filter);
|
||||
}
|
||||
|
||||
static int
|
||||
api_channel_tag_create
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
htsmsg_t *conf;
|
||||
channel_tag_t *ct;
|
||||
|
||||
if (!(conf = htsmsg_get_map(args, "conf")))
|
||||
return EINVAL;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
ct = channel_tag_create(NULL, conf);
|
||||
if (ct)
|
||||
channel_tag_save(ct);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -110,7 +133,10 @@ void api_channel_init ( void )
|
|||
{ "channel/list", ACCESS_ANONYMOUS, api_channel_list, NULL },
|
||||
{ "channel/create", ACCESS_ADMIN, api_channel_create, NULL },
|
||||
|
||||
{ "channeltag/list", ACCESS_ANONYMOUS, api_channeltag_enum, NULL },
|
||||
{ "channeltag/class",ACCESS_ANONYMOUS, api_idnode_class, (void*)&channel_tag_class },
|
||||
{ "channeltag/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_channel_tag_grid },
|
||||
{ "channeltag/list", ACCESS_ANONYMOUS, api_channel_tag_list, NULL },
|
||||
{ "channeltag/create", ACCESS_ADMIN, api_channel_tag_create, NULL },
|
||||
|
||||
{ NULL },
|
||||
};
|
||||
|
|
276
src/channels.c
276
src/channels.c
|
@ -45,11 +45,9 @@
|
|||
struct channel_tree channels;
|
||||
|
||||
struct channel_tag_queue channel_tags;
|
||||
static dtable_t *channeltags_dtable;
|
||||
|
||||
static void channel_tag_init ( void );
|
||||
static void channel_tag_done ( void );
|
||||
static channel_tag_t *channel_tag_find(const char *id, int create);
|
||||
static void channel_tag_mapping_destroy(channel_tag_mapping_t *ctm,
|
||||
int flags);
|
||||
static void channel_tag_destroy(channel_tag_t *ct, int delconf);
|
||||
|
@ -138,7 +136,7 @@ channel_class_tags_get ( void *obj )
|
|||
|
||||
/* Add all */
|
||||
LIST_FOREACH(ctm, &ch->ch_ctms, ctm_channel_link)
|
||||
htsmsg_add_u32(m, NULL, ctm->ctm_tag->ct_identifier);
|
||||
htsmsg_add_str(m, NULL, idnode_uuid_as_str(&ctm->ctm_tag->ct_id));
|
||||
|
||||
return m;
|
||||
}
|
||||
|
@ -488,7 +486,7 @@ int
|
|||
channel_set_tags_by_list ( channel_t *ch, htsmsg_t *tags )
|
||||
{
|
||||
int save = 0;
|
||||
uint32_t u32;
|
||||
const char *uuid;
|
||||
channel_tag_mapping_t *ctm, *n;
|
||||
channel_tag_t *ct;
|
||||
htsmsg_field_t *f;
|
||||
|
@ -499,8 +497,8 @@ channel_set_tags_by_list ( channel_t *ch, htsmsg_t *tags )
|
|||
|
||||
/* Link */
|
||||
HTSMSG_FOREACH(f, tags)
|
||||
if (!htsmsg_field_get_u32(f, &u32)) {
|
||||
if ((ct = channel_tag_find_by_identifier(u32)))
|
||||
if ((uuid = htsmsg_field_get_str(f)) != NULL) {
|
||||
if ((ct = channel_tag_find_by_uuid(uuid)))
|
||||
save |= channel_tag_map(ch, ct);
|
||||
}
|
||||
|
||||
|
@ -757,37 +755,30 @@ channel_tag_mapping_destroy(channel_tag_mapping_t *ctm, int flags)
|
|||
/**
|
||||
*
|
||||
*/
|
||||
static channel_tag_t *
|
||||
channel_tag_find(const char *id, int create)
|
||||
channel_tag_t *
|
||||
channel_tag_create(const char *uuid, htsmsg_t *conf)
|
||||
{
|
||||
channel_tag_t *ct;
|
||||
char buf[20];
|
||||
static int tally;
|
||||
uint32_t u32;
|
||||
|
||||
if(id != NULL) {
|
||||
u32 = atoi(id);
|
||||
TAILQ_FOREACH(ct, &channel_tags, ct_link)
|
||||
if(ct->ct_identifier == u32)
|
||||
return ct;
|
||||
}
|
||||
|
||||
if(create == 0)
|
||||
return NULL;
|
||||
|
||||
ct = calloc(1, sizeof(channel_tag_t));
|
||||
if(id == NULL) {
|
||||
tally++;
|
||||
snprintf(buf, sizeof(buf), "%d", tally);
|
||||
id = buf;
|
||||
} else {
|
||||
tally = MAX(atoi(id), tally);
|
||||
|
||||
if (idnode_insert(&ct->ct_id, uuid, &channel_tag_class, IDNODE_SHORT_UUID)) {
|
||||
if (uuid)
|
||||
tvherror("channel", "invalid tag uuid '%s'", uuid);
|
||||
free(ct);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ct->ct_identifier = atoi(id);
|
||||
ct->ct_name = strdup("New tag");
|
||||
ct->ct_comment = strdup("");
|
||||
ct->ct_icon = strdup("");
|
||||
if (conf)
|
||||
idnode_load(&ct->ct_id, conf);
|
||||
|
||||
if (ct->ct_name == NULL)
|
||||
ct->ct_name = strdup("New tag");
|
||||
if (ct->ct_comment == NULL)
|
||||
ct->ct_comment = strdup("");
|
||||
if (ct->ct_icon == NULL)
|
||||
ct->ct_icon = strdup("");
|
||||
|
||||
TAILQ_INSERT_TAIL(&channel_tags, ct, ct_link);
|
||||
return ct;
|
||||
}
|
||||
|
@ -807,164 +798,104 @@ channel_tag_destroy(channel_tag_t *ct, int delconf)
|
|||
channel_tag_mapping_destroy(ctm, CTM_DESTROY_UPDATE_CHANNEL);
|
||||
channel_save(ch);
|
||||
}
|
||||
hts_settings_remove("channeltags/%s", idnode_uuid_as_str(&ct->ct_id));
|
||||
}
|
||||
|
||||
if(ct->ct_enabled && !ct->ct_internal)
|
||||
htsp_tag_delete(ct);
|
||||
|
||||
TAILQ_REMOVE(&channel_tags, ct, ct_link);
|
||||
idnode_unlink(&ct->ct_id);
|
||||
|
||||
free(ct->ct_name);
|
||||
free(ct->ct_comment);
|
||||
free(ct->ct_icon);
|
||||
TAILQ_REMOVE(&channel_tags, ct, ct_link);
|
||||
free(ct);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static htsmsg_t *
|
||||
channel_tag_record_build(channel_tag_t *ct)
|
||||
void
|
||||
channel_tag_save(channel_tag_t *ct)
|
||||
{
|
||||
htsmsg_t *e = htsmsg_create_map();
|
||||
htsmsg_add_u32(e, "enabled", !!ct->ct_enabled);
|
||||
htsmsg_add_u32(e, "internal", !!ct->ct_internal);
|
||||
htsmsg_add_u32(e, "titledIcon", !!ct->ct_titled_icon);
|
||||
|
||||
htsmsg_add_str(e, "name", ct->ct_name);
|
||||
htsmsg_add_str(e, "comment", ct->ct_comment);
|
||||
htsmsg_add_str(e, "icon", ct->ct_icon);
|
||||
htsmsg_add_u32(e, "id", ct->ct_identifier);
|
||||
return e;
|
||||
htsmsg_t *c = htsmsg_create_map();
|
||||
idnode_save(&ct->ct_id, c);
|
||||
hts_settings_save(c, "channeltags/%s", idnode_uuid_as_str(&ct->ct_id));
|
||||
htsmsg_destroy(c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static htsmsg_t *
|
||||
channel_tag_record_get_all(void *opaque)
|
||||
/* **************************************************************************
|
||||
* Channel Tag Class definition
|
||||
* **************************************************************************/
|
||||
|
||||
static void
|
||||
channel_tag_class_save(idnode_t *self)
|
||||
{
|
||||
htsmsg_t *r = htsmsg_create_list();
|
||||
channel_tag_t *ct;
|
||||
|
||||
TAILQ_FOREACH(ct, &channel_tags, ct_link)
|
||||
htsmsg_add_msg(r, NULL, channel_tag_record_build(ct));
|
||||
|
||||
return r;
|
||||
channel_tag_save((channel_tag_t *)self);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static htsmsg_t *
|
||||
channel_tag_record_get(void *opaque, const char *id)
|
||||
static void
|
||||
channel_tag_class_delete(idnode_t *self)
|
||||
{
|
||||
channel_tag_t *ct;
|
||||
|
||||
if((ct = channel_tag_find(id, 0)) == NULL)
|
||||
return NULL;
|
||||
return channel_tag_record_build(ct);
|
||||
channel_tag_destroy((channel_tag_t *)self, 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static htsmsg_t *
|
||||
channel_tag_record_create(void *opaque)
|
||||
static const char *
|
||||
channel_tag_class_get_title (idnode_t *self)
|
||||
{
|
||||
return channel_tag_record_build(channel_tag_find(NULL, 1));
|
||||
channel_tag_t *ct = (channel_tag_t *)self;
|
||||
return ct->ct_name ?: "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static htsmsg_t *
|
||||
channel_tag_record_update(void *opaque, const char *id, htsmsg_t *values,
|
||||
int maycreate)
|
||||
{
|
||||
channel_tag_t *ct;
|
||||
uint32_t u32;
|
||||
int was_exposed, is_exposed;
|
||||
channel_tag_mapping_t *ctm;
|
||||
|
||||
if((ct = channel_tag_find(id, maycreate)) == NULL)
|
||||
return NULL;
|
||||
|
||||
tvh_str_update(&ct->ct_name, htsmsg_get_str(values, "name"));
|
||||
tvh_str_update(&ct->ct_comment, htsmsg_get_str(values, "comment"));
|
||||
tvh_str_update(&ct->ct_icon, htsmsg_get_str(values, "icon"));
|
||||
|
||||
if(!htsmsg_get_u32(values, "titledIcon", &u32))
|
||||
ct->ct_titled_icon = u32;
|
||||
|
||||
was_exposed = ct->ct_enabled && !ct->ct_internal;
|
||||
|
||||
if(!htsmsg_get_u32(values, "enabled", &u32))
|
||||
ct->ct_enabled = u32;
|
||||
|
||||
if(!htsmsg_get_u32(values, "internal", &u32))
|
||||
ct->ct_internal = u32;
|
||||
|
||||
is_exposed = ct->ct_enabled && !ct->ct_internal;
|
||||
|
||||
/* We only export tags to HTSP if enabled == true and internal == false,
|
||||
thus, it's not as simple as just sending updates here.
|
||||
Depending on how the flags transition we add update or delete tags */
|
||||
|
||||
if(was_exposed == 0 && is_exposed == 1) {
|
||||
htsp_tag_add(ct);
|
||||
|
||||
LIST_FOREACH(ctm, &ct->ct_ctms, ctm_tag_link)
|
||||
htsp_channel_update(ctm->ctm_channel);
|
||||
|
||||
} else if(was_exposed == 1 && is_exposed == 1)
|
||||
htsp_tag_update(ct);
|
||||
else if(was_exposed == 1 && is_exposed == 0) {
|
||||
|
||||
LIST_FOREACH(ctm, &ct->ct_ctms, ctm_tag_link)
|
||||
htsp_channel_update(ctm->ctm_channel);
|
||||
|
||||
htsp_tag_delete(ct);
|
||||
const idclass_t channel_tag_class = {
|
||||
.ic_class = "channeltag",
|
||||
.ic_caption = "Channel Tag",
|
||||
.ic_save = channel_tag_class_save,
|
||||
.ic_get_title = channel_tag_class_get_title,
|
||||
.ic_delete = channel_tag_class_delete,
|
||||
.ic_properties = (const property_t[]) {
|
||||
{
|
||||
.type = PT_BOOL,
|
||||
.id = "enabled",
|
||||
.name = "Enabled",
|
||||
.off = offsetof(channel_tag_t, ct_enabled),
|
||||
},
|
||||
{
|
||||
.type = PT_STR,
|
||||
.id = "name",
|
||||
.name = "Name",
|
||||
.off = offsetof(channel_tag_t, ct_name),
|
||||
},
|
||||
{
|
||||
.type = PT_BOOL,
|
||||
.id = "internal",
|
||||
.name = "Internal",
|
||||
.off = offsetof(channel_tag_t, ct_internal),
|
||||
},
|
||||
{
|
||||
.type = PT_STR,
|
||||
.id = "icon",
|
||||
.name = "Icon (full URL)",
|
||||
.off = offsetof(channel_tag_t, ct_icon),
|
||||
},
|
||||
{
|
||||
.type = PT_BOOL,
|
||||
.id = "titled_icon",
|
||||
.name = "Icon has title",
|
||||
.off = offsetof(channel_tag_t, ct_titled_icon),
|
||||
},
|
||||
{
|
||||
.type = PT_STR,
|
||||
.id = "comment",
|
||||
.name = "Comment",
|
||||
.off = offsetof(channel_tag_t, ct_comment),
|
||||
},
|
||||
{}
|
||||
}
|
||||
return channel_tag_record_build(ct);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int
|
||||
channel_tag_record_delete(void *opaque, const char *id)
|
||||
{
|
||||
channel_tag_t *ct;
|
||||
|
||||
if((ct = channel_tag_find(id, 0)) == NULL)
|
||||
return -1;
|
||||
channel_tag_destroy(ct, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static const dtable_class_t channel_tags_dtc = {
|
||||
.dtc_record_get = channel_tag_record_get,
|
||||
.dtc_record_get_all = channel_tag_record_get_all,
|
||||
.dtc_record_create = channel_tag_record_create,
|
||||
.dtc_record_update = channel_tag_record_update,
|
||||
.dtc_record_delete = channel_tag_record_delete,
|
||||
.dtc_read_access = ACCESS_ADMIN,
|
||||
.dtc_write_access = ACCESS_ADMIN,
|
||||
.dtc_mutex = &global_lock,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -972,7 +903,6 @@ channel_tag_t *
|
|||
channel_tag_find_by_name(const char *name, int create)
|
||||
{
|
||||
channel_tag_t *ct;
|
||||
char str[50];
|
||||
|
||||
TAILQ_FOREACH(ct, &channel_tags, ct_link)
|
||||
if(!strcasecmp(ct->ct_name, name))
|
||||
|
@ -981,14 +911,11 @@ channel_tag_find_by_name(const char *name, int create)
|
|||
if(!create)
|
||||
return NULL;
|
||||
|
||||
ct = channel_tag_find(NULL, 1);
|
||||
ct = channel_tag_create(NULL, NULL);
|
||||
ct->ct_enabled = 1;
|
||||
tvh_str_update(&ct->ct_name, name);
|
||||
|
||||
snprintf(str, sizeof(str), "%d", ct->ct_identifier);
|
||||
dtable_record_store(channeltags_dtable, str, channel_tag_record_build(ct));
|
||||
|
||||
dtable_store_changed(channeltags_dtable);
|
||||
channel_tag_save(ct);
|
||||
return ct;
|
||||
}
|
||||
|
||||
|
@ -1001,19 +928,31 @@ channel_tag_find_by_identifier(uint32_t id) {
|
|||
channel_tag_t *ct;
|
||||
|
||||
TAILQ_FOREACH(ct, &channel_tags, ct_link) {
|
||||
if(ct->ct_identifier == id)
|
||||
if(idnode_get_short_uuid(&ct->ct_id) == id)
|
||||
return ct;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init / Done
|
||||
*/
|
||||
|
||||
static void
|
||||
channel_tag_init ( void )
|
||||
{
|
||||
htsmsg_t *c, *m;
|
||||
htsmsg_field_t *f;
|
||||
|
||||
TAILQ_INIT(&channel_tags);
|
||||
channeltags_dtable = dtable_create(&channel_tags_dtc, "channeltags", NULL);
|
||||
dtable_load(channeltags_dtable);
|
||||
if ((c = hts_settings_load_r(1, "channeltags")) != NULL) {
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(m = htsmsg_field_get_map(f))) continue;
|
||||
(void)channel_tag_create(f->hmf_name, m);
|
||||
}
|
||||
htsmsg_destroy(c);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1025,5 +964,4 @@ channel_tag_done ( void )
|
|||
while ((ct = TAILQ_FIRST(&channel_tags)) != NULL)
|
||||
channel_tag_destroy(ct, 0);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
dtable_delete("channeltags");
|
||||
}
|
||||
|
|
|
@ -79,17 +79,22 @@ typedef struct channel
|
|||
* Channel tag
|
||||
*/
|
||||
typedef struct channel_tag {
|
||||
|
||||
idnode_t ct_id;
|
||||
|
||||
TAILQ_ENTRY(channel_tag) ct_link;
|
||||
|
||||
int ct_enabled;
|
||||
int ct_internal;
|
||||
int ct_titled_icon;
|
||||
int ct_identifier;
|
||||
char *ct_name;
|
||||
char *ct_comment;
|
||||
char *ct_icon;
|
||||
|
||||
struct channel_tag_mapping_list ct_ctms;
|
||||
|
||||
struct dvr_autorec_entry_list ct_autorecs;
|
||||
|
||||
} channel_tag_t;
|
||||
|
||||
/**
|
||||
|
@ -120,6 +125,7 @@ typedef struct channel_service_mapping {
|
|||
} channel_service_mapping_t;
|
||||
|
||||
extern const idclass_t channel_class;
|
||||
extern const idclass_t channel_tag_class;
|
||||
|
||||
void channel_init(void);
|
||||
void channel_done(void);
|
||||
|
@ -145,10 +151,17 @@ channel_t *channel_find_by_number(int no);
|
|||
int channel_set_tags_by_list ( channel_t *ch, htsmsg_t *tags );
|
||||
int channel_set_services_by_list ( channel_t *ch, htsmsg_t *svcs );
|
||||
|
||||
channel_tag_t *channel_tag_create(const char *uuid, htsmsg_t *conf);
|
||||
|
||||
channel_tag_t *channel_tag_find_by_name(const char *name, int create);
|
||||
|
||||
channel_tag_t *channel_tag_find_by_identifier(uint32_t id);
|
||||
|
||||
static inline channel_tag_t *channel_tag_find_by_uuid(const char *uuid)
|
||||
{ return (channel_tag_t*)idnode_find(uuid, &channel_tag_class); }
|
||||
|
||||
void channel_tag_save(channel_tag_t *ct);
|
||||
|
||||
int channel_access(channel_t *ch, struct access *a, const char *username);
|
||||
|
||||
int channel_tag_map(channel_t *ch, channel_tag_t *ct);
|
||||
|
|
|
@ -2287,7 +2287,7 @@ void epg_query(epg_query_result_t *eqr, const char *channel, const char *tag,
|
|||
epg_genre_t *genre, const char *title, const char *lang, int min_duration, int max_duration)
|
||||
{
|
||||
channel_t *ch = channel ? channel_find(channel) : NULL;
|
||||
channel_tag_t *ct = tag ? channel_tag_find_by_name(tag, 0) : NULL;
|
||||
channel_tag_t *ct = tag ? channel_tag_find_by_uuid(tag) : NULL;
|
||||
|
||||
epg_query0(eqr, ch, ct, genre, title, lang, min_duration, max_duration);
|
||||
}
|
||||
|
|
|
@ -575,7 +575,7 @@ htsp_build_channel(channel_t *ch, const char *method, htsp_connection_t *htsp)
|
|||
LIST_FOREACH(ctm, &ch->ch_ctms, ctm_channel_link) {
|
||||
ct = ctm->ctm_tag;
|
||||
if(ct->ct_enabled && !ct->ct_internal)
|
||||
htsmsg_add_u32(tags, NULL, ct->ct_identifier);
|
||||
htsmsg_add_u32(tags, NULL, idnode_get_short_uuid(&ct->ct_id));
|
||||
}
|
||||
|
||||
LIST_FOREACH(csm, &ch->ch_services, csm_chn_link) {
|
||||
|
@ -607,7 +607,7 @@ htsp_build_tag(channel_tag_t *ct, const char *method, int include_channels)
|
|||
htsmsg_t *out = htsmsg_create_map();
|
||||
htsmsg_t *members = include_channels ? htsmsg_create_list() : NULL;
|
||||
|
||||
htsmsg_add_u32(out, "tagId", ct->ct_identifier);
|
||||
htsmsg_add_u32(out, "tagId", idnode_get_short_uuid(&ct->ct_id));
|
||||
|
||||
htsmsg_add_str(out, "tagName", ct->ct_name);
|
||||
htsmsg_add_str(out, "tagIcon", ct->ct_icon);
|
||||
|
@ -2461,7 +2461,7 @@ void
|
|||
htsp_tag_delete(channel_tag_t *ct)
|
||||
{
|
||||
htsmsg_t *m = htsmsg_create_map();
|
||||
htsmsg_add_u32(m, "tagId", ct->ct_identifier);
|
||||
htsmsg_add_u32(m, "tagId", idnode_get_short_uuid(&ct->ct_id));
|
||||
htsmsg_add_str(m, "method", "tagDelete");
|
||||
htsp_async_send(m, HTSP_ASYNC_ON);
|
||||
}
|
||||
|
|
|
@ -502,50 +502,6 @@ extjs_epggrab(http_connection_t *hc, const char *remain, void *opaque)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int
|
||||
extjs_channeltags(http_connection_t *hc, const char *remain, void *opaque)
|
||||
{
|
||||
htsbuf_queue_t *hq = &hc->hc_reply;
|
||||
const char *op = http_arg_get(&hc->hc_req_args, "op");
|
||||
htsmsg_t *out, *array, *e;
|
||||
channel_tag_t *ct;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if(op != NULL && !strcmp(op, "listTags")) {
|
||||
|
||||
out = htsmsg_create_map();
|
||||
array = htsmsg_create_list();
|
||||
|
||||
TAILQ_FOREACH(ct, &channel_tags, ct_link) {
|
||||
if(!ct->ct_enabled)
|
||||
continue;
|
||||
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_u32(e, "identifier", ct->ct_identifier);
|
||||
htsmsg_add_str(e, "name", ct->ct_name);
|
||||
htsmsg_add_msg(array, NULL, e);
|
||||
}
|
||||
|
||||
htsmsg_add_msg(out, "entries", array);
|
||||
|
||||
} else {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_BAD_REQUEST;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
htsmsg_json_serialize(out, hq, 0);
|
||||
htsmsg_destroy(out);
|
||||
http_output_content(hc, "text/x-json; charset=UTF-8");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -1752,7 +1708,6 @@ extjs_start(void)
|
|||
http_path_add("/capabilities", NULL, extjs_capabilities, ACCESS_WEB_INTERFACE);
|
||||
http_path_add("/tablemgr", NULL, extjs_tablemgr, ACCESS_WEB_INTERFACE);
|
||||
http_path_add("/epggrab", NULL, extjs_epggrab, ACCESS_WEB_INTERFACE);
|
||||
http_path_add("/channeltags", NULL, extjs_channeltags, ACCESS_WEB_INTERFACE);
|
||||
http_path_add("/confignames", NULL, extjs_confignames, ACCESS_WEB_INTERFACE);
|
||||
http_path_add("/epg", NULL, extjs_epg, ACCESS_WEB_INTERFACE);
|
||||
http_path_add("/epgrelated", NULL, extjs_epgrelated, ACCESS_WEB_INTERFACE);
|
||||
|
|
|
@ -2,26 +2,25 @@
|
|||
* Channel tags
|
||||
*/
|
||||
insertChannelTagsClearOption = function( scope, records, options ){
|
||||
var placeholder = Ext.data.Record.create(['identifier', 'name']);
|
||||
scope.insert(0,new placeholder({identifier: '-1', name: '(Clear filter)'}));
|
||||
var placeholder = Ext.data.Record.create(['key', 'val']);
|
||||
scope.insert(0,new placeholder({key: '-1', val: '(Clear filter)'}));
|
||||
};
|
||||
|
||||
tvheadend.channelTags = new Ext.data.JsonStore({
|
||||
autoLoad: true,
|
||||
url: 'api/channeltag/list',
|
||||
root: 'entries',
|
||||
fields: ['identifier', 'name'],
|
||||
id: 'identifier',
|
||||
url: 'channeltags',
|
||||
baseParams: {
|
||||
op: 'listTags'
|
||||
fields: ['key', 'val'],
|
||||
id: 'key',
|
||||
autoLoad: true,
|
||||
sortInfo: {
|
||||
field: 'val',
|
||||
direction: 'ASC',
|
||||
},
|
||||
listeners: {
|
||||
'load': insertChannelTagsClearOption
|
||||
}
|
||||
});
|
||||
|
||||
tvheadend.channelTags.setDefaultSort('name', 'ASC');
|
||||
|
||||
tvheadend.comet.on('channeltags', function(m) {
|
||||
if (m.reload != null)
|
||||
tvheadend.channelTags.reload();
|
||||
|
@ -59,7 +58,7 @@ tvheadend.comet.on('channels', function(m) {
|
|||
tvheadend.channels.reload();
|
||||
});
|
||||
|
||||
tvheadend.channel_tab = function(panel)
|
||||
tvheadend.channel_tab = function(panel, index)
|
||||
{
|
||||
function assign_low_number() {
|
||||
var tab = panel.getActiveTab();
|
||||
|
@ -191,7 +190,7 @@ tvheadend.channel_tab = function(panel)
|
|||
comet: 'channel',
|
||||
titleS: 'Channel',
|
||||
titleP: 'Channels',
|
||||
tabIndex: 0,
|
||||
tabIndex: index,
|
||||
help: function() {
|
||||
new tvheadend.help('Channels', 'config_channels.html');
|
||||
},
|
||||
|
|
|
@ -1,48 +1,27 @@
|
|||
tvheadend.cteditor = function() {
|
||||
var fm = Ext.form;
|
||||
/*
|
||||
* Channel Tag
|
||||
*/
|
||||
|
||||
var cm = new Ext.grid.ColumnModel({
|
||||
defaultSortable: true,
|
||||
columns: [{
|
||||
xtype: 'checkcolumn',
|
||||
header: "Enabled",
|
||||
dataIndex: 'enabled',
|
||||
width: 60
|
||||
}, {
|
||||
header: "Name",
|
||||
dataIndex: 'name',
|
||||
editor: new fm.TextField({
|
||||
allowBlank: false
|
||||
})
|
||||
}, {
|
||||
xtype: 'checkcolumn',
|
||||
header: "Internal",
|
||||
dataIndex: 'internal',
|
||||
width: 100
|
||||
}, {
|
||||
header: "Icon (full URL)",
|
||||
dataIndex: 'icon',
|
||||
width: 400,
|
||||
editor: new fm.TextField({})
|
||||
}, {
|
||||
xtype: 'checkcolumn',
|
||||
header: "Icon has title",
|
||||
dataIndex: 'titledIcon',
|
||||
width: 100,
|
||||
tooltip: 'Set this if the supplied icon has a title embedded. '
|
||||
+ 'This will tell displaying application not to superimpose title '
|
||||
+ 'on top of logo.'
|
||||
}, {
|
||||
header: "Comment",
|
||||
dataIndex: 'comment',
|
||||
width: 400,
|
||||
editor: new fm.TextField({})
|
||||
}]});
|
||||
tvheadend.cteditor = function(panel, index)
|
||||
{
|
||||
tvheadend.idnode_grid(panel, {
|
||||
url: 'api/channeltag',
|
||||
comet: 'channeltag',
|
||||
titleS: 'Channel Tag',
|
||||
titleP: 'Channel Tags',
|
||||
tabIndex: index,
|
||||
add: {
|
||||
url: 'api/channeltag',
|
||||
create: { }
|
||||
},
|
||||
sort: {
|
||||
field: 'name',
|
||||
direction: 'ASC'
|
||||
},
|
||||
help: function() {
|
||||
new tvheadend.help('Channel Tags', 'config_tags.html');
|
||||
},
|
||||
});
|
||||
|
||||
var ChannelTagRecord = Ext.data.Record.create([
|
||||
'enabled', 'name', 'internal', 'icon', 'comment', 'titledIcon']);
|
||||
|
||||
return new tvheadend.tableEditor('Channel Tags', 'channeltags', cm,
|
||||
ChannelTagRecord, [],
|
||||
null, 'config_tags.html', 'tags');
|
||||
return panel;
|
||||
};
|
||||
|
|
|
@ -639,7 +639,7 @@ tvheadend.autoreceditor = function() {
|
|||
header: "Channel tag",
|
||||
dataIndex: 'tag',
|
||||
editor: new Ext.form.ComboBox({
|
||||
displayField: 'name',
|
||||
displayField: 'val',
|
||||
store: tvheadend.channelTags,
|
||||
mode: 'local',
|
||||
editable: true,
|
||||
|
|
|
@ -395,7 +395,7 @@ tvheadend.epg = function() {
|
|||
|
||||
var epgFilterChannelTags = new Ext.form.ComboBox({
|
||||
width: 200,
|
||||
displayField: 'name',
|
||||
displayField: 'val',
|
||||
store: tvheadend.channelTags,
|
||||
mode: 'local',
|
||||
editable: true,
|
||||
|
@ -511,10 +511,10 @@ tvheadend.epg = function() {
|
|||
});
|
||||
|
||||
epgFilterChannelTags.on('select', function(c, r) {
|
||||
if (r.data.identifier == -1)
|
||||
if (r.data.key == -1)
|
||||
clearChannelTagsFilter();
|
||||
else if (epgStore.baseParams.tag !== r.data.name)
|
||||
epgStore.baseParams.tag = r.data.name;
|
||||
else if (epgStore.baseParams.tag !== r.data.key)
|
||||
epgStore.baseParams.tag = r.data.key;
|
||||
epgStore.reload();
|
||||
});
|
||||
|
||||
|
|
|
@ -196,6 +196,7 @@ tvheadend.IdNodeField = function(conf)
|
|||
t.push(d[i]);
|
||||
}
|
||||
}
|
||||
t.sort();
|
||||
v = t.join(',');
|
||||
}
|
||||
return v;
|
||||
|
|
|
@ -259,12 +259,11 @@ function accessUpdate(o) {
|
|||
autoScroll: true,
|
||||
title: 'Channel / EPG',
|
||||
iconCls: 'television',
|
||||
items: [
|
||||
new tvheadend.cteditor,
|
||||
new tvheadend.epggrab
|
||||
]
|
||||
items: []
|
||||
});
|
||||
tvheadend.channel_tab(tvheadend.conf_chepg);
|
||||
tvheadend.channel_tab(tvheadend.conf_chepg, 0);
|
||||
tvheadend.cteditor(tvheadend.conf_chepg, 1);
|
||||
tvheadend.conf_chepg.insert(2, new tvheadend.epggrab);
|
||||
tabs1.push(tvheadend.conf_chepg);
|
||||
|
||||
/* DVR / Timeshift */
|
||||
|
|
|
@ -477,7 +477,7 @@ http_tag_list_playlist(http_connection_t *hc)
|
|||
if(!ct->ct_enabled || ct->ct_internal)
|
||||
continue;
|
||||
|
||||
snprintf(buf, sizeof(buf), "/playlist/tagid/%d", ct->ct_identifier);
|
||||
snprintf(buf, sizeof(buf), "/playlist/tagid/%d", idnode_get_short_uuid(&ct->ct_id));
|
||||
htsbuf_qprintf(hq, "#EXTINF:-1,%s\n", ct->ct_name);
|
||||
htsbuf_qprintf(hq, "http://%s%s?ticket=%s", host, buf,
|
||||
access_ticket_create(buf));
|
||||
|
|
Loading…
Add table
Reference in a new issue