]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Add support for channel tags (except for being there they don't add
authorAndreas Öman <andreas@lonelycoder.com>
Sat, 6 Sep 2008 19:08:10 +0000 (19:08 +0000)
committerAndreas Öman <andreas@lonelycoder.com>
Sat, 6 Sep 2008 19:08:10 +0000 (19:08 +0000)
any functionality a.t.m)

channels.c
channels.h
webui/extjs.c
webui/static/app/cteditor.js [new file with mode: 0644]
webui/static/app/tvheadend.js

index 6461fa7376e4666312a3e50f54415930d4392eb9..d129216196d9678e6a16197cfed934a7cf7c9dec 100644 (file)
 #include "pvr.h"
 #include "autorec.h"
 #include "xmltv.h"
+#include "dtable.h"
 
 struct channel_list channels_not_xmltv_mapped;
 
 struct channel_tree channel_name_tree;
 static struct channel_tree channel_identifier_tree;
+static struct channel_tag_queue channel_tags;
 
 static int
 dictcmp(const char *a, const char *b)
@@ -258,17 +260,6 @@ channels_load(void)
 }
 
 
-/**
- *
- */
-void
-channels_init(void)
-{
-  channels_load();
-}
-
-
-
 /**
  * Write out a config file for a channel
  */
@@ -436,3 +427,198 @@ channel_set_xmltv_source(channel_t *ch, xmltv_channel_t *xc)
   ch->ch_xc = xc;
   channel_save(ch);
 }
+
+
+
+/**
+ *
+ */
+static void
+channel_tag_mapping_destroy(channel_tag_mapping_t *ctm)
+{
+  LIST_REMOVE(ctm, ctm_channel_link);
+  LIST_REMOVE(ctm, ctm_tag_link);
+  free(ctm);
+}
+
+
+/**
+ *
+ */
+static channel_tag_t *
+channel_tag_find(const char *id, int create)
+{
+  channel_tag_t *ct;
+  char buf[20];
+  static int tally;
+
+  if(id != NULL) {
+    TAILQ_FOREACH(ct, &channel_tags, ct_link)
+      if(!strcmp(ct->ct_identifier, id))
+       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 = atoi(id);
+  }
+
+  ct->ct_identifier = strdup(id);
+  ct->ct_name = strdup("New tag");
+  ct->ct_comment = strdup("");
+  TAILQ_INSERT_TAIL(&channel_tags, ct, ct_link);
+  return ct;
+}
+
+
+/**
+ *
+ */
+static void
+channel_tag_destroy(channel_tag_t *ct)
+{
+  channel_tag_mapping_t *ctm;
+
+  while((ctm = LIST_FIRST(&ct->ct_ctms)) != NULL)
+    channel_tag_mapping_destroy(ctm);
+
+  free(ct->ct_identifier);
+  free(ct->ct_name);
+  free(ct->ct_comment);
+  TAILQ_REMOVE(&channel_tags, ct, ct_link);
+  free(ct);
+}
+
+
+/**
+ *
+ */
+static htsmsg_t *
+channel_tag_record_build(channel_tag_t *ct)
+{
+  htsmsg_t *e = htsmsg_create();
+  htsmsg_add_u32(e, "enabled",  !!ct->ct_enabled);
+  htsmsg_add_u32(e, "internal",  !!ct->ct_internal);
+
+  htsmsg_add_str(e, "name", ct->ct_name);
+  htsmsg_add_str(e, "comment", ct->ct_comment);
+  htsmsg_add_str(e, "id", ct->ct_identifier);
+  return e;
+}
+
+
+/**
+ *
+ */
+static htsmsg_t *
+channel_tag_record_get_all(void *opaque)
+{
+  htsmsg_t *r = htsmsg_create_array();
+  channel_tag_t *ct;
+
+  TAILQ_FOREACH(ct, &channel_tags, ct_link)
+    htsmsg_add_msg(r, NULL, channel_tag_record_build(ct));
+
+  return r;
+}
+
+
+/**
+ *
+ */
+static htsmsg_t *
+channel_tag_record_get(void *opaque, const char *id)
+{
+  channel_tag_t *ct;
+
+  if((ct = channel_tag_find(id, 0)) == NULL)
+    return NULL;
+  return channel_tag_record_build(ct);
+}
+
+
+/**
+ *
+ */
+static htsmsg_t *
+channel_tag_record_create(void *opaque)
+{
+  return channel_tag_record_build(channel_tag_find(NULL, 1));
+}
+
+
+/**
+ *
+ */
+static htsmsg_t *
+channel_tag_record_update(void *opaque, const char *id, htsmsg_t *values, 
+                         int maycreate)
+{
+  channel_tag_t *ct;
+  uint32_t u32;
+
+  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"));
+
+ if(!htsmsg_get_u32(values, "enabled", &u32))
+    ct->ct_enabled = u32;
+
+ if(!htsmsg_get_u32(values, "internal", &u32))
+    ct->ct_internal = u32;
+
+ 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);
+  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,
+};
+
+
+/**
+ *
+ */
+void
+channels_init(void)
+{
+  dtable_t *dt;
+
+  TAILQ_INIT(&channel_tags);
+
+  dt = dtable_create(&channel_tags_dtc, "channeltags", NULL);
+  dtable_load(dt);
+
+  channels_load();
+}
index e06a8693e9b4e0d89f1790449b23c008915c48f5..49ad4750d513a40c87854089b5db7d484427345a 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef CHANNELS_H
 #define CHANNELS_H
 
+LIST_HEAD(channel_tag_mapping_list, channel_tag_mapping);
+TAILQ_HEAD(channel_tag_queue, channel_tag);
 
 /*
  * Channel definition
@@ -57,8 +59,39 @@ typedef struct channel {
   struct xmltv_channel *ch_xc;
   LIST_ENTRY(channel) ch_xc_link;
 
+  struct channel_tag_mapping_list ch_ctms;
+
 } channel_t;
 
+
+/**
+ * Channel tag
+ */
+typedef struct channel_tag {
+  TAILQ_ENTRY(channel_tag) ct_link;
+  int ct_enabled;
+  int ct_internal;
+  char *ct_name;
+  char *ct_comment;
+  char *ct_identifier;
+  struct channel_tag_mapping_list ct_ctms;
+} channel_tag_t;
+
+
+/**
+ * Channel tag mapping
+ */
+typedef struct channel_tag_mapping {
+  LIST_ENTRY(channel_tag_mapping) ctm_channel_link;
+  channel_t *ctm_channel;
+  
+  LIST_ENTRY(channel_tag_mapping) ctm_tag_link;
+  channel_tag_t *ctm_tag;
+
+} channel_tag_mapping_t;
+
+
+
 void channels_init(void);
 
 channel_t *channel_find_by_name(const char *name, int create);
index 4b63ee149d3c389bd3c86d8b72bea2ad076d0aad..643a30d630a634afe99a14333c218eb3dc77dfa7 100644 (file)
@@ -104,6 +104,7 @@ extjs_root(http_connection_t *hc, const char *remain, void *opaque)
   /**
    * Load all components
    */
+  extjs_load(hq, "static/app/cteditor.js");
   extjs_load(hq, "static/app/acleditor.js");
   extjs_load(hq, "static/app/cwceditor.js");
   extjs_load(hq, "static/app/dvb.js");
diff --git a/webui/static/app/cteditor.js b/webui/static/app/cteditor.js
new file mode 100644 (file)
index 0000000..f89f14b
--- /dev/null
@@ -0,0 +1,160 @@
+
+tvheadend.cteditor = function() {
+    var fm = Ext.form;
+    
+    var enabledColumn = new Ext.grid.CheckColumn({
+       header: "Enabled",
+       dataIndex: 'enabled',
+       width: 60
+    });
+
+    var internalColumn = new Ext.grid.CheckColumn({
+       header: "Internal",
+       dataIndex: 'internal',
+       width: 100
+    });
+
+
+    var cm = new Ext.grid.ColumnModel([
+                                      enabledColumn,
+       {
+           id:'name',
+           header: "Name",
+           dataIndex: 'name',
+           editor: new fm.TextField({
+               allowBlank: false
+                              })
+       },
+           internalColumn,
+       {
+           id:'comment',
+           header: "Comment",
+           dataIndex: 'comment',
+           width: 400,
+           editor: new fm.TextField({
+               
+                              })
+       }
+       ]);
+    
+    
+    cm.defaultSortable = true;
+    
+    var ChannelTagRecord = Ext.data.Record.create([
+       {name: 'enabled'},
+       {name: 'name'},
+       {name: 'internal'},
+       {name: 'comment'}
+    ]);
+    
+    var store = new Ext.data.JsonStore({
+       root: 'entries',
+       fields: ChannelTagRecord,
+       url: "tablemgr",
+       autoLoad: true,
+       id: 'id',
+       storeid: 'id',
+       baseParams: {table: "channeltags", op: "get"}
+    });
+    
+
+    function addRecord() {
+       Ext.Ajax.request({
+               url: "tablemgr", params: {op:"create", table:"channeltags"},
+                   failure:function(response,options){
+                   Ext.MessageBox.alert('Server Error','Unable to generate new record');
+               },
+                   success:function(response,options){
+                   var responseData = Ext.util.JSON.decode(response.responseText);
+                   
+                   var p = new ChannelTagRecord(responseData, responseData.id);
+                   grid.stopEditing();
+                   store.insert(0, p);
+                   grid.startEditing(0, 0);
+               }
+           })
+           };
+    
+    function delSelected() {
+       var selectedKeys = grid.selModel.selections.keys;
+       if(selectedKeys.length > 0)
+            {
+                Ext.MessageBox.confirm('Message',
+                                      'Do you really want to delete selection?',
+                                      deleteRecord);
+            } else {
+                Ext.MessageBox.alert('Message',
+                                    'Please select at least one item to delete');
+            }
+    };
+    
+    
+    function deleteRecord(btn) {
+       if(btn=='yes') {
+           var selectedKeys = grid.selModel.selections.keys;
+           
+           Ext.Ajax.request({
+                   url: "tablemgr", params: {op:"delete", table:"channeltags",
+                           entries:Ext.encode(selectedKeys)},
+                       failure:function(response,options){
+                       Ext.MessageBox.alert('Server Error','Unable to delete');
+                   },
+                       success:function(response,options){
+                       store.reload();
+                   }
+               })
+               }
+    }
+
+
+    function saveChanges() {
+       var mr = store.getModifiedRecords();
+       var out = new Array();
+       for (var x = 0; x < mr.length; x++) {
+           v = mr[x].getChanges();
+           out[x] = v;
+           out[x].id = mr[x].id;
+       }
+
+       Ext.Ajax.request({url: "tablemgr",
+                         params: {op:"update", table:"channeltags",
+                                  entries:Ext.encode(out)},
+                         success:function(response,options){
+                   store.commitChanges();
+               },
+                         failure:function(response,options){
+                   Ext.MessageBox.alert('Message',response.statusText);
+               }
+           });
+    }
+       
+    var grid = new Ext.grid.EditorGridPanel({
+           title: 'Channel Tags',
+           plugins:[enabledColumn,internalColumn],
+           store: store,
+           clicksToEdit: 2,
+           cm: cm,
+           selModel: new Ext.grid.RowSelectionModel({singleSelect:false}),
+           tbar: [{
+                   tooltip: 'Create a new channel tag entry on the server. ' + 
+                   'The new entry is initially disabled so it must be enabled before it start taking effect.',
+                   iconCls:'add',
+                   text: 'Add entry',
+                   handler: addRecord
+               }, '-', {
+                   tooltip: 'Delete one or more selected rows',
+                   iconCls:'remove',
+                   text: 'Delete selected',
+                   handler: delSelected
+               }, '-', {
+                   tooltip: 'Save any changes made (Changed cells have red borders).',
+                   iconCls:'save',
+                   text: "Save changes",
+                   handler: saveChanges
+               }
+               ]
+       });
+    
+    return grid;
+}
index f0bb680a416d503e3cf4f2c9de71ea728a64a4f1..f5aaa734dd413a00e9ae37b3375a07c767fc13c8 100644 (file)
@@ -87,6 +87,7 @@ tvheadend.app = function() {
                autoScroll:true, 
                title: 'Configuration', 
                items: [new tvheadend.chconf,
+                       new tvheadend.cteditor,
                        new tvheadend.dvb,
                        new tvheadend.acleditor, 
                        new tvheadend.cwceditor]