1 /*
2  *  tvheadend, charset list
3  *  Copyright (C) 2014 Jaroslav Kysela
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "tvheadend.h"
20 #include "settings.h"
21 #include "bouquet.h"
22 #include "dvb.h"
23 #include "fastscan.h"
24 
25 #if ENABLE_MPEGTS_DVB
26 
27 typedef struct dvb_fastscan_item {
28   LIST_ENTRY(dvb_fastscan_item) ilink;
29 
30   const char *name;
31   int         pid;
32 
33 } dvb_fastscan_item_t;
34 
35 typedef struct dvb_fastscan {
36   RB_ENTRY(dvb_fastscan) link;
37 
38   LIST_HEAD(,dvb_fastscan_item) items;
39 
40   int                       position;
41   dvb_fe_delivery_system_t  delsys;
42   dvb_polarisation_t        polarisation;
43   uint32_t                  frequency;
44   uint32_t                  symbolRate;
45 } dvb_fastscan_t;
46 
47 static RB_HEAD(,dvb_fastscan) fastscan_rb;
48 static SKEL_DECLARE(fastscan_rb_skel, dvb_fastscan_t);
49 
50 static int
_fs_cmp(const void * a,const void * b)51 _fs_cmp(const void *a, const void *b)
52 {
53   int r = ((dvb_fastscan_t *)a)->position - ((dvb_fastscan_t *)b)->position;
54   if (r == 0) {
55     r = ((dvb_fastscan_t *)a)->frequency - ((dvb_fastscan_t *)b)->frequency;
56     if (abs(r) < 2000)
57       return (((dvb_fastscan_t *)a)->polarisation - ((dvb_fastscan_t *)b)->polarisation);
58   }
59   return r;
60 }
61 
62 void
dvb_fastscan_each(void * aux,int position,uint32_t frequency,dvb_polarisation_t polarisation,void (* job)(void * aux,bouquet_t * bq,const char * name,int pid))63 dvb_fastscan_each(void *aux, int position, uint32_t frequency, dvb_polarisation_t polarisation,
64                   void (*job)(void *aux, bouquet_t *bq,
65                               const char *name, int pid))
66 {
67   dvb_fastscan_t *fs;
68   dvb_fastscan_item_t *fsi;
69   bouquet_t *bq;
70   char url[64], buf[16];
71 
72   SKEL_ALLOC(fastscan_rb_skel);
73   fastscan_rb_skel->position = position;
74   fastscan_rb_skel->frequency = frequency;
75   fastscan_rb_skel->polarisation = polarisation;
76   fs = RB_FIND(&fastscan_rb, fastscan_rb_skel, link, _fs_cmp);
77   if (!fs)
78     return;
79   LIST_FOREACH(fsi, &fs->items, ilink) {
80     dvb_sat_position_to_str(fs->position, buf, sizeof(buf));
81     snprintf(url, sizeof(url), "dvb-fastscan://%s,%s,%u,%s,%u,%d", dvb_delsys2str(fastscan_rb_skel->delsys),
82              buf, fs->frequency, dvb_pol2str(fs->polarisation), fs->symbolRate, fsi->pid);
83     bq = bouquet_find_by_source(NULL, url, 0);
84     if (bq == NULL || !bq->bq_enabled)
85       continue;
86     bq->bq_shield = 1;
87     job(aux, bq, fsi->name, fsi->pid);
88   }
89 }
90 
91 static void
dvb_fastscan_create(htsmsg_t * e)92 dvb_fastscan_create(htsmsg_t *e)
93 {
94   dvb_fastscan_t *fs;
95   dvb_fastscan_item_t *fsi;
96   bouquet_t *bq;
97   const char *name, *polarisation, *delsys;
98   int pid;
99   char url[64], buf[16];
100 
101   SKEL_ALLOC(fastscan_rb_skel);
102   if (htsmsg_get_s32(e, "position", &fastscan_rb_skel->position))
103     goto fail;
104   if (htsmsg_get_u32(e, "frequency", &fastscan_rb_skel->frequency))
105     goto fail;
106   if (htsmsg_get_s32(e, "pid", &pid))
107     goto fail;
108   if ((name = htsmsg_get_str(e, "name")) == NULL)
109     goto fail;
110   if (htsmsg_get_u32(e, "symbolrate", &fastscan_rb_skel->symbolRate))
111     goto fail;
112   if ((delsys = htsmsg_get_str(e, "delsys")) == NULL)
113     goto fail;
114   if ((polarisation = htsmsg_get_str(e, "polarisation")) == NULL)
115     goto fail;
116 
117   fastscan_rb_skel->polarisation = dvb_str2pol(polarisation);
118   fastscan_rb_skel->delsys = dvb_str2delsys(delsys);
119   dvb_sat_position_to_str(fastscan_rb_skel->position, buf, sizeof(buf));
120   snprintf(url, sizeof(url), "dvb-fastscan://%s,%s,%u,%s,%u,%d", dvb_delsys2str(fastscan_rb_skel->delsys),
121            buf, fastscan_rb_skel->frequency, dvb_pol2str(fastscan_rb_skel->polarisation), fastscan_rb_skel->symbolRate, pid);
122   bq = bouquet_find_by_source(name, url, 1);
123   if (bq == NULL)
124     goto fail;
125   bq->bq_shield = 1;
126   if (bq->bq_saveflag) {
127     bq->bq_saveflag = 0;
128     idnode_changed(&bq->bq_id);
129   }
130 
131   fs = RB_INSERT_SORTED(&fastscan_rb, fastscan_rb_skel, link, _fs_cmp);
132   if (!fs) {
133     fs = fastscan_rb_skel;
134     SKEL_USED(fastscan_rb_skel);
135     LIST_INIT(&fs->items);
136   }
137 
138   fsi = calloc(1, sizeof(*fsi));
139   fsi->pid = pid;
140   if ((fsi->name = htsmsg_get_str(e, "name")) == NULL)
141     goto fail;
142   fsi->name = strdup(name);
143 
144   LIST_INSERT_HEAD(&fs->items, fsi, ilink);
145 
146   return;
147 
148 fail:
149   tvhwarn(LS_FASTSCAN, "wrong entry format");
150 }
151 
152 /*
153  * Initialize the fastscan list
154  */
dvb_fastscan_init(void)155 void dvb_fastscan_init ( void )
156 {
157   htsmsg_t *c, *e;
158   htsmsg_field_t *f;
159 
160   if (!(c = hts_settings_load("fastscan"))) {
161     tvhwarn(LS_FASTSCAN, "configuration file missing");
162     return;
163   }
164 
165   HTSMSG_FOREACH(f, c) {
166     if (!(e = htsmsg_field_get_map(f))) continue;
167     dvb_fastscan_create(e);
168   }
169   htsmsg_destroy(c);
170 }
171 
172 /*
173  *
174  */
dvb_fastscan_done(void)175 void dvb_fastscan_done ( void )
176 {
177   dvb_fastscan_t *fs;
178   dvb_fastscan_item_t *fsi;
179 
180   while ((fs = RB_FIRST(&fastscan_rb)) != NULL) {
181     RB_REMOVE(&fastscan_rb, fs, link);
182     while ((fsi = LIST_FIRST(&fs->items)) != NULL) {
183       LIST_REMOVE(fsi, ilink);
184       free((char *)fsi->name);
185       free(fsi);
186     }
187     free(fs);
188   }
189   SKEL_FREE(fastscan_rb_skel);
190 }
191 
192 #else
193 
dvb_fastscan_init(void)194 void dvb_fastscan_init ( void )
195 {
196 }
197 
dvb_fastscan_done(void)198 void dvb_fastscan_done ( void )
199 {
200 }
201 
202 #endif
203