- add getLength() call to iStaticServiceInformation
[enigma2.git] / lib / dvb / db.cpp
1 #include <errno.h>
2 #include <lib/dvb/db.h>
3 #include <lib/dvb/frontend.h>
4 #include <lib/base/eerror.h>
5 #include <lib/dvb_si/sdt.h>
6 #include <lib/dvb_si/descriptor_tag.h>
7 #include <lib/dvb_si/service_descriptor.h>
8 #include <lib/dvb_si/satellite_delivery_system_descriptor.h>
9
10 DEFINE_REF(eDVBService);
11
12 eDVBService::eDVBService()
13 {
14 }
15
16 eDVBService::~eDVBService()
17 {
18 }
19
20 eDVBService &eDVBService::operator=(const eDVBService &s)
21 {
22         m_service_name = s.m_service_name;
23         m_provider_name = s.m_provider_name;
24         m_flags = s.m_flags;
25         m_ca = s.m_ca;
26         m_cache = s.m_cache;
27         return *this;
28 }
29
30 RESULT eDVBService::getName(const eServiceReference &ref, std::string &name)
31 {
32         name = m_service_name;
33         return 0;
34 }
35
36 int eDVBService::getLength(const eServiceReference &ref)
37 {
38         return -1;
39 }
40
41 int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQuery &query)
42 {
43         int res = 0;
44         switch (query.m_type)
45         {
46         case eDVBChannelQuery::tName:
47                 res = m_service_name.find(query.m_string) != std::string::npos;
48                 break;
49         case eDVBChannelQuery::tProvider:
50                 res = m_provider_name.find(query.m_string) != std::string::npos;
51                 break;
52         case eDVBChannelQuery::tType:
53                 res = ref.getServiceType() == query.m_int;
54                 break;
55         case eDVBChannelQuery::tBouquet:
56                 res = 0;
57                 break;
58         case eDVBChannelQuery::tSatellitePosition:
59                 res = (ref.getDVBNamespace().get() >> 16) == query.m_int;
60                 break;
61         case eDVBChannelQuery::tChannelID:
62         {
63                 eDVBChannelID chid;
64                 ref.getChannelID(chid);
65                 res = chid == query.m_channelid;
66                 break;
67         }
68         case eDVBChannelQuery::tAND:
69                 res = checkFilter(ref, *query.m_p1) && checkFilter(ref, *query.m_p2);
70                 break;
71         case eDVBChannelQuery::tOR:
72                 res = checkFilter(ref, *query.m_p1) || checkFilter(ref, *query.m_p2);
73                 break;
74         }
75
76         if (query.m_inverse)
77                 return !res;
78         else
79                 return res;
80 }
81
82 int eDVBService::getCachePID(cacheID id)
83 {
84         std::map<int, int>::iterator it = m_cache.find(id);
85         if ( it != m_cache.end() )
86                 return it->second;
87         return -1;
88 }
89
90 void eDVBService::setCachePID(cacheID id, int pid)
91 {
92         m_cache[id] = pid;
93 }
94
95 DEFINE_REF(eDVBDB);
96
97 eDVBDB::eDVBDB()
98 {
99         eDebug("---- opening lame channel db");
100         FILE *f=fopen("lamedb", "rt");
101         if (!f)
102                 return;
103         char line[256];
104         if ((!fgets(line, 256, f)) || strncmp(line, "eDVB services", 13))
105         {
106                 eDebug("not a servicefile");
107                 fclose(f);
108                 return;
109         }
110         eDebug("reading services");
111         if ((!fgets(line, 256, f)) || strcmp(line, "transponders\n"))
112         {
113                 eDebug("services invalid, no transponders");
114                 fclose(f);
115                 return;
116         }
117         
118         // clear all transponders
119
120         while (!feof(f))
121         {
122                 if (!fgets(line, 256, f))
123                         break;
124                 if (!strcmp(line, "end\n"))
125                         break;
126                 int dvb_namespace=-1, transport_stream_id=-1, original_network_id=-1;
127                 sscanf(line, "%x:%x:%x", &dvb_namespace, &transport_stream_id, &original_network_id);
128                 if (original_network_id == -1)
129                         continue;
130                 eDVBChannelID channelid = eDVBChannelID(
131                         eDVBNamespace(dvb_namespace), 
132                         eTransportStreamID(transport_stream_id), 
133                         eOriginalNetworkID(original_network_id));
134                 
135                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
136                 while (!feof(f))
137                 {
138                         fgets(line, 256, f);
139                         if (!strcmp(line, "/\n"))
140                                 break;
141                         if (line[1]=='s')
142                         {
143                                 eDVBFrontendParametersSatellite sat;
144                                 int frequency, symbol_rate, polarisation, fec, orbital_position, inversion;
145                                 sscanf(line+2, "%d:%d:%d:%d:%d:%d", &frequency, &symbol_rate, &polarisation, &fec, &inversion, &orbital_position);
146                                 sat.frequency = frequency;
147                                 sat.symbol_rate = symbol_rate;
148                                 sat.polarisation = polarisation;
149                                 sat.fec = fec;
150                                 sat.orbital_position = orbital_position;
151                                 sat.inversion = inversion;
152                                 // ...
153 //                              t.setSatellite(frequency, symbol_rate, polarisation, fec, sat, inversion);
154                                 feparm->setDVBS(sat);
155                         }
156                         if (line[1]=='c')
157                         {
158                                 int frequency, symbol_rate, inversion=0, modulation=3;
159                                 sscanf(line+2, "%d:%d:%d:%d", &frequency, &symbol_rate, &inversion, &modulation);
160 //                              t.setCable(frequency, symbol_rate, inversion, modulation);
161                         }
162                 }
163                 addChannelToList(channelid, feparm);
164         }
165
166         if ((!fgets(line, 256, f)) || strcmp(line, "services\n"))
167         {
168                 eDebug("services invalid, no services");
169                 return;
170         }
171         
172         // clear all services
173         
174         int count=0;
175
176         while (!feof(f))
177         {
178                 if (!fgets(line, 256, f))
179                         break;
180                 if (!strcmp(line, "end\n"))
181                         break;
182
183                 int service_id=-1, dvb_namespace, transport_stream_id=-1, original_network_id=-1, service_type=-1, service_number=-1;
184                 sscanf(line, "%x:%x:%x:%x:%d:%d", &service_id, &dvb_namespace, &transport_stream_id, &original_network_id, &service_type, &service_number);
185                 if (service_number == -1)
186                         continue;
187                 ePtr<eDVBService> s = new eDVBService;
188                 eServiceReferenceDVB ref = 
189                                                 eServiceReferenceDVB(
190                                                 eDVBNamespace(dvb_namespace),
191                                                 eTransportStreamID(transport_stream_id),
192                                                 eOriginalNetworkID(original_network_id),
193                                                 eServiceID(service_id),
194                                                 service_type);
195                 count++;
196                 fgets(line, 256, f);
197                 if (strlen(line))
198                         line[strlen(line)-1]=0;
199                 s->m_service_name=line;
200                 fgets(line, 256, f);
201                 if (strlen(line))
202                         line[strlen(line)-1]=0;
203
204                 std::string str=line;
205
206                 if (str[1]!=':')        // old ... (only service_provider)
207                 {
208                         s->m_provider_name=line;
209                 } else
210                         while ((!str.empty()) && str[1]==':') // new: p:, f:, c:%02d...
211                         {
212                                 unsigned int c=str.find(',');
213                                 char p=str[0];
214                                 std::string v;
215                                 if (c == std::string::npos)
216                                 {
217                                         v=str.substr(2);
218                                         str="";
219                                 } else
220                                 {
221                                         v=str.substr(2, c-2);
222                                         str=str.substr(c+1);
223                                 }
224 //                              eDebug("%c ... %s", p, v.c_str());
225                                 if (p == 'p')
226                                         s->m_provider_name=v;
227                                 else if (p == 'f')
228                                 {
229                                         sscanf(v.c_str(), "%x", &s->m_flags);
230                                 } else if (p == 'c')
231                                 {
232                                         int cid, val;
233                                         sscanf(v.c_str(), "%02d%04x", &cid, &val);
234                                         s->m_cache[cid]=val;
235                                 } else if (p == 'C')
236                                 {
237                                         int val;
238                                         sscanf(v.c_str(), "%04x", &val);
239                                         s->m_ca.insert(val);
240                                 }
241                         }
242                 addService(ref, s);
243         }
244
245         eDebug("loaded %d services", count);
246         
247         fclose(f);
248         
249 }
250
251 eDVBDB::~eDVBDB()
252 {
253         eDebug("---- saving lame channel db");
254         FILE *f=fopen("lamedb", "wt");
255         int channels=0, services=0;
256         if (!f)
257                 eFatal("couldn't save lame channel db!"); 
258         fprintf(f, "eDVB services /3/\n");
259         fprintf(f, "transponders\n");
260         for (std::map<eDVBChannelID, channel>::const_iterator i(m_channels.begin());
261                         i != m_channels.end(); ++i)
262         {
263                 const eDVBChannelID &chid = i->first;
264                 const channel &ch = i->second;
265                 
266                 fprintf(f, "%08x:%04x:%04x\n", chid.dvbnamespace.get(),
267                                 chid.transport_stream_id.get(), chid.original_network_id.get());
268                 eDVBFrontendParametersSatellite sat;
269                 if (!ch.m_frontendParameters->getDVBS(sat))
270                 {
271                         fprintf(f, "\ts %d:%d:%d:%d:%d:%d\n", 
272                                 sat.frequency, sat.symbol_rate,
273                                 sat.polarisation, sat.fec, sat.inversion,
274                                 sat.orbital_position);
275                 }
276                 fprintf(f, "/\n");
277                 channels++;
278         }
279         fprintf(f, "end\nservices\n");
280         
281         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator i(m_services.begin());
282                 i != m_services.end(); ++i)
283         {
284                 const eServiceReferenceDVB &s = i->first;
285                 fprintf(f, "%04x:%08x:%04x:%04x:%d:%d\n", 
286                                 s.getServiceID().get(), s.getDVBNamespace().get(), 
287                                 s.getTransportStreamID().get(),s.getOriginalNetworkID().get(), 
288                                 s.getServiceType(),
289                                 0);
290                 
291                 fprintf(f, "%s\n", i->second->m_service_name.c_str());
292                 fprintf(f, "p:%s", i->second->m_provider_name.c_str());
293                 for (std::set<int>::const_iterator ca(i->second->m_ca.begin());
294                         ca != i->second->m_ca.end(); ++ca)
295                         fprintf(f, ",C:%04x", *ca);
296                 fprintf(f, "\n");
297                 services++;
298         }
299         fprintf(f, "end\nHave a lot of bugs!\n");
300         eDebug("saved %d channels and %d services!", channels, services);
301         fclose(f);
302 }
303
304 RESULT eDVBDB::addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm)
305 {
306         channel ch;
307         assert(feparm);
308         ch.m_frontendParameters = feparm;
309         m_channels.insert(std::pair<eDVBChannelID, channel>(id, ch));
310         return 0;
311 }
312
313 RESULT eDVBDB::removeChannel(const eDVBChannelID &id)
314 {
315         m_channels.erase(id);
316         return 0;
317 }
318
319 RESULT eDVBDB::getChannelFrontendData(const eDVBChannelID &id, ePtr<iDVBFrontendParameters> &parm)
320 {
321         std::map<eDVBChannelID, channel>::iterator i = m_channels.find(id);
322         if (i == m_channels.end())
323         {
324                 parm = 0;
325                 return -ENOENT;
326         }
327         parm = i->second.m_frontendParameters;
328         return 0;
329 }
330
331 RESULT eDVBDB::addService(const eServiceReferenceDVB &serviceref, eDVBService *service)
332 {
333         m_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(serviceref, service));
334         return 0;
335 }
336
337 RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr<eDVBService> &service)
338 {
339         std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator i;
340         i = m_services.find(reference);
341         if (i == m_services.end())
342         {
343                 service = 0;
344                 return -ENOENT;
345         }
346         service = i->second;
347         return 0;
348 }
349
350 RESULT eDVBDB::startQuery(ePtr<iDVBChannelListQuery> &query, eDVBChannelQuery *q)
351 {
352         query = new eDVBDBQuery(this, eServiceReference(), q);
353         return 0;
354 }
355
356 DEFINE_REF(eDVBDBQuery);
357
358 eDVBDBQuery::eDVBDBQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query): m_db(db), m_query(query)
359 {
360                 // TODO: use SOURCE ...
361         m_cursor = m_db->m_services.begin();
362 }
363
364 RESULT eDVBDBQuery::getNextResult(eServiceReferenceDVB &ref)
365 {
366         while (m_cursor != m_db->m_services.end())
367         {
368                 ref = m_cursor->first;
369                 
370                 int res = (!m_query) || m_cursor->second->checkFilter(ref, *m_query);
371
372                 ++m_cursor;
373                 
374                 if (res)
375                         return 0;
376         }
377         return 1;
378 }
379
380 /* (<name|provider|type|bouquet|satpos|chid> <==|...> <"string"|int>)[AND (..)] */
381
382         /* never, NEVER write a parser in C++! */
383 RESULT parseExpression(ePtr<eDVBChannelQuery> &res, std::list<std::string>::const_iterator begin, std::list<std::string>::const_iterator end)
384 {
385         std::list<std::string>::const_iterator end_of_exp;
386         if (*begin == "(")
387         {
388                 end_of_exp = begin;
389                 while (end_of_exp != end)
390                         if (*end_of_exp == ")")
391                                 break;
392                         else
393                                 ++end_of_exp;
394         
395                 if (end_of_exp == end)
396                 {
397                         eDebug("expression parse: end of expression while searching for closing brace");
398                         return -1;
399                 }
400                 
401                 ++begin;
402                 // begin..end_of_exp
403                 int r = parseExpression(res, begin, end_of_exp);
404                 if (r)
405                         return r;
406                 ++end_of_exp;
407                 
408                         /* we had only one sub expression */
409                 if (end_of_exp == end)
410                         return 1;
411                 
412                         /* otherwise we have an operator here.. */
413                 
414                 ePtr<eDVBChannelQuery> r2 = res;
415                 res = new eDVBChannelQuery();
416                 res->m_p1 = r2;
417                 res->m_inverse = 0;
418                 r2 = 0;
419                 
420                 if (*end_of_exp == "||")
421                         res->m_type = eDVBChannelQuery::tOR;
422                 else if (*end_of_exp == "&&")
423                         res->m_type = eDVBChannelQuery::tAND;
424                 else
425                 {
426                         eDebug("found operator %s, but only && and || are allowed!", end_of_exp->c_str());
427                         res = 0;
428                         return 1;
429                 }
430                 
431                 ++end_of_exp;
432                 
433                 return parseExpression(res->m_p2, end_of_exp, end);
434         }
435         
436         // "begin" <op> "end"
437         std::string type, op, val;
438         
439         res = new eDVBChannelQuery();
440         
441         int cnt = 0;
442         while (begin != end)
443         {
444                 switch (cnt)
445                 {
446                 case 0:
447                         type = *begin;
448                         break;
449                 case 1:
450                         op = *begin;
451                         break;
452                 case 2:
453                         val = *begin;
454                         break;
455                 case 3:
456                         eDebug("malformed query: got '%s', but expected only <type> <op> <val>", begin->c_str());
457                         return 1;
458                 }
459                 ++begin;
460                 ++cnt;
461         }
462         
463         if (cnt != 3)
464         {
465                 eDebug("malformed query: missing stuff");
466                 res = 0;
467                 return 1;
468         }
469         
470         if (type == "name")
471                 res->m_type = eDVBChannelQuery::tName;
472         else if (type == "provider")
473                 res->m_type = eDVBChannelQuery::tProvider;
474         else if (type == "type")
475                 res->m_type = eDVBChannelQuery::tType;
476         else if (type == "bouquet")
477                 res->m_type = eDVBChannelQuery::tBouquet;
478         else if (type == "satellitePosition")
479                 res->m_type = eDVBChannelQuery::tSatellitePosition;
480         else if (type == "channelID")
481                 res->m_type = eDVBChannelQuery::tChannelID;
482         else
483         {
484                 eDebug("malformed query: invalid type %s", type.c_str());
485                 res = 0;
486                 return 1;
487         }
488         
489         eDebug("type is %d, nice!", res->m_type);
490         
491         if (op == "==")
492                 res->m_inverse = 0;
493         else if (op == "!=")
494                 res->m_inverse = 1;
495         else
496         {
497                 eDebug("invalid operator %s", op.c_str());
498                 res = 0;
499                 return 1;
500         }
501         
502         res->m_string = val;
503         res->m_int = atoi(val.c_str());
504 //      res->m_channelid = eDVBChannelID(val);
505         
506         return 0;
507 }
508
509 RESULT eDVBChannelQuery::compile(ePtr<eDVBChannelQuery> &res, std::string query)
510 {
511         std::list<std::string> tokens;
512         
513         std::string current_token;
514         
515 //      eDebug("splitting %s....", query.c_str());
516         unsigned int i = 0;
517         const char *splitchars="()";
518         int quotemode = 0, lastsplit = 0, lastalnum = 0;
519         while (i <= query.size())
520         {
521                 int c = (i < query.size()) ? query[i] : ' ';
522                 ++i;
523                 
524                 int issplit = !!strchr(splitchars, c);
525                 int isaln = isalnum(c);
526                 int iswhite = c == ' ';
527                 int isquot = c == '\"';
528                 
529                 if (quotemode)
530                 {
531                         iswhite = issplit = 0;
532                         isaln = lastalnum;
533                 }
534                 
535                 if (issplit || iswhite || isquot || lastsplit || (lastalnum != isaln))
536                 {
537                         if (current_token.size())
538                                 tokens.push_back(current_token);
539                         current_token.clear();
540                 }
541                 
542                 if (!(iswhite || isquot))
543                         current_token += c;
544                 
545                 if (isquot)
546                         quotemode = !quotemode;
547                 lastsplit = issplit;
548                 lastalnum = isaln;
549         }
550         
551 //      for (std::list<std::string>::const_iterator a(tokens.begin()); a != tokens.end(); ++a)
552 //      {
553 //              printf("%s\n", a->c_str());
554 //      }
555         
556                 /* now we recursivly parse that. */
557         return  parseExpression(res, tokens.begin(), tokens.end());
558 /*      
559         res = new eDVBChannelQuery();
560         res->m_type = eDVBChannelQuery::tName;
561         res->m_inverse = 0;
562         res->m_string = query;
563         return 0; */
564 }
565
566 DEFINE_REF(eDVBChannelQuery);