diff --git a/src/channels.c b/src/channels.c index 802787a1..686c3b16 100644 --- a/src/channels.c +++ b/src/channels.c @@ -159,12 +159,11 @@ channel_set_name(channel_t *ch, const char *name) * */ static channel_t * -channel_create(const char *name, int number) +channel_create2(const char *name, int number) { channel_t *ch, *x; int id; - - if (!name || !*name) return NULL; + char buf[32]; ch = RB_LAST(&channel_identifier_tree); if(ch == NULL) { @@ -173,6 +172,11 @@ channel_create(const char *name, int number) id = ch->ch_id + 1; } + if (!name || !*name) { + snprintf(buf, sizeof(buf), "Channel %d", id); + name = buf; + } + ch = calloc(1, sizeof(channel_t)); channel_set_name(ch, name); ch->ch_number = number; @@ -189,6 +193,15 @@ channel_create(const char *name, int number) return ch; } +/** + * + */ +channel_t * +channel_create ( void ) +{ + return channel_create2(NULL, 0); +} + /** * */ @@ -197,13 +210,15 @@ channel_find_by_name(const char *name, int create, int channel_number) { channel_t skel, *ch; + if (!name || !*name) return NULL; + lock_assert(&global_lock); skel.ch_name = (char *)name; ch = RB_FIND(&channel_name_tree, &skel, ch_name_link, channelcmp); if(ch != NULL || create == 0) return ch; - return channel_create(name, channel_number); + return channel_create2(name, channel_number); } diff --git a/src/channels.h b/src/channels.h index 316d3e88..b0a361db 100644 --- a/src/channels.h +++ b/src/channels.h @@ -104,6 +104,8 @@ typedef struct channel_tag_mapping { void channels_init(void); +channel_t *channel_create(void); + channel_t *channel_find_by_name(const char *name, int create, int number); channel_t *channel_find_by_identifier(int id); diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 9d18d069..b8d82134 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -391,21 +391,73 @@ extjs_channels_update(htsmsg_t *in) /** * */ -static int -extjs_channels(http_connection_t *hc, const char *remain, void *opaque) +static htsmsg_t * +build_record_channel ( channel_t *ch ) { - htsbuf_queue_t *hq = &hc->hc_reply; - htsmsg_t *array, *c; - channel_t *ch; char buf[1024]; channel_tag_mapping_t *ctm; - const char *op = http_arg_get(&hc->hc_req_args, "op"); - const char *entries = http_arg_get(&hc->hc_req_args, "entries"); + htsmsg_t *c; char *epggrabsrc; epggrab_module_t *mod; epggrab_channel_t *ec; epggrab_channel_link_t *ecl; + c = htsmsg_create_map(); + htsmsg_add_str(c, "name", ch->ch_name); + htsmsg_add_u32(c, "chid", ch->ch_id); + + if(ch->ch_icon != NULL) + htsmsg_add_str(c, "ch_icon", ch->ch_icon); + + buf[0] = 0; + LIST_FOREACH(ctm, &ch->ch_ctms, ctm_channel_link) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + "%s%d", strlen(buf) == 0 ? "" : ",", + ctm->ctm_tag->ct_identifier); + } + htsmsg_add_str(c, "tags", buf); + + htsmsg_add_s32(c, "epg_pre_start", ch->ch_dvr_extra_time_pre); + htsmsg_add_s32(c, "epg_post_end", ch->ch_dvr_extra_time_post); + htsmsg_add_s32(c, "number", ch->ch_number); + + epggrabsrc = NULL; + LIST_FOREACH(mod, &epggrab_modules, link) { + if (mod->type != EPGGRAB_OTA && mod->channels) { + RB_FOREACH(ec, mod->channels, link) { + LIST_FOREACH(ecl, &ec->channels, link) { + if (ecl->channel == ch) { + char id[100]; + sprintf(id, "%s|%s", mod->id, ec->id); + if (!epggrabsrc) { + epggrabsrc = strdup(id); + } else { + epggrabsrc = realloc(epggrabsrc, strlen(epggrabsrc) + 2 + strlen(id)); + strcat(epggrabsrc, ","); + strcat(epggrabsrc, id); + } + } + } + } + } + } + if (epggrabsrc) htsmsg_add_str(c, "epggrabsrc", epggrabsrc); + free(epggrabsrc); + return c; +} + +/** + * + */ +static int +extjs_channels(http_connection_t *hc, const char *remain, void *opaque) +{ + htsbuf_queue_t *hq = &hc->hc_reply; + htsmsg_t *array; + channel_t *ch; + const char *op = http_arg_get(&hc->hc_req_args, "op"); + const char *entries = http_arg_get(&hc->hc_req_args, "entries"); + if(op == NULL) return 400; @@ -420,53 +472,14 @@ extjs_channels(http_connection_t *hc, const char *remain, void *opaque) array = htsmsg_create_list(); RB_FOREACH(ch, &channel_name_tree, ch_name_link) { - c = htsmsg_create_map(); - htsmsg_add_str(c, "name", ch->ch_name); - htsmsg_add_u32(c, "chid", ch->ch_id); - - if(ch->ch_icon != NULL) - htsmsg_add_str(c, "ch_icon", ch->ch_icon); - - buf[0] = 0; - LIST_FOREACH(ctm, &ch->ch_ctms, ctm_channel_link) { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "%s%d", strlen(buf) == 0 ? "" : ",", - ctm->ctm_tag->ct_identifier); - } - htsmsg_add_str(c, "tags", buf); - - htsmsg_add_s32(c, "epg_pre_start", ch->ch_dvr_extra_time_pre); - htsmsg_add_s32(c, "epg_post_end", ch->ch_dvr_extra_time_post); - htsmsg_add_s32(c, "number", ch->ch_number); - - epggrabsrc = NULL; - LIST_FOREACH(mod, &epggrab_modules, link) { - if (mod->type != EPGGRAB_OTA && mod->channels) { - RB_FOREACH(ec, mod->channels, link) { - LIST_FOREACH(ecl, &ec->channels, link) { - if (ecl->channel == ch) { - char id[100]; - sprintf(id, "%s|%s", mod->id, ec->id); - if (!epggrabsrc) { - epggrabsrc = strdup(id); - } else { - epggrabsrc = realloc(epggrabsrc, strlen(epggrabsrc) + 2 + strlen(id)); - strcat(epggrabsrc, ","); - strcat(epggrabsrc, id); - } - } - } - } - } - } - if (epggrabsrc) htsmsg_add_str(c, "epggrabsrc", epggrabsrc); - free(epggrabsrc); - - htsmsg_add_msg(array, NULL, c); + htsmsg_add_msg(array, NULL, build_record_channel(ch)); } htsmsg_add_msg(out, "entries", array); + } else if(!strcmp(op, "create")) { + out = build_record_channel(channel_create()); + } else if(!strcmp(op, "delete") && in != NULL) { extjs_channels_delete(in); diff --git a/src/webui/static/app/chconf.js b/src/webui/static/app/chconf.js index fcffbf31..2549a7f9 100644 --- a/src/webui/static/app/chconf.js +++ b/src/webui/static/app/chconf.js @@ -21,11 +21,14 @@ tvheadend.comet.on('channeltags', function(m) { /** * Channels */ +tvheadend.channelrec = new Ext.data.Record.create( + [ 'name', 'chid', 'epggrabsrc', 'tags', 'ch_icon', 'epg_pre_start', + 'epg_post_end', 'number' ]); + tvheadend.channels = new Ext.data.JsonStore({ autoLoad : true, root : 'entries', - fields : [ 'name', 'chid', 'epggrabsrc', 'tags', 'ch_icon', 'epg_pre_start', - 'epg_post_end', 'number' ], + fields : tvheadend.channelrec, id : 'chid', sortInfo : { field : 'number', @@ -243,6 +246,25 @@ tvheadend.chconf = function() { } } + function addRecord() { + Ext.Ajax.request({ + url : "channels", + params : { + op : "create" + }, + failure : function(response, options) { + Ext.MessageBox.alert('Server Error', 'Unable to create new record'); + }, + success : function(response, options) { + var responseData = Ext.util.JSON.decode(response.responseText); + var p = new tvheadend.channelrec(responseData, responseData.id); + grid.stopEditing(); + store.insert(0, p) + grid.startEditing(0, 0); + } + }) + } + function deleteRecord(btn) { if (btn == 'yes') { var selectedKeys = grid.selModel.selections.keys; @@ -288,6 +310,13 @@ tvheadend.chconf = function() { singleSelect : false }); + var addBtn = new Ext.Toolbar.Button({ + tooltop : 'Add a new channel', + iconCls : 'add', + text : 'Add channel', + handler : addRecord, + }); + var delBtn = new Ext.Toolbar.Button({ tooltip : 'Delete one or more selected channels', iconCls : 'remove', @@ -330,7 +359,7 @@ tvheadend.chconf = function() { forceFit : true }, selModel : selModel, - tbar : [ delBtn, '-', saveBtn, rejectBtn, '->', { + tbar : [ addBtn, '-', delBtn, '-', saveBtn, rejectBtn, '->', { text : 'Help', handler : function() { new tvheadend.help('Channels', 'config_channels.html');