]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
channel/bouquet: add bouquet detach functionality to 'Map services' menu
authorJaroslav Kysela <perex@perex.cz>
Sun, 28 Aug 2016 07:49:36 +0000 (09:49 +0200)
committerJaroslav Kysela <perex@perex.cz>
Sun, 28 Aug 2016 07:49:36 +0000 (09:49 +0200)
src/api/api_bouquet.c
src/bouquet.c
src/bouquet.h
src/webui/static/app/chconf.js
src/webui/static/app/tvheadend.js

index 21ab504d4fbd896a894a424f2afce61ebb9bee1e..3e651bd0f76cb27c0f17d3149811dcad0a755f3c 100644 (file)
@@ -82,13 +82,14 @@ api_bouquet_create
 }
 
 static int
-api_bouquet_scan
-  ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+bouquet_cb
+  ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp,
+    int (*cb)(const char *uuid) )
 {
   htsmsg_field_t *f;
   htsmsg_t *uuids;
-  bouquet_t *bq;
   const char *uuid;
+  int r = 0;
 
   if (!(f = htsmsg_field_find(args, "uuid")))
     return -EINVAL;
@@ -96,24 +97,52 @@ api_bouquet_scan
     HTSMSG_FOREACH(f, uuids) {
       if (!(uuid = htsmsg_field_get_str(f))) continue;
       pthread_mutex_lock(&global_lock);
-      bq = bouquet_find_by_uuid(uuid);
-      if (bq)
-        bouquet_scan(bq);
+      cb(uuid);
       pthread_mutex_unlock(&global_lock);
     }
   } else if ((uuid = htsmsg_field_get_str(f))) {
     pthread_mutex_lock(&global_lock);
-    bq = bouquet_find_by_uuid(uuid);
-    if (bq)
-      bouquet_scan(bq);
+    r = cb(uuid);
     pthread_mutex_unlock(&global_lock);
-    if (!bq)
-      return -ENOENT;
   } else {
     return -EINVAL;
   }
 
-  return 0;
+  return r;
+}
+
+static int bouquet_cb_scan(const char *uuid)
+{
+  bouquet_t *bq = bouquet_find_by_uuid(uuid);
+  if (bq) {
+    bouquet_scan(bq);
+    return 0;
+  }
+  return -ENOENT;
+}
+
+static int
+api_bouquet_scan
+  ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+  return bouquet_cb(perm, opaque, op, args, resp, bouquet_cb_scan);
+}
+
+static int bouquet_cb_detach(const char *uuid)
+{
+  channel_t *ch = channel_find_by_uuid(uuid);
+  if (ch) {
+    bouquet_detach(ch);
+    return 0;
+  }
+  return -ENOENT;
+}
+
+static int
+api_bouquet_detach
+  ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+  return bouquet_cb(perm, opaque, op, args, resp, bouquet_cb_detach);
 }
 
 void api_bouquet_init ( void )
@@ -124,6 +153,7 @@ void api_bouquet_init ( void )
     { "bouquet/grid",    ACCESS_ADMIN, api_idnode_grid,  api_bouquet_grid },
     { "bouquet/create",  ACCESS_ADMIN, api_bouquet_create, NULL },
     { "bouquet/scan",    ACCESS_ADMIN, api_bouquet_scan, NULL },
+    { "bouquet/detach",  ACCESS_ADMIN, api_bouquet_detach, NULL },
 
     { NULL },
   };
index ae52361e476e5000635e1fb196f6f2a14b97e540..1e95272b2615b771bdbe9c82298bb5c0b1d1310d 100644 (file)
@@ -606,6 +606,37 @@ bouquet_scan ( bouquet_t *bq )
   bq->bq_rescan = 0;
 }
 
+/*
+ *
+ */
+void
+bouquet_detach ( channel_t *ch )
+{
+  bouquet_t *bq = ch->ch_bouquet;
+  idnode_list_mapping_t *ilm;
+  service_lcn_t *tl;
+  service_t *t;
+  int64_t n = 0;
+
+  if (!bq)
+    return;
+  LIST_FOREACH(ilm, &ch->ch_services, ilm_in2_link) {
+    t = (service_t *)ilm->ilm_in1;
+    LIST_FOREACH(tl, &t->s_lcns, sl_link)
+      if (tl->sl_bouquet == bq) {
+        n = (int64_t)tl->sl_lcn;
+        goto found;
+      }
+  }
+found:
+  if (n) {
+    n += (int64_t)ch->ch_bouquet->bq_lcn_offset * CHANNEL_SPLIT;
+    ch->ch_number = n;
+  }
+  ch->ch_bouquet = NULL;
+  idnode_changed(&ch->ch_id);
+}
+
 /* **************************************************************************
  * Class definition
  * **************************************************************************/
index cd269da0307d8b957252d0c7c768dcf514696d57..1fcd1fa6008528979eed154ff684e65c7d901a8d 100644 (file)
@@ -101,6 +101,7 @@ void bouquet_add_service(bouquet_t *bq, service_t *s, uint64_t lcn, const char *
 void bouquet_completed(bouquet_t *bq, uint32_t seen);
 void bouquet_change_comment(bouquet_t *bq, const char *comment, int replace);
 void bouquet_scan(bouquet_t *bq);
+void bouquet_detach(channel_t *ch);
 
 uint64_t bouquet_get_channel_number(bouquet_t *bq, service_t *t);
 
index 34ab1d80f7ed7e73e0bcac897ec48f26bf2b86b3..3a1d7213347030c4c9ed35b28535ed9a7ec59fb6 100644 (file)
@@ -118,7 +118,14 @@ tvheadend.channel_tab = function(panel, index)
 
     function reset_icons(ctx, e, store, sm) {
         Ext.each(sm.getSelections(), function(channel) {
-           channel.set('icon', '');
+            channel.set('icon', '');
+        });
+    }
+
+    function bouquet_detach(ctx, e, store, sm) {
+        tvheadend.AjaxUUID(sm.getSelections(), {
+            url: 'api/bouquet/detach',
+            success: function(d) { store.reload(); }
         });
     }
 
@@ -138,6 +145,12 @@ tvheadend.channel_tab = function(panel, index)
                 iconCls: 'clone',
                 text: _('Map all services'),
             });
+            m.add({
+                name: 'bqdetach',
+                tooltip: _('Detach from bouquet'),
+                iconCls: 'bouquets',
+                text: _('Detach selected channels from bouquet'),
+            });
             return new Ext.Toolbar.Button({
                 tooltip: _('Map services to channels'),
                 iconCls: 'clone',
@@ -149,6 +162,7 @@ tvheadend.channel_tab = function(panel, index)
         callback: {
             mapall: tvheadend.service_mapper_all,
             mapsel: tvheadend.service_mapper_none,
+            bqdetach: bouquet_detach
         }
     };
 
index 3c984038a7df44e4bd15c80abc719272bec600d3..2a43fd359c74b3c0c34c922bac424185246a998c 100644 (file)
@@ -307,6 +307,19 @@ tvheadend.AjaxConfirm = function(conf) {
     );
 };
 
+tvheadend.AjaxUUID = function(sel, conf)
+{
+    if (sel && sel.length > 0) {
+        var uuids = [];
+        for (var i = 0; i < sel.length; i++)
+            uuids.push(sel[i].id);
+        if (!conf.params)
+            conf.params = {};
+        conf.params.uuid = uuids;
+        tvheadend.Ajax(conf);
+    }    
+}
+
 tvheadend.loading = function(on) {
     if (on)
       Ext.getBody().mask(_('Loading, please wait...'), 'loading');