Allow user defined cable.xml and terrestrial.xml under /etc/enigma2 just like we...
[openblackhole/openblackhole-enigma2.git] / lib / dvb / db.cpp
1 #include <errno.h>
2 #include <unistd.h>
3 #include <lib/dvb/db.h>
4 #include <lib/dvb/dvb.h>
5 #include <lib/dvb/frontend.h>
6 #include <lib/dvb/epgcache.h>
7 #include <lib/base/cfile.h>
8 #include <lib/base/eenv.h>
9 #include <lib/base/eerror.h>
10 #include <lib/base/estring.h>
11 #include <lib/base/nconfig.h>
12 #include <xmlccwrap/xmlccwrap.h>
13 #include <dvbsi++/service_description_section.h>
14 #include <dvbsi++/descriptor_tag.h>
15 #include <dvbsi++/service_descriptor.h>
16 #include <dvbsi++/satellite_delivery_system_descriptor.h>
17 #include <dirent.h>
18
19 DEFINE_REF(eDVBService);
20
21 RESULT eBouquet::addService(const eServiceReference &ref, eServiceReference before)
22 {
23         list::iterator it =
24                 std::find(m_services.begin(), m_services.end(), ref);
25         if ( it != m_services.end() )
26                 return -1;
27         if (before.valid())
28         {
29                 it = std::find(m_services.begin(), m_services.end(), before);
30                 m_services.insert(it, ref);
31         }
32         else
33                 m_services.push_back(ref);
34         eDVBDB::getInstance()->renumberBouquet();
35         return 0;
36 }
37
38 RESULT eBouquet::removeService(const eServiceReference &ref, bool renameBouquet)
39 {
40         list::iterator it =
41                 std::find(m_services.begin(), m_services.end(), ref);
42         if ( it == m_services.end() )
43                 return -1;
44         if (renameBouquet && (ref.flags & eServiceReference::canDescent))
45         {
46                 std::string filename = ref.toString();
47                 size_t pos = filename.find("FROM BOUQUET ");
48                 if(pos != std::string::npos)
49                 {
50                         char endchr = filename[pos+13];
51                         if (endchr == '"')
52                         {
53                                 char *beg = &filename[pos+14];
54                                 char *end = strchr(beg, endchr);
55                                 filename.assign(beg, end - beg);
56                                 filename = eEnv::resolve("${sysconfdir}/enigma2/" + filename);
57                                 std::string newfilename(filename);
58                                 newfilename.append(".del");
59                                 eDebug("[eBouquet] Rename bouquet file %s to %s", filename.c_str(), newfilename.c_str());
60                                 rename(filename.c_str(), newfilename.c_str());
61                         }
62                 }
63         }
64         m_services.erase(it);
65         eDVBDB::getInstance()->renumberBouquet();
66         return 0;
67 }
68
69 RESULT eBouquet::moveService(const eServiceReference &ref, unsigned int pos)
70 {
71         if ( pos < 0 || pos >= m_services.size() )
72                 return -1;
73         ++pos;
74         list::iterator source=m_services.end();
75         list::iterator dest=m_services.end();
76         bool forward = false;
77         for (list::iterator it(m_services.begin()); it != m_services.end(); ++it)
78         {
79                 if (dest == m_services.end() && !--pos)
80                         dest = it;
81                 if (*it == ref)
82                 {
83                         source = it;
84                         forward = pos>0;
85                 }
86                 if (dest != m_services.end() && source != m_services.end())
87                         break;
88         }
89         if (dest == m_services.end() || source == m_services.end() || source == dest)
90                 return -1;
91         while (source != dest)
92         {
93                 if (forward)
94                         std::iter_swap(source++, source);
95                 else
96                         std::iter_swap(source--, source);
97         }
98         eDVBDB::getInstance()->renumberBouquet();
99         return 0;
100 }
101
102 RESULT eBouquet::flushChanges()
103 {
104         std::string filename = eEnv::resolve("${sysconfdir}/enigma2/" + m_filename);
105         {
106                 CFile f((filename + ".writing").c_str(), "w");
107                 if (!f)
108                         goto err;
109                 if ( fprintf(f, "#NAME %s\r\n", m_bouquet_name.c_str()) < 0 )
110                         goto err;
111                 for (list::iterator i(m_services.begin()); i != m_services.end(); ++i)
112                 {
113                         eServiceReference tmp = *i;
114                         std::string str = tmp.path;
115                         if ( fprintf(f, "#SERVICE %s\r\n", tmp.toString().c_str()) < 0 )
116                                 goto err;
117                         if ( i->name.length() )
118                                 if ( fprintf(f, "#DESCRIPTION %s\r\n", i->name.c_str()) < 0 )
119                                         goto err;
120                 }
121                 f.sync();
122         }
123         rename((filename + ".writing").c_str(), filename.c_str());
124         return 0;
125 err:
126         eDebug("[eBouquet] couldn't write file %s", m_filename.c_str());
127         return -1;
128 }
129
130 RESULT eBouquet::setListName(const std::string &name)
131 {
132         m_bouquet_name = name;
133         return 0;
134 }
135
136 eDVBService::eDVBService()
137         :m_cache(0), m_flags(0)
138 {
139 }
140
141 eDVBService::~eDVBService()
142 {
143         delete [] m_cache;
144 }
145
146 eDVBService &eDVBService::operator=(const eDVBService &s)
147 {
148         m_service_name = s.m_service_name;
149         m_service_name_sort = s.m_service_name_sort;
150         m_provider_name = s.m_provider_name;
151         m_flags = s.m_flags;
152         m_ca = s.m_ca;
153         copyCache(s.m_cache);
154         return *this;
155 }
156
157 void eDVBService::genSortName()
158 {
159         size_t start = m_service_name.find_first_not_of(' ');
160         if (start != std::string::npos)
161         {
162                 /* strip leading spaces */
163                 m_service_name_sort = m_service_name.substr(start);
164                 /* remove UTF-8 */
165                 m_service_name_sort = removeDVBChars(m_service_name_sort);
166                 /* convert to uppercase */
167                 makeUpper(m_service_name_sort);
168         }
169
170         if (m_service_name_sort.empty())
171         {
172                 /* put unnamed services at the end, not at the beginning. */
173                 m_service_name_sort = "\xFF";
174         }
175 }
176
177 RESULT eDVBService::getName(const eServiceReference &ref, std::string &name)
178 {
179         if (!ref.name.empty())
180                 name = ref.name; // use renamed service name..
181         else if (!m_service_name.empty())
182                 name = m_service_name;
183         else
184                 name = "(...)";
185         return 0;
186 }
187
188 RESULT eDVBService::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
189 {
190         return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
191 }
192
193 bool eDVBService::isCrypted()
194 {
195         return m_ca.size() > 0;
196 }
197
198 int eDVBService::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
199 {
200         ePtr<eDVBResourceManager> res_mgr;
201         bool remote_fallback_enabled = eConfigManager::getConfigBoolValue("config.usage.remote_fallback_enabled", false);
202
203         if (eDVBResourceManager::getInstance(res_mgr))
204                 eDebug("[eDVBService] isPlayble... no res manager!!");
205         else
206         {
207                 eDVBChannelID chid, chid_ignore;
208                 int system;
209
210                 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
211                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
212
213                 if (res_mgr->canAllocateChannel(chid, chid_ignore, system, simulate))
214                         return 1;
215
216                 if (remote_fallback_enabled)
217                         return 2;
218         }
219
220         return 0;
221 }
222
223 int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQuery &query)
224 {
225         int res = 0;
226         switch (query.m_type)
227         {
228                 case eDVBChannelQuery::tName:
229                 {
230                         res = m_service_name_sort == query.m_string;
231                         break;
232                 }
233                 case eDVBChannelQuery::tProvider:
234                 {
235                         if (query.m_string == "Unknown" && m_provider_name.empty())
236                                 res = 1;
237                         else
238                                 res = m_provider_name == query.m_string;
239                         break;
240                 }
241                 case eDVBChannelQuery::tType:
242                 {
243                         int service_type = ref.getServiceType();
244                         if (query.m_int == 1) // TV Service
245                         {
246                                 // Hack for dish network
247                                 int onid = ref.getOriginalNetworkID().get();
248                                 if (onid >= 0x1001 && onid <= 0x100b)
249                                 {
250                                         static int dish_tv_types[] = { 128, 133, 137, 140, 144, 145, 150, 154, 163, 164, 165, 166, 167, 168, 173, 174 };
251                                         static size_t dish_tv_num_types = sizeof(dish_tv_types) / sizeof(int);
252                                         if (std::binary_search(dish_tv_types, dish_tv_types + dish_tv_num_types, service_type))
253                                                 return true;
254                                 }
255                         }
256                         res = service_type == query.m_int;
257                         break;
258                 }
259                 case eDVBChannelQuery::tBouquet:
260                 {
261                         res = 0;
262                         break;
263                 }
264                 case eDVBChannelQuery::tSatellitePosition:
265                 {
266                         res = ((unsigned int)ref.getDVBNamespace().get())>>16 == (unsigned int)query.m_int;
267                         break;
268                 }
269                 case eDVBChannelQuery::tFlags:
270                 {
271                         res = (m_flags & query.m_int) == query.m_int;
272                         break;
273                 }
274                 case eDVBChannelQuery::tChannelID:
275                 {
276                         eDVBChannelID chid;
277                         ref.getChannelID(chid);
278                         res = chid == query.m_channelid;
279                         break;
280                 }
281                 case eDVBChannelQuery::tAND:
282                 {
283                         res = checkFilter(ref, *query.m_p1) && checkFilter(ref, *query.m_p2);
284                         break;
285                 }
286                 case eDVBChannelQuery::tOR:
287                 {
288                         res = checkFilter(ref, *query.m_p1) || checkFilter(ref, *query.m_p2);
289                         break;
290                 }
291                 case eDVBChannelQuery::tAny:
292                 {
293                         res = 1;
294                         break;
295                 }
296         }
297
298         if (query.m_inverse)
299                 return !res;
300         else
301                 return res;
302 }
303
304 bool eDVBService::cacheEmpty()
305 {
306         if (m_cache)
307                 for (int i=0; i < cacheMax; ++i)
308                         if (m_cache[i] != -1)
309                                 return false;
310         return true;
311 }
312
313 void eDVBService::initCache()
314 {
315         m_cache = new int[cacheMax];
316         memset(m_cache, -1, sizeof(int) * cacheMax);
317 }
318
319 void eDVBService::copyCache(int *source)
320 {
321         if (source)
322         {
323                 if (!m_cache)
324                         m_cache = new int[cacheMax];
325                 memcpy(m_cache, source, cacheMax * sizeof(int));
326         }
327         else
328         {
329                 delete [] m_cache;
330                 m_cache = 0;
331         }
332 }
333
334 int eDVBService::getCacheEntry(cacheID id)
335 {
336         if (id >= cacheMax || !m_cache)
337                 return -1;
338         return m_cache[id];
339 }
340
341 void eDVBService::setCacheEntry(cacheID id, int pid)
342 {
343         if (!m_cache)
344                 initCache();
345         if (id < cacheMax)
346                 m_cache[id] = pid;
347 }
348
349 DEFINE_REF(eDVBDB);
350
351 void eDVBDB::reloadServicelist()
352 {
353         loadServicelist(eEnv::resolve("${sysconfdir}/enigma2/lamedb").c_str());
354 }
355
356 void eDVBDB::parseServiceData(ePtr<eDVBService> s, std::string str)
357 {
358         while ((!str.empty()) && str[1]==':') // new: p:, f:, c:%02d...
359         {
360                 size_t c=str.find(',');
361                 char p=str[0];
362                 std::string v;
363                 if (c == std::string::npos)
364                 {
365                         v=str.substr(2);
366                         str="";
367                 } else
368                 {
369                         v=str.substr(2, c-2);
370                         str=str.substr(c+1);
371                 }
372 //              eDebug("[eDVBDB] %c ... %s", p, v.c_str());
373                 if (p == 'p')
374                         s->m_provider_name=v;
375                 else if (p == 'f')
376                 {
377                         sscanf(v.c_str(), "%x", &s->m_flags);
378                 } else if (p == 'c')
379                 {
380                         int cid, val;
381                         sscanf(v.c_str(), "%02d%x", &cid, &val);
382                         s->setCacheEntry((eDVBService::cacheID)cid,val);
383                 } else if (p == 'C')
384                 {
385                         int val;
386                         sscanf(v.c_str(), "%04x", &val);
387                         s->m_ca.push_back((uint16_t)val);
388                 }
389         }
390 }
391
392 static ePtr<eDVBFrontendParameters> parseFrontendData(const char* line, int version)
393 {
394         switch(line[0])
395         {
396                 case 's':
397                 {
398                         eDVBFrontendParametersSatellite sat;
399                         int frequency, symbol_rate, polarisation, fec, orbital_position, inversion,
400                                 flags=0,
401                                 system=eDVBFrontendParametersSatellite::System_DVB_S,
402                                 modulation=eDVBFrontendParametersSatellite::Modulation_QPSK,
403                                 rolloff=eDVBFrontendParametersSatellite::RollOff_alpha_0_35,
404                                 pilot=eDVBFrontendParametersSatellite::Pilot_Unknown;
405                         if (version == 3)
406                                 sscanf(line+2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
407                                         &frequency, &symbol_rate, &polarisation, &fec, &orbital_position,
408                                         &inversion, &system, &modulation, &rolloff, &pilot);
409                         else
410                                 sscanf(line+2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
411                                         &frequency, &symbol_rate, &polarisation, &fec, &orbital_position,
412                                         &inversion, &flags, &system, &modulation, &rolloff, &pilot);
413                         sat.frequency = frequency;
414                         sat.symbol_rate = symbol_rate;
415                         sat.polarisation = polarisation;
416                         sat.fec = fec;
417                         sat.orbital_position = orbital_position < 0 ? orbital_position + 3600 : orbital_position;
418                         sat.inversion = inversion;
419                         sat.system = system;
420                         sat.modulation = modulation;
421                         sat.rolloff = rolloff;
422                         sat.pilot = pilot;
423                         ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
424                         feparm->setDVBS(sat);
425                         feparm->setFlags(flags);
426                         return feparm;
427                 }
428                 case 't':
429                 {
430                         eDVBFrontendParametersTerrestrial ter;
431                         int frequency, bandwidth, code_rate_HP, code_rate_LP, modulation, transmission_mode,
432                                 guard_interval, hierarchy, inversion, flags = 0, plpid = 0;
433                         int system = eDVBFrontendParametersTerrestrial::System_DVB_T;
434                         sscanf(line+2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
435                                 &frequency, &bandwidth, &code_rate_HP, &code_rate_LP, &modulation,
436                                 &transmission_mode, &guard_interval, &hierarchy, &inversion, &flags, &system, &plpid);
437                         ter.frequency = frequency;
438                         switch (bandwidth)
439                         {
440                                 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz: ter.bandwidth = 8000000; break;
441                                 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz: ter.bandwidth = 7000000; break;
442                                 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz: ter.bandwidth = 6000000; break;
443                                 default:
444                                 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto: ter.bandwidth = 0; break;
445                                 case eDVBFrontendParametersTerrestrial::Bandwidth_5MHz: ter.bandwidth = 5000000; break;
446                                 case eDVBFrontendParametersTerrestrial::Bandwidth_1_712MHz: ter.bandwidth = 1712000; break;
447                                 case eDVBFrontendParametersTerrestrial::Bandwidth_10MHz: ter.bandwidth = 10000000; break;
448                         }
449                         ter.code_rate_HP = code_rate_HP;
450                         ter.code_rate_LP = code_rate_LP;
451                         ter.modulation = modulation;
452                         ter.transmission_mode = transmission_mode;
453                         ter.guard_interval = guard_interval;
454                         ter.hierarchy = hierarchy;
455                         ter.inversion = inversion;
456                         ter.system = system;
457                         ter.plpid = plpid;
458                         ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
459                         feparm->setDVBT(ter);
460                         feparm->setFlags(flags);
461                         return feparm;
462                 }
463                 case 'c':
464                 {
465                         eDVBFrontendParametersCable cab;
466                         int frequency, symbol_rate,
467                                 inversion=eDVBFrontendParametersCable::Inversion_Unknown,
468                                 modulation=eDVBFrontendParametersCable::Modulation_Auto,
469                                 fec_inner=eDVBFrontendParametersCable::FEC_Auto,
470                                 system = eDVBFrontendParametersCable::System_DVB_C_ANNEX_A,
471                                 flags=0;
472                         sscanf(line+2, "%d:%d:%d:%d:%d:%d:%d",
473                                 &frequency, &symbol_rate, &inversion, &modulation, &fec_inner, &flags, &system);
474                         cab.frequency = frequency;
475                         cab.fec_inner = fec_inner;
476                         cab.inversion = inversion;
477                         cab.symbol_rate = symbol_rate;
478                         cab.modulation = modulation;
479                         cab.system = system;
480                         ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
481                         feparm->setDVBC(cab);
482                         feparm->setFlags(flags);
483                         return feparm;
484                 }
485                 default:
486                         return NULL;
487         }
488 }
489
490 static eDVBChannelID parseChannelData(const char * line)
491 {
492         int dvb_namespace = -1, transport_stream_id = -1, original_network_id = -1;
493         sscanf(line, "%x:%x:%x", &dvb_namespace, &transport_stream_id, &original_network_id);
494         if (original_network_id == -1)
495                 return eDVBChannelID();
496         return eDVBChannelID(
497                         eDVBNamespace(dvb_namespace),
498                         eTransportStreamID(transport_stream_id),
499                         eOriginalNetworkID(original_network_id));
500 }
501
502 static eServiceReferenceDVB parseServiceRefData(const char *line)
503 {
504         int service_id = -1, dvb_namespace, transport_stream_id = -1, original_network_id = -1,
505                 service_type = -1, service_number = -1;
506         sscanf(line, "%x:%x:%x:%x:%d:%d", &service_id, &dvb_namespace, &transport_stream_id,
507                                           &original_network_id, &service_type, &service_number);
508         if (service_number == -1)
509                 return eServiceReferenceDVB();
510         return eServiceReferenceDVB(
511                                 eDVBNamespace(dvb_namespace),
512                                 eTransportStreamID(transport_stream_id),
513                                 eOriginalNetworkID(original_network_id),
514                                 eServiceID(service_id),
515                                 service_type);
516 }
517
518 void eDVBDB::loadServicelist(const char *file)
519 {
520         eDebug("[eDVBDB] ---- opening lame channel db");
521         CFile f(file, "rt");
522         if (!f) {
523                 eDebug("[eDVBDB] can't open %s: %m", file);
524                 return;
525         }
526
527         char line[256];
528         int version;
529         if ((!fgets(line, sizeof(line), f)) || sscanf(line, "eDVB services /%d/", &version) != 1)
530         {
531                 eDebug("[eDVBDB] not a valid servicefile");
532                 return;
533         }
534         eDebug("[eDVBDB] reading services (version %d)", version);
535
536         if ((!fgets(line, sizeof(line), f)) || strcmp(line, "transponders\n"))
537         {
538                 eDebug("[eDVBDB] services invalid, no transponders");
539                 return;
540         }
541         // clear all transponders
542         int tcount = 0;
543         while (!feof(f))
544         {
545                 if (!fgets(line, sizeof(line), f) || !strcmp(line, "end\n"))
546                         break;
547
548                 eDVBChannelID channelid = parseChannelData(line);
549                 if (!channelid)
550                         continue;
551
552                 if (!fgets(line, sizeof(line), f))
553                         break;
554                 ePtr<eDVBFrontendParameters> feparm = parseFrontendData(line + 1, version);
555                 if (feparm) {
556                         addChannelToList(channelid, feparm);
557                         tcount++;
558                 }
559                 if (!fgets(line, sizeof(line), f) || strcmp(line, "/\n"))
560                         break;
561         }
562
563         if ((!fgets(line, sizeof(line), f)) || strcmp(line, "services\n"))
564         {
565                 eDebug("[eDVBDB] services invalid, no services");
566                 return;
567         }
568         // clear all services
569         int scount=0;
570         while (!feof(f))
571         {
572                 int len;
573                 if (!fgets(line, sizeof(line), f) || !strcmp(line, "end\n"))
574                         break;
575
576                 eServiceReferenceDVB ref = parseServiceRefData(line);
577                 if (!ref)
578                         continue;
579                 if (!fgets(line, sizeof(line), f))
580                         break;
581                 len = strlen(line); /* strip newline */
582                 if (len > 0 && line[len - 1 ] == '\n')
583                         line[len - 1] = '\0';
584                 ePtr<eDVBService> s = new eDVBService;
585                 s->m_service_name = line;
586                 s->genSortName();
587
588                 if (!fgets(line, sizeof(line), f))
589                         break;
590                 len = strlen(line); /* strip newline */
591                 if (len > 0 && line[len - 1 ] == '\n')
592                         line[len - 1] = '\0';
593                 if (line[1] != ':')     // old ... (only service_provider)
594                         s->m_provider_name = line;
595                 else
596                         parseServiceData(s, line);
597                 addService(ref, s);
598                 scount++;
599         }
600
601         eDebug("[eDVBDB] loaded %d channels/transponders and %d services", tcount, scount);
602 }
603
604 void eDVBDB::saveServicelist(const char *file)
605 {
606         eDebug("[eDVBDB] ---- saving lame channel db");
607         std::string filename = file;
608         {
609         CFile f((filename + ".writing").c_str(), "w");
610         int channels=0, services=0;
611         if (!f)
612                 eFatal("[eDVBDB] couldn't save lame channel db!");
613         fprintf(f, "eDVB services /4/\n");
614         fprintf(f, "transponders\n");
615         for (std::map<eDVBChannelID, channel>::const_iterator i(m_channels.begin());
616                         i != m_channels.end(); ++i)
617         {
618                 const eDVBChannelID &chid = i->first;
619                 const channel &ch = i->second;
620
621                 fprintf(f, "%08x:%04x:%04x\n", chid.dvbnamespace.get(),
622                                 chid.transport_stream_id.get(), chid.original_network_id.get());
623                 eDVBFrontendParametersSatellite sat;
624                 eDVBFrontendParametersTerrestrial ter;
625                 eDVBFrontendParametersCable cab;
626                 unsigned int flags;  // flagOnlyFree yet..
627                 ch.m_frontendParameters->getFlags(flags);
628                 if (!ch.m_frontendParameters->getDVBS(sat))
629                 {
630                         if (sat.system == eDVBFrontendParametersSatellite::System_DVB_S2)
631                         {
632                                 fprintf(f, "\ts %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
633                                         sat.frequency, sat.symbol_rate,
634                                         sat.polarisation, sat.fec,
635                                         sat.orbital_position > 1800 ? sat.orbital_position - 3600 : sat.orbital_position,
636                                         sat.inversion,
637                                         flags,
638                                         sat.system,
639                                         sat.modulation,
640                                         sat.rolloff,
641                                         sat.pilot);
642                         }
643                         else
644                         {
645                                 fprintf(f, "\ts %d:%d:%d:%d:%d:%d:%d\n",
646                                         sat.frequency, sat.symbol_rate,
647                                         sat.polarisation, sat.fec,
648                                         sat.orbital_position > 1800 ? sat.orbital_position - 3600 : sat.orbital_position,
649                                         sat.inversion, flags);
650                         }
651                 }
652                 else if (!ch.m_frontendParameters->getDVBT(ter))
653                 {
654                         int bandwidth;
655                         switch (ter.bandwidth)
656                         {
657                         case 8000000: bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
658                         case 7000000: bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
659                         case 6000000: bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
660                         default:
661                         case 0: bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
662                         case 5000000: bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_5MHz; break;
663                         case 1712000: bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_1_712MHz; break;
664                         case 10000000: bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_10MHz; break;
665                         }
666                         if (ter.system == eDVBFrontendParametersTerrestrial::System_DVB_T_T2)
667                         {
668                                 /*
669                                  * System_DVB_T_T2 (T with fallback to T2) is used only when 'system' is not (yet) specified.
670                                  * When storing a transponder with 'system' still equalling System_DVB_T_T2,
671                                  * there has been no fallback to T2 (in which case 'system' would have been set to
672                                  * System_DVB_T2).
673                                  * So we are dealing with a T transponder, store it with System_DVB_T.
674                                  * (fallback to T2 is only used while scanning, System_DVB_T_T2 should never be used for actual
675                                  * transponders in the lamedb)
676                                  */
677                                 ter.system = eDVBFrontendParametersTerrestrial::System_DVB_T;
678                         }
679                         fprintf(f, "\tt %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
680                                 ter.frequency, bandwidth, ter.code_rate_HP,
681                                 ter.code_rate_LP, ter.modulation, ter.transmission_mode,
682                                 ter.guard_interval, ter.hierarchy, ter.inversion, flags, ter.system, ter.plpid);
683                 }
684                 else if (!ch.m_frontendParameters->getDVBC(cab))
685                 {
686                         fprintf(f, "\tc %d:%d:%d:%d:%d:%d:%d\n",
687                                 cab.frequency, cab.symbol_rate, cab.inversion, cab.modulation, cab.fec_inner, flags, cab.system);
688                 }
689                 fprintf(f, "/\n");
690                 channels++;
691         }
692         fprintf(f, "end\nservices\n");
693
694         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator i(m_services.begin());
695                 i != m_services.end(); ++i)
696         {
697                 const eServiceReferenceDVB &s = i->first;
698                 fprintf(f, "%04x:%08x:%04x:%04x:%d:%d\n",
699                                 s.getServiceID().get(), s.getDVBNamespace().get(),
700                                 s.getTransportStreamID().get(),s.getOriginalNetworkID().get(),
701                                 s.getServiceType(),
702                                 0);
703
704                 fprintf(f, "%s\n", i->second->m_service_name.c_str());
705
706                 fprintf(f, "p:%s", i->second->m_provider_name.c_str());
707
708                 // write cached pids
709                 for (int x=0; x < eDVBService::cacheMax; ++x)
710                 {
711                         int entry = i->second->getCacheEntry((eDVBService::cacheID)x);
712                         if (entry != -1)
713                                 fprintf(f, ",c:%02d%04x", x, entry);
714                 }
715
716                 // write cached ca pids
717                 for (CAID_LIST::const_iterator ca(i->second->m_ca.begin());
718                         ca != i->second->m_ca.end(); ++ca)
719                         fprintf(f, ",C:%04x", *ca);
720
721                 if (i->second->m_flags)
722                         fprintf(f, ",f:%x", i->second->m_flags);
723
724                 fprintf(f, "\n");
725                 services++;
726         }
727         fprintf(f, "end\nHave a lot of bugs!\n");
728         eDebug("[eDVBDB] saved %d channels and %d services!", channels, services);
729         f.sync();
730         }
731         rename((filename + ".writing").c_str(), filename.c_str());
732 }
733
734 void eDVBDB::saveServicelist()
735 {
736         saveServicelist(eEnv::resolve("${sysconfdir}/enigma2/lamedb").c_str());
737 }
738
739 void eDVBDB::loadBouquet(const char *path)
740 {
741         std::vector<std::string> userbouquetsfiles;
742         std::string extension;
743         if (!strcmp(path, "bouquets.tv"))
744                 extension = ".tv";
745         if (!strcmp(path, "bouquets.radio"))
746                 extension = ".radio";
747         if (extension.length())
748         {
749                 std::string p = eEnv::resolve("${sysconfdir}/enigma2/");
750                 DIR *dir = opendir(p.c_str());
751                 if (!dir)
752                 {
753                         eDebug("[eDVBDB] Cannot open directory where the userbouquets should be expected..");
754                         return;
755                 }
756                 dirent *entry;
757                 while((entry = readdir(dir)) != NULL)
758                         if (entry->d_type == DT_REG)
759                         {
760                                 std::string filename = entry->d_name;
761                                 if (filename.find("userbouquet") != std::string::npos && filename.find(extension, (filename.length() - extension.size())) != std::string::npos)
762                                         userbouquetsfiles.push_back(filename);
763                         }
764                 closedir(dir);
765         }
766         std::string bouquet_name = path;
767         if (!bouquet_name.length())
768         {
769                 eDebug("[eDVBDB] Bouquet load failed.. no path given..");
770                 return;
771         }
772         size_t pos = bouquet_name.rfind('/');
773         if ( pos != std::string::npos )
774                 bouquet_name.erase(0, pos+1);
775         if (bouquet_name.empty())
776         {
777                 eDebug("[eDVBDB] Bouquet load failed.. no filename given..");
778                 return;
779         }
780         eBouquet &bouquet = m_bouquets[bouquet_name];
781         bouquet.m_filename = bouquet_name;
782         std::list<eServiceReference> &list = bouquet.m_services;
783         list.clear();
784
785         int entries = 0;
786         std::string enigma_conf = eEnv::resolve("${sysconfdir}/enigma2/");
787         std::string file_path;
788         bool found = false;
789
790         static const char *const searchpath[] = { "alternatives", "bouquets", "", 0 };
791
792         for(int index = 0; searchpath[index]; index++)
793         {
794                 file_path = enigma_conf + searchpath[index] + "/" + path;
795
796                 if (!access(file_path.c_str(), R_OK))
797                 {
798                         found = true;
799                         break;
800                 }
801         }
802
803         if(!found)
804         {
805                 eDebug("[eDVBDB] can't open %s: %m", (enigma_conf + ".../" + path).c_str());
806                 if (!strcmp(path, "bouquets.tv"))
807                 {
808                         file_path = enigma_conf + path;
809
810                         eDebug("[eDVBDB] recreate bouquets.tv");
811                         bouquet.m_bouquet_name="Bouquets (TV)";
812                         bouquet.flushChanges();
813                 }
814                 else
815                 {
816                         if (!strcmp(path, "bouquets.radio"))
817                         {
818                                 file_path = enigma_conf + path;
819
820                                 eDebug("[eDVBDB] recreate bouquets.radio");
821                                 bouquet.m_bouquet_name="Bouquets (Radio)";
822                                 bouquet.flushChanges();
823                         }
824                         else
825                                 file_path = "";
826                 }
827         }
828
829         eDebug("[eDVBDB] loading bouquet... %s", file_path.c_str());
830         CFile fp(file_path, "rt");
831
832         if (fp)
833         {
834                 size_t linesize = 256;
835                 char *line = (char*)malloc(linesize);
836                 bool read_descr=false;
837                 eServiceReference *e = NULL;
838                 while (1)
839                 {
840                         int len;
841                         if ((len = getline(&line, &linesize, fp)) < 2) break;
842                         /* strip newline */
843                         line[--len] = 0;
844                         /* strip carriage return (when found) */
845                         if (line[len - 1] == '\r') line[--len] = 0;
846                         if (!strncmp(line, "#SERVICE", 8))
847                         {
848                                 int offs = line[8] == ':' ? 10 : 9;
849                                 eServiceReference tmp(line+offs);
850                                 if ( tmp.flags&eServiceReference::canDescent )
851                                 {
852                                         size_t pos = tmp.path.rfind('/');
853                                         char buf[256];
854                                         std::string path = tmp.path;
855                                         if ( pos != std::string::npos )
856                                                 path.erase(0, pos+1);
857                                         if (path.empty())
858                                         {
859                                                 eDebug("[eDVBDB] Bouquet load failed.. no filename given..");
860                                                 continue;
861                                         }
862                                         pos = path.find("FROM BOUQUET ");
863                                         if (pos != std::string::npos)
864                                         {
865                                                 char endchr = path[pos+13];
866                                                 if (endchr != '"')
867                                                 {
868                                                         eDebug("[eDVBDB] ignore invalid bouquet '%s' (only \" are allowed)",
869                                                                 tmp.toString().c_str());
870                                                         continue;
871                                                 }
872                                                 char *beg = &path[pos+14];
873                                                 char *end = strchr(beg, endchr);
874                                                 path.assign(beg, end - beg);
875                                         }
876                                         else
877                                         {
878                                                 snprintf(buf, sizeof(buf), "FROM BOUQUET \"%s\" ORDER BY bouquet", path.c_str());
879                                                 tmp.path = buf;
880                                         }
881                                         for(unsigned int i=0; i<userbouquetsfiles.size(); ++i)
882                                         {
883                                                 if (userbouquetsfiles[i].compare(path.c_str()) == 0)
884                                                 {
885                                                         userbouquetsfiles.erase(userbouquetsfiles.begin() + i);
886                                                         break;
887                                                 }
888                                         }
889                                         loadBouquet(path.c_str());
890                                 }
891                                 list.push_back(tmp);
892                                 e = &list.back();
893                                 read_descr=true;
894                                 ++entries;
895                         }
896                         else if (read_descr && !strncmp(line, "#DESCRIPTION", 12))
897                         {
898                                 int offs = line[12] == ':' ? 14 : 13;
899                                 e->name = line+offs;
900                                 read_descr=false;
901                         }
902                         else if (!strncmp(line, "#NAME ", 6))
903                                 bouquet.m_bouquet_name=line+6;
904                 }
905                 free(line);
906         }
907
908         if (userbouquetsfiles.size())
909         {
910                 for(unsigned int i=0; i<userbouquetsfiles.size(); ++i)
911                 {
912                         if (m_load_unlinked_userbouquets)
913                         {
914                                 eDebug("[eDVBDB] Adding additional userbouquet %s", userbouquetsfiles[i].c_str());
915                                 char buf[256];
916                                 if (!strcmp(path, "bouquets.tv"))
917                                         snprintf(buf, sizeof(buf), "1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"%s\" ORDER BY bouquet", userbouquetsfiles[i].c_str());
918                                 else
919                                         snprintf(buf, sizeof(buf), "1:7:2:0:0:0:0:0:0:0:FROM BOUQUET \"%s\" ORDER BY bouquet", userbouquetsfiles[i].c_str());
920                                 eServiceReference tmp(buf);
921                                 loadBouquet(userbouquetsfiles[i].c_str());
922                                 if (!strcmp(userbouquetsfiles[i].c_str(), "userbouquet.LastScanned.tv"))
923                                         list.push_back(tmp);
924                                 else
925                                         list.push_front(tmp);
926                                 ++entries;
927                         }
928                         else
929                         {
930                                 std::string filename = eEnv::resolve("${sysconfdir}/enigma2/" + userbouquetsfiles[i]);
931                                 std::string newfilename(filename);
932                                 newfilename.append(".del");
933                                 eDebug("[eDVBDB] Rename unlinked bouquet file %s to %s", filename.c_str(), newfilename.c_str());
934                                 rename(filename.c_str(), newfilename.c_str());
935                         }
936                 }
937                 bouquet.flushChanges();
938         }
939         eDebug("[eDVBDB] %d entries in Bouquet %s", entries, bouquet_name.c_str());
940 }
941
942 void eDVBDB::reloadBouquets()
943 {
944         m_bouquets.clear();
945         loadBouquet("bouquets.tv");
946         loadBouquet("bouquets.radio");
947         // create default bouquets when missing
948         if ( m_bouquets.find("userbouquet.favourites.tv") == m_bouquets.end() )
949         {
950                 eBouquet &b = m_bouquets["userbouquet.favourites.tv"];
951                 b.m_filename = "userbouquet.favourites.tv";
952                 b.m_bouquet_name = "Favourites (TV)";
953                 b.flushChanges();
954                 eServiceReference ref;
955                 ref.type=1;
956                 ref.flags=7;
957                 ref.data[0]=1;
958                 ref.path="FROM BOUQUET \"userbouquet.favourites.tv\" ORDER BY bouquet";
959                 eBouquet &parent = m_bouquets["bouquets.tv"];
960                 parent.m_services.push_back(ref);
961                 parent.flushChanges();
962         }
963         if ( m_bouquets.find("userbouquet.favourites.radio") == m_bouquets.end() )
964         {
965                 eBouquet &b = m_bouquets["userbouquet.favourites.radio"];
966                 b.m_filename = "userbouquet.favourites.radio";
967                 b.m_bouquet_name = "Favourites (Radio)";
968                 b.flushChanges();
969                 eServiceReference ref;
970                 ref.type=1;
971                 ref.flags=7;
972                 ref.data[0]=2;
973                 ref.path="FROM BOUQUET \"userbouquet.favourites.radio\" ORDER BY bouquet";
974                 eBouquet &parent = m_bouquets["bouquets.radio"];
975                 parent.m_services.push_back(ref);
976                 parent.flushChanges();
977         }
978         renumberBouquet();
979 }
980
981 void eDVBDB::renumberBouquet()
982 {
983         eDebug("[eDVBDB] Renumbering...");
984         renumberBouquet( m_bouquets["bouquets.tv"] );
985         renumberBouquet( m_bouquets["bouquets.radio"] );
986 }
987
988 void eDVBDB::setNumberingMode(bool numberingMode)
989 {
990         if (m_numbering_mode != numberingMode)
991         {
992                 m_numbering_mode = numberingMode;
993                 renumberBouquet();
994         }
995 }
996
997 int eDVBDB::renumberBouquet(eBouquet &bouquet, int startChannelNum)
998 {
999         std::list<eServiceReference> &list = bouquet.m_services;
1000         for (std::list<eServiceReference>::iterator it = list.begin(); it != list.end(); ++it)
1001         {
1002                 eServiceReference &ref = *it;
1003                 if (ref.flags & eServiceReference::canDescent)
1004                 {
1005                         std::string filename = ref.toString();
1006                         size_t pos = filename.find("FROM BOUQUET ");
1007                         if(pos != std::string::npos)
1008                         {
1009                                 char endchr = filename[pos+13];
1010                                 if (endchr == '"')
1011                                 {
1012                                         char *beg = &filename[pos+14];
1013                                         char *end = strchr(beg, endchr);
1014                                         filename.assign(beg, end - beg);
1015                                         eBouquet &subBouquet = m_bouquets[filename];
1016                                         if (m_numbering_mode || filename.find("alternatives.") == 0)
1017                                                 renumberBouquet(subBouquet);
1018                                         else
1019                                                 startChannelNum = renumberBouquet(subBouquet, startChannelNum);
1020                                 }
1021                         }
1022                 }
1023                 if( !(ref.flags & (eServiceReference::isMarker|eServiceReference::isDirectory)) ||
1024                    (ref.flags & eServiceReference::isNumberedMarker) )
1025                         ref.number = startChannelNum++;
1026
1027         }
1028         return startChannelNum;
1029 }
1030
1031 eDVBDB *eDVBDB::instance;
1032
1033 using namespace xmlcc;
1034
1035 eDVBDB::eDVBDB()
1036         : m_numbering_mode(false), m_load_unlinked_userbouquets(true)
1037 {
1038         instance = this;
1039         reloadServicelist();
1040 }
1041
1042 PyObject *eDVBDB::readSatellites(ePyObject sat_list, ePyObject sat_dict, ePyObject tp_dict)
1043 {
1044         if (!PyDict_Check(tp_dict)) {
1045                 PyErr_SetString(PyExc_StandardError,
1046                         "type error");
1047                         eDebug("[eDVBDB] readSatellites arg 2 is not a python dict");
1048                 return NULL;
1049         }
1050         else if (!PyDict_Check(sat_dict))
1051         {
1052                 PyErr_SetString(PyExc_StandardError,
1053                         "type error");
1054                         eDebug("[eDVBDB] readSatellites arg 1 is not a python dict");
1055                 return NULL;
1056         }
1057         else if (!PyList_Check(sat_list))
1058         {
1059                 PyErr_SetString(PyExc_StandardError,
1060                         "type error");
1061                         eDebug("[eDVBDB] readSatellites arg 0 is not a python list");
1062                 return NULL;
1063         }
1064         XMLTree tree;
1065         const char* satellitesFilename = "/etc/enigma2/satellites.xml";
1066         if (::access(satellitesFilename, R_OK) < 0)
1067         {
1068                 satellitesFilename = "/etc/tuxbox/satellites.xml";
1069         }
1070         tree.setFilename(satellitesFilename);
1071         tree.read();
1072         Element *root = tree.getRoot();
1073         if (!root)
1074         {
1075                 eDebug("[eDVBDB] couldn't open %s!!", satellitesFilename);
1076                 Py_INCREF(Py_False);
1077                 return Py_False;
1078         }
1079         int tmp, *dest = NULL,
1080                 modulation, system, freq, sr, pol, fec, inv, pilot, rolloff, tsid, onid;
1081         char *end_ptr;
1082         const Attribute *at;
1083         std::string name;
1084         const ElementList &root_elements = root->getElementList();
1085         for (ElementConstIterator it(root_elements.begin()); it != root_elements.end(); ++it)
1086         {
1087 //              eDebug("[eDVBDB] element: %s", (*it)->name().c_str());
1088                 const Element *el = *it;
1089                 const ElementList &sat_elements = el->getElementList();
1090                 const AttributeList &sat_attributes = el->getAttributeList();
1091                 ePyObject sat_name;
1092                 ePyObject sat_pos;
1093                 ePyObject sat_flags;
1094                 for (AttributeConstIterator it(sat_attributes.begin()); it != sat_attributes.end(); ++it)
1095                 {
1096 //                      eDebug("[eDVBDB] \tattr: %s", at->name().c_str());
1097                         at = *it;
1098                         name = at->name();
1099                         if (name == "name")
1100                                 sat_name = PyString_FromString(at->value().c_str());
1101                         else if (name == "flags")
1102                         {
1103                                 tmp = strtol(at->value().c_str(), &end_ptr, 10);
1104                                 if (!*end_ptr)
1105                                         sat_flags = PyInt_FromLong(tmp);
1106                         }
1107                         else if (name == "position")
1108                         {
1109                                 tmp = strtol(at->value().c_str(), &end_ptr, 10);
1110                                 if (!*end_ptr)
1111                                 {
1112                                         if (tmp < 0)
1113                                                 tmp = 3600 + tmp;
1114                                         sat_pos = PyInt_FromLong(tmp);
1115                                 }
1116                         }
1117                 }
1118                 if (sat_pos && sat_name)
1119                 {
1120                         ePyObject tplist = PyList_New(0);
1121                         ePyObject tuple = PyTuple_New(3);
1122                         if (!sat_flags)
1123                                 sat_flags = PyInt_FromLong(0);
1124                         PyTuple_SET_ITEM(tuple, 0, sat_pos);
1125                         PyTuple_SET_ITEM(tuple, 1, sat_name);
1126                         PyTuple_SET_ITEM(tuple, 2, sat_flags);
1127                         PyList_Append(sat_list, tuple);
1128                         Py_DECREF(tuple);
1129                         PyDict_SetItem(sat_dict, sat_pos, sat_name);
1130                         PyDict_SetItem(tp_dict, sat_pos, tplist);
1131                         for (ElementConstIterator it(sat_elements.begin()); it != sat_elements.end(); ++it)
1132                         {
1133                                 //eDebug("[eDVBDB] \telement: %s", (*it)->name().c_str());
1134                                 const AttributeList &tp_attributes = (*it)->getAttributeList();
1135                                 AttributeConstIterator end = tp_attributes.end();
1136                                 modulation = eDVBFrontendParametersSatellite::Modulation_QPSK;
1137                                 system = eDVBFrontendParametersSatellite::System_DVB_S;
1138                                 freq = 0;
1139                                 sr = 0;
1140                                 pol = -1;
1141                                 fec = eDVBFrontendParametersSatellite::FEC_Auto;
1142                                 inv = eDVBFrontendParametersSatellite::Inversion_Unknown;
1143                                 pilot = eDVBFrontendParametersSatellite::Pilot_Unknown;
1144                                 rolloff = eDVBFrontendParametersSatellite::RollOff_alpha_0_35;
1145                                 tsid = -1;
1146                                 onid = -1;
1147
1148                                 for (AttributeConstIterator it(tp_attributes.begin()); it != end; ++it)
1149                                 {
1150                                         at = *it;
1151                                         //eDebug("[eDVBDB] \t\tattr: %s", at->name().c_str());
1152                                         name = at->name();
1153                                         if (name == "modulation") dest = &modulation;
1154                                         else if (name == "system") dest = &system;
1155                                         else if (name == "frequency") dest = &freq;
1156                                         else if (name == "symbol_rate") dest = &sr;
1157                                         else if (name == "polarization") dest = &pol;
1158                                         else if (name == "fec_inner") dest = &fec;
1159                                         else if (name == "inversion") dest = &inv;
1160                                         else if (name == "rolloff") dest = &rolloff;
1161                                         else if (name == "pilot") dest = &pilot;
1162                                         else if (name == "tsid") dest = &tsid;
1163                                         else if (name == "onid") dest = &onid;
1164                                         else continue;
1165                                         if (dest)
1166                                         {
1167                                                 //eDebug("[eDVBDB] \t\t\tvalue: %s", at->value().c_str());
1168                                                 tmp = strtol(at->value().c_str(), &end_ptr, 10);
1169                                                 if (!*end_ptr)
1170                                                         *dest = tmp;
1171                                         }
1172                                 }
1173                                 if (freq && sr && pol != -1)
1174                                 {
1175                                         tuple = PyTuple_New(12);
1176                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
1177                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(freq));
1178                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(sr));
1179                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(pol));
1180                                         PyTuple_SET_ITEM(tuple, 4, PyInt_FromLong(fec));
1181                                         PyTuple_SET_ITEM(tuple, 5, PyInt_FromLong(system));
1182                                         PyTuple_SET_ITEM(tuple, 6, PyInt_FromLong(modulation));
1183                                         PyTuple_SET_ITEM(tuple, 7, PyInt_FromLong(inv));
1184                                         PyTuple_SET_ITEM(tuple, 8, PyInt_FromLong(rolloff));
1185                                         PyTuple_SET_ITEM(tuple, 9, PyInt_FromLong(pilot));
1186                                         PyTuple_SET_ITEM(tuple, 10, PyInt_FromLong(tsid));
1187                                         PyTuple_SET_ITEM(tuple, 11, PyInt_FromLong(onid));
1188                                         PyList_Append(tplist, tuple);
1189                                         Py_DECREF(tuple);
1190                                 }
1191                         }
1192                         Py_DECREF(tplist);
1193                 }
1194                 else
1195                 {
1196                         if (sat_pos)
1197                                 Py_DECREF(sat_pos);
1198                         if (sat_name)
1199                                 Py_DECREF(sat_name);
1200                         if (sat_flags)
1201                                 Py_DECREF(sat_flags);
1202                 }
1203         }
1204         Py_INCREF(Py_True);
1205         return Py_True;
1206 }
1207
1208 PyObject *eDVBDB::readCables(ePyObject cab_list, ePyObject tp_dict)
1209 {
1210         if (!PyDict_Check(tp_dict)) {
1211                 PyErr_SetString(PyExc_StandardError,
1212                         "type error");
1213                         eDebug("[eDVBDB] readCables arg 1 is not a python dict");
1214                 return NULL;
1215         }
1216         else if (!PyList_Check(cab_list))
1217         {
1218                 PyErr_SetString(PyExc_StandardError,
1219                         "type error");
1220                         eDebug("[eDVBDB] readCables arg 0 is not a python list");
1221                 return NULL;
1222         }
1223         XMLTree tree;
1224         const char* cablesFilename = "/etc/enigma2/cables.xml";
1225         if (::access(cablesFilename, R_OK) < 0)
1226         {
1227                 cablesFilename = "/etc/tuxbox/cables.xml";
1228         }
1229         tree.setFilename(cablesFilename);
1230         tree.read();
1231         Element *root = tree.getRoot();
1232         if (!root)
1233         {
1234                 eDebug("[eDVBDB] couldn't open %s!!", cablesFilename);
1235                 Py_INCREF(Py_False);
1236                 return Py_False;
1237         }
1238         const Attribute *at;
1239         int tmp, *dest,
1240                 modulation, fec, freq, sr, inversion, system;
1241         std::string name;
1242         char *end_ptr;
1243         const ElementList &root_elements = root->getElementList();
1244         for (ElementConstIterator it(root_elements.begin()); it != root_elements.end(); ++it)
1245         {
1246 //              eDebug("[eDVBDB] element: %s", el->name().c_str());
1247                 const Element *el = *it;
1248                 const ElementList &cab_elements = el->getElementList();
1249                 const AttributeList &cab_attributes = el->getAttributeList();
1250                 ePyObject cab_name;
1251                 ePyObject cab_flags;
1252                 for (AttributeConstIterator it(cab_attributes.begin()); it != cab_attributes.end(); ++it)
1253                 {
1254 //                      eDebug("[eDVBDB]\tattr: %s", at->name().c_str());
1255                         at = *it;
1256                         name = at->name();
1257                         if (name == "name")
1258                                 cab_name = PyString_FromString(at->value().c_str());
1259                         else if (name == "flags")
1260                         {
1261                                 tmp = strtol(at->value().c_str(), &end_ptr, 10);
1262                                 if (!*end_ptr)
1263                                         cab_flags = PyInt_FromLong(tmp);
1264                         }
1265                 }
1266                 if (cab_name)
1267                 {
1268                         ePyObject tplist = PyList_New(0);
1269                         ePyObject tuple = PyTuple_New(2);
1270                         if (!cab_flags)
1271                                 cab_flags = PyInt_FromLong(0);
1272                         PyTuple_SET_ITEM(tuple, 0, cab_name);
1273                         PyTuple_SET_ITEM(tuple, 1, cab_flags);
1274                         PyList_Append(cab_list, tuple);
1275                         Py_DECREF(tuple);
1276                         PyDict_SetItem(tp_dict, cab_name, tplist);
1277                         for (ElementConstIterator it(cab_elements.begin()); it != cab_elements.end(); ++it)
1278                         {
1279 //                              eDebug("[eDVBDB]\telement: %s", (*it)->name().c_str());
1280                                 const AttributeList &tp_attributes = (*it)->getAttributeList();
1281                                 AttributeConstIterator end = tp_attributes.end();
1282                                 modulation = eDVBFrontendParametersCable::Modulation_QAM64;
1283                                 fec = eDVBFrontendParametersCable::FEC_Auto;
1284                                 system = eDVBFrontendParametersCable::System_DVB_C_ANNEX_A;
1285                                 inversion = eDVBFrontendParametersCable::Inversion_Unknown;
1286                                 freq = 0;
1287                                 sr = 0;
1288                                 for (AttributeConstIterator it(tp_attributes.begin()); it != end; ++it)
1289                                 {
1290 //                                      eDebug("[eDVBDB]\t\tattr: %s", at->name().c_str());
1291                                         at = *it;
1292                                         dest = 0;
1293                                         name = at->name();
1294                                         if (name == "modulation") dest = &modulation;
1295                                         else if (name == "frequency") dest = &freq;
1296                                         else if (name == "symbol_rate") dest = &sr;
1297                                         else if (name == "fec_inner") dest = &fec;
1298                                         else if (name == "inversion") dest = &inversion;
1299                                         else if (name == "system") dest = &system;
1300                                         else continue;
1301                                         if (dest)
1302                                         {
1303                                                 tmp = strtol(at->value().c_str(), &end_ptr, 10);
1304                                                 if (!*end_ptr)
1305                                                         *dest = tmp;
1306                                         }
1307                                 }
1308                                 if (freq && sr)
1309                                 {
1310                                         while (freq > 999999)
1311                                                 freq /= 10;
1312                                         tuple = PyTuple_New(7);
1313                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
1314                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(freq));
1315                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(sr));
1316                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(modulation));
1317                                         PyTuple_SET_ITEM(tuple, 4, PyInt_FromLong(fec));
1318                                         PyTuple_SET_ITEM(tuple, 5, PyInt_FromLong(inversion));
1319                                         PyTuple_SET_ITEM(tuple, 6, PyInt_FromLong(system));
1320                                         PyList_Append(tplist, tuple);
1321                                         Py_DECREF(tuple);
1322                                 }
1323                         }
1324                         Py_DECREF(tplist);
1325                 }
1326                 else if (cab_flags)
1327                         Py_DECREF(cab_flags);
1328         }
1329         Py_INCREF(Py_True);
1330         return Py_True;
1331 }
1332
1333 PyObject *eDVBDB::readTerrestrials(ePyObject ter_list, ePyObject tp_dict)
1334 {
1335         if (!PyDict_Check(tp_dict)) {
1336                 PyErr_SetString(PyExc_StandardError,
1337                         "type error");
1338                         eDebug("[eDVBDB] readTerrestrials arg 1 is not a python dict");
1339                 return NULL;
1340         }
1341         else if (!PyList_Check(ter_list))
1342         {
1343                 PyErr_SetString(PyExc_StandardError,
1344                         "type error");
1345                         eDebug("[eDVBDB] readTerrestrials arg 0 is not a python list");
1346                 return NULL;
1347         }
1348         XMLTree tree;
1349         const char* terrestrialFilename = "/etc/enigma2/terrestrial.xml";
1350         if (::access(terrestrialFilename, R_OK) < 0)
1351         {
1352                 terrestrialFilename = "/etc/tuxbox/terrestrial.xml";
1353         }
1354         tree.setFilename(terrestrialFilename);
1355         tree.read();
1356         Element *root = tree.getRoot();
1357         if (!root)
1358         {
1359                 eDebug("[eDVBDB] couldn't open %s!!", terrestrialFilename);
1360                 Py_INCREF(Py_False);
1361                 return Py_False;
1362         }
1363         const Attribute *at;
1364         std::string name;
1365         int tmp, *dest,
1366                 freq, bw, constellation, crh, crl, guard, transm, hierarchy, inv, system, plpid;
1367         char *end_ptr;
1368         const ElementList &root_elements = root->getElementList();
1369         for (ElementConstIterator it(root_elements.begin()); it != root_elements.end(); ++it)
1370         {
1371 //              eDebug("[eDVBDB] element: %s", el->name().c_str());
1372                 const Element *el = *it;
1373                 const ElementList &ter_elements = el->getElementList();
1374                 const AttributeList &ter_attributes = el->getAttributeList();
1375                 ePyObject ter_name;
1376                 ePyObject ter_flags;
1377                 for (AttributeConstIterator it(ter_attributes.begin()); it != ter_attributes.end(); ++it)
1378                 {
1379 //                      eDebug("[eDVBDB]\tattr: %s", at->name().c_str());
1380                         at = *it;
1381                         name = at->name();
1382                         if (name == "name")
1383                                 ter_name = PyString_FromString(at->value().c_str());
1384                         else if (name == "flags")
1385                         {
1386                                 tmp = strtol(at->value().c_str(), &end_ptr, 10);
1387                                 if (!*end_ptr)
1388                                         ter_flags = PyInt_FromLong(tmp);
1389                         }
1390                 }
1391                 if (ter_name)
1392                 {
1393                         ePyObject tplist = PyList_New(0);
1394                         ePyObject tuple = PyTuple_New(2);
1395                         if (!ter_flags)
1396                                 ter_flags = PyInt_FromLong(0);
1397                         PyTuple_SET_ITEM(tuple, 0, ter_name);
1398                         PyTuple_SET_ITEM(tuple, 1, ter_flags);
1399                         PyList_Append(ter_list, tuple);
1400                         Py_DECREF(tuple);
1401                         PyDict_SetItem(tp_dict, ter_name, tplist);
1402                         for (ElementConstIterator it(ter_elements.begin()); it != ter_elements.end(); ++it)
1403                         {
1404 //                              eDebug("[eDVBDB]\telement: %s", (*it)->name().c_str());
1405                                 const AttributeList &tp_attributes = (*it)->getAttributeList();
1406                                 AttributeConstIterator end = tp_attributes.end();
1407                                 freq = 0;
1408                                 bw = eDVBFrontendParametersTerrestrial::Bandwidth_Auto;
1409                                 constellation = eDVBFrontendParametersTerrestrial::Modulation_Auto;
1410                                 crh = eDVBFrontendParametersTerrestrial::FEC_Auto;
1411                                 crl = eDVBFrontendParametersTerrestrial::FEC_Auto;
1412                                 guard = eDVBFrontendParametersTerrestrial::GuardInterval_Auto;
1413                                 transm = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto;
1414                                 hierarchy = eDVBFrontendParametersTerrestrial::Hierarchy_Auto;
1415                                 inv = eDVBFrontendParametersTerrestrial::Inversion_Unknown;
1416                                 system = eDVBFrontendParametersTerrestrial::System_DVB_T_T2;
1417                                 plpid = 0;
1418                                 for (AttributeConstIterator it(tp_attributes.begin()); it != end; ++it)
1419                                 {
1420 //                                      eDebug("[eDVBDB]\t\tattr: %s", at->name().c_str());
1421                                         at = *it;
1422                                         dest = 0;
1423                                         name = at->name();
1424                                         if (name == "centre_frequency") dest = &freq;
1425                                         else if (name == "bandwidth") dest = &bw;
1426                                         else if (name == "constellation") dest = &constellation;
1427                                         else if (name == "code_rate_hp") dest = &crh;
1428                                         else if (name == "code_rate_lp") dest = &crl;
1429                                         else if (name == "guard_interval") dest = &guard;
1430                                         else if (name == "transmission_mode") dest = &transm;
1431                                         else if (name == "hierarchy_information") dest = &hierarchy;
1432                                         else if (name == "inversion") dest = &inv;
1433                                         else if (name == "system") dest = &system;
1434                                         else if (name == "plp_id") dest = &plpid;
1435                                         else continue;
1436                                         if (dest)
1437                                         {
1438                                                 tmp = strtol(at->value().c_str(), &end_ptr, 10);
1439                                                 if (!*end_ptr)
1440                                                         *dest = tmp;
1441                                         }
1442                                 }
1443                                 if (freq)
1444                                 {
1445                                         switch (bw)
1446                                         {
1447                                         case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz: bw = 8000000; break;
1448                                         case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz: bw = 7000000; break;
1449                                         case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz: bw = 6000000; break;
1450                                         default:
1451                                         case eDVBFrontendParametersTerrestrial::Bandwidth_Auto: bw = 0; break;
1452                                         case eDVBFrontendParametersTerrestrial::Bandwidth_5MHz: bw = 5000000; break;
1453                                         case eDVBFrontendParametersTerrestrial::Bandwidth_1_712MHz: bw = 1712000; break;
1454                                         case eDVBFrontendParametersTerrestrial::Bandwidth_10MHz: bw = 10000000; break;
1455                                         }
1456                                         if (crh > eDVBFrontendParametersTerrestrial::FEC_8_9)
1457                                                 crh = eDVBFrontendParametersTerrestrial::FEC_Auto;
1458                                         if (crl > eDVBFrontendParametersTerrestrial::FEC_8_9)
1459                                                 crl = eDVBFrontendParametersTerrestrial::FEC_Auto;
1460                                         tuple = PyTuple_New(12);
1461                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(2));
1462                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(freq));
1463                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(bw));
1464                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(constellation));
1465                                         PyTuple_SET_ITEM(tuple, 4, PyInt_FromLong(crh));
1466                                         PyTuple_SET_ITEM(tuple, 5, PyInt_FromLong(crl));
1467                                         PyTuple_SET_ITEM(tuple, 6, PyInt_FromLong(guard));
1468                                         PyTuple_SET_ITEM(tuple, 7, PyInt_FromLong(transm));
1469                                         PyTuple_SET_ITEM(tuple, 8, PyInt_FromLong(hierarchy));
1470                                         PyTuple_SET_ITEM(tuple, 9, PyInt_FromLong(inv));
1471                                         PyTuple_SET_ITEM(tuple, 10, PyInt_FromLong(system));
1472                                         PyTuple_SET_ITEM(tuple, 11, PyInt_FromLong(plpid));
1473                                         PyList_Append(tplist, tuple);
1474                                         Py_DECREF(tuple);
1475                                 }
1476                         }
1477                         Py_DECREF(tplist);
1478                 }
1479                 else if (ter_flags)
1480                         Py_DECREF(ter_flags);
1481         }
1482         Py_INCREF(Py_True);
1483         return Py_True;
1484 }
1485
1486 eDVBDB::~eDVBDB()
1487 {
1488         instance=NULL;
1489 }
1490
1491 RESULT eDVBDB::removeService(const eServiceReference &ref)
1492 {
1493         if (ref.type == eServiceReference::idDVB)
1494         {
1495                 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
1496                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(service));
1497                 if (it != m_services.end())
1498                 {
1499                         m_services.erase(it);
1500                         return 0;
1501                 }
1502         }
1503         return -1;
1504 }
1505
1506 RESULT eDVBDB::removeServices(int dvb_namespace, int tsid, int onid, unsigned int orb_pos)
1507 {
1508         return removeServices(eDVBChannelID(eDVBNamespace(dvb_namespace), eTransportStreamID(tsid), eOriginalNetworkID(onid)), orb_pos);
1509 }
1510
1511 RESULT eDVBDB::removeServices(eDVBChannelID chid, unsigned int orbpos)
1512 {
1513         RESULT ret=-1;
1514         eDVBNamespace eNs;
1515         eTransportStreamID eTsid;
1516         eOriginalNetworkID eOnid;
1517         std::map<eDVBChannelID, channel>::iterator it(m_channels.begin());
1518         std::set<eDVBChannelID> removed_chids;
1519         while (it != m_channels.end())
1520         {
1521                 const eDVBChannelID &ch = it->first;
1522                 bool remove=true;
1523                 int system;
1524                 it->second.m_frontendParameters->getSystem(system);
1525                 if ( system == iDVBFrontend::feSatellite )
1526                 {
1527                         eDVBFrontendParametersSatellite sat;
1528                         it->second.m_frontendParameters->getDVBS(sat);
1529                         if ((unsigned int)sat.orbital_position != orbpos)
1530                                 remove=false;
1531                 }
1532                 if ( remove && chid.dvbnamespace != eNs ) // namespace given?
1533                 {
1534                         if ( system == iDVBFrontend::feCable && chid.dvbnamespace.get() == (int)0xFFFF0000 )
1535                                 ;
1536                         else if ( system == iDVBFrontend::feTerrestrial && chid.dvbnamespace.get() == (int)0xEEEE0000 )
1537                                 ;
1538                         else if ( chid.dvbnamespace != ch.dvbnamespace )
1539                                 remove=false;
1540                 }
1541                 else if ( system == iDVBFrontend::feCable || system == iDVBFrontend::feTerrestrial )
1542                         remove=false;
1543                 if ( remove && chid.original_network_id != eOnid && chid.original_network_id != ch.original_network_id )
1544                         remove=false;
1545                 if ( remove && chid.transport_stream_id != eTsid && chid.transport_stream_id != ch.transport_stream_id )
1546                         remove=false;
1547                 if ( remove )
1548                 {
1549                         eDebug("[eDVBDB] remove %08x %04x %04x",
1550                                 ch.dvbnamespace.get(),
1551                                 ch.original_network_id.get(),
1552                                 ch.transport_stream_id.get());
1553                         removed_chids.insert(it->first);
1554                         m_channels.erase(it++);
1555                 }
1556                 else
1557                         ++it;
1558         }
1559         if (!removed_chids.empty())
1560         {
1561                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator service(m_services.begin());
1562                 while(service != m_services.end())
1563                 {
1564                         eDVBChannelID chid;
1565                         service->first.getChannelID(chid);
1566                         std::set<eDVBChannelID>::iterator it(removed_chids.find(chid));
1567                         if (it != removed_chids.end())
1568                                 m_services.erase(service++);
1569                         else
1570                                 ++service;
1571                         ret=0;
1572                 }
1573         }
1574         return ret;
1575 }
1576
1577 RESULT eDVBDB::removeServices(iDVBFrontendParameters *feparm)
1578 {
1579         int ret = -1;
1580         std::set<eDVBChannelID> removed_chids;
1581         std::map<eDVBChannelID, channel>::iterator it(m_channels.begin());
1582         while (it != m_channels.end())
1583         {
1584                 int diff;
1585                 if (!feparm->calculateDifference(&(*it->second.m_frontendParameters), diff, false))
1586                 {
1587                         if (diff < 4000)
1588                         {
1589                                 removed_chids.insert(it->first);
1590                                 m_channels.erase(it++);
1591                         }
1592                         else
1593                                 ++it;
1594                 }
1595                 else
1596                         ++it;
1597         }
1598         if (!removed_chids.empty())
1599         {
1600                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator service(m_services.begin());
1601                 while(service != m_services.end())
1602                 {
1603                         eDVBChannelID chid;
1604                         service->first.getChannelID(chid);
1605                         std::set<eDVBChannelID>::iterator it(removed_chids.find(chid));
1606                         if (it != removed_chids.end())
1607                                 m_services.erase(service++);
1608                         else
1609                                 ++service;
1610                 }
1611                 ret = 0;
1612         }
1613         return ret;
1614 }
1615
1616 PyObject *eDVBDB::getFlag(const eServiceReference &ref)
1617 {
1618         if (ref.type == eServiceReference::idDVB)
1619         {
1620                 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
1621                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(service));
1622                 if (it != m_services.end())
1623                         return PyInt_FromLong(it->second->m_flags);
1624         }
1625         return PyInt_FromLong(0);
1626 }
1627
1628 RESULT eDVBDB::addFlag(const eServiceReference &ref, unsigned int flagmask)
1629 {
1630         if (ref.type == eServiceReference::idDVB)
1631         {
1632                 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
1633                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(service));
1634                 if (it != m_services.end())
1635                         it->second->m_flags |= flagmask;
1636                 return 0;
1637         }
1638         return -1;
1639 }
1640
1641 RESULT eDVBDB::removeFlag(const eServiceReference &ref, unsigned int flagmask)
1642 {
1643         if (ref.type == eServiceReference::idDVB)
1644         {
1645                 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
1646                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(service));
1647                 if (it != m_services.end())
1648                         it->second->m_flags &= ~flagmask;
1649                 return 0;
1650         }
1651         return -1;
1652 }
1653
1654 RESULT eDVBDB::removeFlags(unsigned int flagmask, int dvb_namespace, int tsid, int onid, unsigned int orb_pos)
1655 {
1656         return removeFlags(flagmask, eDVBChannelID(eDVBNamespace(dvb_namespace), eTransportStreamID(tsid), eOriginalNetworkID(onid)), orb_pos);
1657 }
1658
1659 RESULT eDVBDB::removeFlags(unsigned int flagmask, eDVBChannelID chid, unsigned int orbpos)
1660 {
1661         eDVBNamespace eNs;
1662         eTransportStreamID eTsid;
1663         eOriginalNetworkID eOnid;
1664         std::map<eDVBChannelID, channel>::iterator it(m_channels.begin());
1665         std::set<eDVBChannelID> removed_chids;
1666         while (it != m_channels.end())
1667         {
1668                 const eDVBChannelID &ch = it->first;
1669                 bool remove=true;
1670                 int system;
1671                 it->second.m_frontendParameters->getSystem(system);
1672                 if ( orbpos != 0xFFFFFFFF && system == iDVBFrontend::feSatellite )
1673                 {
1674                         eDVBFrontendParametersSatellite sat;
1675                         it->second.m_frontendParameters->getDVBS(sat);
1676                         if ((unsigned int)sat.orbital_position != orbpos)
1677                                 remove=false;
1678                 }
1679                 if ( remove && chid.dvbnamespace != eNs )
1680                 {
1681                         if (system == iDVBFrontend::feCable && chid.dvbnamespace.get() == (int)0xFFFF0000)
1682                                 ;
1683                         else if (system == iDVBFrontend::feTerrestrial && chid.dvbnamespace.get() == (int)0xEEEE0000)
1684                                 ;
1685                         else if ( chid.dvbnamespace != ch.dvbnamespace )
1686                                 remove=false;
1687                 }
1688                 if ( remove && chid.original_network_id != eOnid && chid.original_network_id != ch.original_network_id )
1689                         remove=false;
1690                 if ( remove && chid.transport_stream_id != eTsid && chid.transport_stream_id != ch.transport_stream_id )
1691                         remove=false;
1692                 if ( remove )
1693                         removed_chids.insert(it->first);
1694                 ++it;
1695         }
1696         if (!removed_chids.empty())
1697         {
1698                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator service(m_services.begin());
1699                 while(service != m_services.end())
1700                 {
1701                         eDVBChannelID chid;
1702                         service->first.getChannelID(chid);
1703                         std::set<eDVBChannelID>::iterator it(removed_chids.find(chid));
1704                         if (it != removed_chids.end())
1705                                 service->second->m_flags &= ~flagmask;
1706                         ++service;
1707                 }
1708         }
1709         return 0;
1710 }
1711
1712 RESULT eDVBDB::addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm)
1713 {
1714         channel ch;
1715         std::map<eDVBChannelID, channel>::iterator it = m_channels.find(id);
1716         ASSERT(feparm);
1717         ch.m_frontendParameters = feparm;
1718         if (it != m_channels.end())
1719                 it->second = ch;
1720         else
1721                 m_channels.insert(std::pair<eDVBChannelID, channel>(id, ch));
1722         return 0;
1723 }
1724
1725 RESULT eDVBDB::removeChannel(const eDVBChannelID &id)
1726 {
1727         m_channels.erase(id);
1728         return 0;
1729 }
1730
1731 RESULT eDVBDB::getChannelFrontendData(const eDVBChannelID &id, ePtr<iDVBFrontendParameters> &parm)
1732 {
1733         std::map<eDVBChannelID, channel>::iterator i = m_channels.find(id);
1734         if (i == m_channels.end())
1735         {
1736                 parm = 0;
1737                 return -ENOENT;
1738         }
1739         parm = i->second.m_frontendParameters;
1740         return 0;
1741 }
1742
1743 RESULT eDVBDB::addService(const eServiceReferenceDVB &serviceref, eDVBService *service)
1744 {
1745         std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(serviceref));
1746         if (it == m_services.end())
1747                 m_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(serviceref, service));
1748         return 0;
1749 }
1750
1751 RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr<eDVBService> &service)
1752 {
1753         std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator i;
1754         i = m_services.find(reference);
1755         if (i == m_services.end())
1756         {
1757                 service = 0;
1758                 return -ENOENT;
1759         }
1760         service = i->second;
1761         return 0;
1762 }
1763
1764 RESULT eDVBDB::flush()
1765 {
1766         saveServicelist();
1767         return 0;
1768 }
1769
1770 RESULT eDVBDB::getBouquet(const eServiceReference &ref, eBouquet* &bouquet)
1771 {
1772         std::string str = ref.path;
1773         if (str.empty())
1774         {
1775                 eDebug("[eDVBDB] getBouquet failed.. no path given!");
1776                 return -1;
1777         }
1778         size_t pos = str.find("FROM BOUQUET \"");
1779         if ( pos != std::string::npos )
1780         {
1781                 str.erase(0, pos+14);
1782                 pos = str.find('"');
1783                 if ( pos != std::string::npos )
1784                         str.erase(pos);
1785                 else
1786                         str.clear();
1787         }
1788         if (str.empty())
1789         {
1790                 eDebug("[eDVBDB] getBouquet failed.. couldn't parse bouquet name");
1791                 return -1;
1792         }
1793         std::map<std::string, eBouquet>::iterator i =
1794                 m_bouquets.find(str);
1795         if (i == m_bouquets.end())
1796         {
1797                 bouquet = 0;
1798                 return -ENOENT;
1799         }
1800         bouquet = &i->second;
1801         return 0;
1802 }
1803
1804 RESULT eDVBDB::startQuery(ePtr<iDVBChannelListQuery> &query, eDVBChannelQuery *q, const eServiceReference &source)
1805 {
1806         if ( source.path.find("FROM") != std::string::npos )
1807         {
1808                 if ( source.path.find("BOUQUET") != std::string::npos )
1809                         query = new eDVBDBBouquetQuery(this, source, q);
1810                 else if ( source.path.find("SATELLITES") != std::string::npos )
1811                         query = new eDVBDBSatellitesQuery(this, source, q);
1812                 else if ( source.path.find("PROVIDERS") != std::string::npos )
1813                         query = new eDVBDBProvidersQuery(this, source, q);
1814                 else
1815                         eFatal("[eDVBDB] invalid query %s", source.toString().c_str());
1816         }
1817         else
1818                 query = new eDVBDBQuery(this, source, q);
1819         return 0;
1820 }
1821
1822 eServiceReference eDVBDB::searchReference(int tsid, int onid, int sid)
1823 {
1824         eServiceID Sid(sid);
1825         eTransportStreamID Tsid(tsid);
1826         eOriginalNetworkID Onid(onid);
1827         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator sit(m_services.begin());
1828                 sit != m_services.end(); ++sit)
1829         {
1830                 if (sit->first.getTransportStreamID() == Tsid &&
1831                         sit->first.getOriginalNetworkID() == Onid &&
1832                         sit->first.getServiceID() == Sid)
1833                         return sit->first;
1834         }
1835         return eServiceReference();
1836 }
1837
1838 void eDVBDB::searchAllReferences(std::vector<eServiceReference> &result, int tsid, int onid, int sid)
1839 {
1840         eServiceID Sid(sid);
1841         eTransportStreamID Tsid(tsid);
1842         eOriginalNetworkID Onid(onid);
1843         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator sit(m_services.begin());
1844                 sit != m_services.end(); ++sit)
1845         {
1846                 if (sit->first.getTransportStreamID() == Tsid &&
1847                         sit->first.getOriginalNetworkID() == Onid &&
1848                         sit->first.getServiceID() == Sid)
1849                         result.push_back(sit->first);
1850         }
1851 }
1852
1853 DEFINE_REF(eDVBDBQueryBase);
1854
1855 eDVBDBQueryBase::eDVBDBQueryBase(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
1856         :m_db(db), m_query(query), m_source(source)
1857 {
1858 }
1859
1860 int eDVBDBQueryBase::compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b)
1861 {
1862         ePtr<eDVBService> a_service, b_service;
1863         int sortmode = m_query ? m_query->m_sort : eDVBChannelQuery::tName;
1864
1865         if ((sortmode == eDVBChannelQuery::tName) || (sortmode == eDVBChannelQuery::tProvider))
1866         {
1867                 if (a.name.empty() && m_db->getService(a, a_service))
1868                         return 1;
1869                 if (b.name.empty() && m_db->getService(b, b_service))
1870                         return 1;
1871         }
1872
1873         switch (sortmode)
1874         {
1875         case eDVBChannelQuery::tName:
1876                 if (a_service)
1877                 {
1878                         if (b_service)
1879                                 return a_service->m_service_name_sort < b_service->m_service_name_sort;
1880                         else
1881                         {
1882                                 std::string str = b.name;
1883                                 makeUpper(str);
1884                                 return a_service->m_service_name_sort < str;
1885                         }
1886                 }
1887                 else if (b_service)
1888                 {
1889                         std::string str = a.name;
1890                         makeUpper(str);
1891                         return str < b_service->m_service_name_sort;
1892                 }
1893                 else
1894                 {
1895                         std::string aa = a.name, bb = b.name;
1896                         makeUpper(aa);
1897                         makeUpper(bb);
1898                         return aa < bb;
1899                 }
1900         case eDVBChannelQuery::tProvider:
1901                 return a_service->m_provider_name < b_service->m_provider_name;
1902         case eDVBChannelQuery::tType:
1903                 return a.getServiceType() < b.getServiceType();
1904         case eDVBChannelQuery::tBouquet:
1905                 return 0;
1906         case eDVBChannelQuery::tSatellitePosition:
1907                 return (a.getDVBNamespace().get() >> 16) < (b.getDVBNamespace().get() >> 16);
1908         default:
1909                 return 1;
1910         }
1911         return 0;
1912 }
1913
1914 eDVBDBQuery::eDVBDBQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
1915         :eDVBDBQueryBase(db, source, query)
1916 {
1917         m_cursor = m_db->m_services.begin();
1918 }
1919
1920 RESULT eDVBDBQuery::getNextResult(eServiceReferenceDVB &ref)
1921 {
1922         while (m_cursor != m_db->m_services.end())
1923         {
1924                 ePtr<eDVBService> service = m_cursor->second;
1925                 if (service->isHidden())
1926                         ++m_cursor;
1927                 else
1928                 {
1929                         ref = m_cursor->first;
1930
1931                         int res = (!m_query) || service->checkFilter(ref, *m_query);
1932
1933                         ++m_cursor;
1934
1935                         if (res)
1936                                 return 0;
1937                 }
1938         }
1939
1940         ref.type = eServiceReference::idInvalid;
1941
1942         return 1;
1943 }
1944
1945 eDVBDBBouquetQuery::eDVBDBBouquetQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
1946         :eDVBDBQueryBase(db, source, query), m_cursor(db->m_bouquets[query->m_bouquet_name].m_services.begin())
1947 {
1948 }
1949
1950 RESULT eDVBDBBouquetQuery::getNextResult(eServiceReferenceDVB &ref)
1951 {
1952         eBouquet &bouquet = m_db->m_bouquets[m_query->m_bouquet_name];
1953         std::list<eServiceReference> &list = bouquet.m_services;
1954         while (m_cursor != list.end())
1955         {
1956                 ref = *((eServiceReferenceDVB*)&(*m_cursor));
1957
1958                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it =
1959                         m_db->m_services.find(ref);
1960
1961                 int res = (!m_query) || it == m_db->m_services.end() || !(it->second->isHidden() && it->second->checkFilter(ref, *m_query));
1962
1963                 ++m_cursor;
1964
1965                 if (res)
1966                         return 0;
1967         }
1968
1969         ref.type = eServiceReference::idInvalid;
1970
1971         return 1;
1972 }
1973
1974 eDVBDBListQuery::eDVBDBListQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
1975         :eDVBDBQueryBase(db, source, query), m_cursor(m_list.end())
1976 {
1977 }
1978
1979 RESULT eDVBDBListQuery::getNextResult(eServiceReferenceDVB &ref)
1980 {
1981         if (m_cursor != m_list.end())
1982         {
1983                 ref = *m_cursor++;
1984                 return 0;
1985         }
1986         ref.type = eServiceReference::idInvalid;
1987         return 1;
1988 }
1989
1990 int eDVBDBListQuery::compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b)
1991 {
1992         if ( m_query->m_sort == eDVBChannelQuery::tSatellitePosition )
1993         {
1994                 int x = (a.getDVBNamespace().get() >> 16);
1995                 int y = (b.getDVBNamespace().get() >> 16);
1996                 if ( x > 1800 )
1997                         x -= 3600;
1998                 if ( y > 1800 )
1999                         y -= 3600;
2000                 return x < y;
2001         }
2002         std::string aa = a.name, bb = b.name;
2003         makeUpper(aa);
2004         makeUpper(bb);
2005         return aa < bb;
2006 }
2007
2008 eDVBDBSatellitesQuery::eDVBDBSatellitesQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
2009         :eDVBDBListQuery(db, source, query)
2010 {
2011         std::set<unsigned int> found;
2012         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_db->m_services.begin());
2013                 it != m_db->m_services.end(); ++it)
2014         {
2015                 int res = !it->second->isHidden() && it->second->checkFilter(it->first, *query);
2016                 if (res)
2017                 {
2018                         unsigned int dvbnamespace = it->first.getDVBNamespace().get()&0xFFFF0000;
2019                         if (found.find(dvbnamespace) == found.end())
2020                         {
2021                                 found.insert(dvbnamespace);
2022                                 eServiceReferenceDVB ref;
2023                                 ref.setDVBNamespace(dvbnamespace);
2024                                 ref.flags=eServiceReference::flagDirectory;
2025                                 char buf[128];
2026                                 snprintf(buf, sizeof(buf), "(satellitePosition == %d) && ", dvbnamespace>>16);
2027
2028                                 ref.path=buf+source.path;
2029                                 unsigned int pos=ref.path.find("FROM");
2030                                 ref.path.erase(pos);
2031                                 ref.path+="ORDER BY name";
2032 //                              eDebug("[eDVBDB] ref.path now %s", ref.path.c_str());
2033                                 m_list.push_back(ref);
2034
2035                                 ref.path=buf+source.path;
2036                                 pos=ref.path.find("FROM");
2037                                 ref.path.erase(pos+5);
2038                                 ref.path+="PROVIDERS ORDER BY name";
2039 //                              eDebug("[eDVBDB] ref.path now %s", ref.path.c_str());
2040                                 m_list.push_back(ref);
2041
2042                                 snprintf(buf, sizeof(buf), "(satellitePosition == %d) && (flags == %d) && ", dvbnamespace>>16, eDVBService::dxNewFound);
2043                                 ref.path=buf+source.path;
2044                                 pos=ref.path.find("FROM");
2045                                 ref.path.erase(pos);
2046                                 ref.path+="ORDER BY name";
2047 //                              eDebug("[eDVBDB] ref.path now %s", ref.path.c_str());
2048                                 m_list.push_back(ref);
2049                         }
2050                 }
2051         }
2052         m_cursor=m_list.begin();
2053 }
2054
2055 eDVBDBProvidersQuery::eDVBDBProvidersQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
2056         :eDVBDBListQuery(db, source, query)
2057 {
2058         std::set<std::string> found;
2059         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_db->m_services.begin());
2060                 it != m_db->m_services.end(); ++it)
2061         {
2062                 int res = !it->second->isHidden() && it->second->checkFilter(it->first, *query);
2063                 if (res)
2064                 {
2065                         const char *provider_name = it->second->m_provider_name.length() ?
2066                                 it->second->m_provider_name.c_str() :
2067                                 "Unknown";
2068                         if (found.find(std::string(provider_name)) == found.end())
2069                         {
2070                                 found.insert(std::string(provider_name));
2071                                 eServiceReferenceDVB ref;
2072                                 char buf[64];
2073                                 ref.name=provider_name;
2074                                 snprintf(buf, sizeof(buf), "(provider == \"%s\") && ", provider_name);
2075                                 ref.path=buf+source.path;
2076                                 unsigned int pos = ref.path.find("FROM");
2077                                 ref.flags=eServiceReference::flagDirectory;
2078                                 ref.path.erase(pos);
2079                                 ref.path+="ORDER BY name";
2080 //                              eDebug("[eDVBDB] ref.path now %s", ref.path.c_str());
2081                                 m_list.push_back(ref);
2082                         }
2083                 }
2084         }
2085         m_cursor=m_list.begin();
2086 }
2087
2088 /* (<name|provider|type|bouquet|satpos|chid> <==|...> <"string"|int>)[||,&& (..)] */
2089
2090 static int decodeType(const std::string &type)
2091 {
2092         if (type == "name")
2093                 return eDVBChannelQuery::tName;
2094         else if (type == "provider")
2095                 return eDVBChannelQuery::tProvider;
2096         else if (type == "type")
2097                 return eDVBChannelQuery::tType;
2098         else if (type == "bouquet")
2099                 return eDVBChannelQuery::tBouquet;
2100         else if (type == "satellitePosition")
2101                 return eDVBChannelQuery::tSatellitePosition;
2102         else if (type == "channelID")
2103                 return eDVBChannelQuery::tChannelID;
2104         else if (type == "flags")
2105                 return eDVBChannelQuery::tFlags;
2106         else
2107                 return -1;
2108 }
2109
2110         /* never, NEVER write a parser in C++! */
2111 RESULT parseExpression(ePtr<eDVBChannelQuery> &res, std::list<std::string>::const_iterator begin, std::list<std::string>::const_iterator end)
2112 {
2113         std::list<std::string>::const_iterator end_of_exp;
2114
2115         if (begin == end)
2116                 return 0;
2117
2118         if (*begin == "(")
2119         {
2120                 end_of_exp = begin;
2121                 while (end_of_exp != end)
2122                         if (*end_of_exp == ")")
2123                                 break;
2124                         else
2125                                 ++end_of_exp;
2126
2127                 if (end_of_exp == end)
2128                 {
2129                         eDebug("[parseExpression] end of expression while searching for closing brace");
2130                         return -1;
2131                 }
2132
2133                 ++begin;
2134                 // begin..end_of_exp
2135                 int r = parseExpression(res, begin, end_of_exp);
2136                 if (r)
2137                         return r;
2138                 ++end_of_exp;
2139
2140                         /* we had only one sub expression */
2141                 if (end_of_exp == end)
2142                 {
2143 //                      eDebug("[parseExpression] only one sub expression");
2144                         return 0;
2145                 }
2146
2147                         /* otherwise we have an operator here.. */
2148
2149                 ePtr<eDVBChannelQuery> r2 = res;
2150                 res = new eDVBChannelQuery();
2151                 res->m_sort = 0;
2152                 res->m_p1 = r2;
2153                 res->m_inverse = 0;
2154                 r2 = 0;
2155
2156                 if (*end_of_exp == "||")
2157                         res->m_type = eDVBChannelQuery::tOR;
2158                 else if (*end_of_exp == "&&")
2159                         res->m_type = eDVBChannelQuery::tAND;
2160                 else
2161                 {
2162                         eDebug("[parseExpression] found operator %s, but only && and || are allowed!", end_of_exp->c_str());
2163                         res = 0;
2164                         return 1;
2165                 }
2166
2167                 ++end_of_exp;
2168
2169                 return parseExpression(res->m_p2, end_of_exp, end);
2170         }
2171
2172         // "begin" <op> "end"
2173         std::string type, op, val;
2174
2175         res = new eDVBChannelQuery();
2176         res->m_sort = 0;
2177
2178         int cnt = 0;
2179         while (begin != end)
2180         {
2181                 switch (cnt)
2182                 {
2183                 case 0:
2184                         type = *begin;
2185                         break;
2186                 case 1:
2187                         op = *begin;
2188                         break;
2189                 case 2:
2190                         val = *begin;
2191                         break;
2192                 case 3:
2193                         eDebug("[parseExpression] malformed query: got '%s', but expected only <type> <op> <val>", begin->c_str());
2194                         return 1;
2195                 }
2196                 ++begin;
2197                 ++cnt;
2198         }
2199
2200         if (cnt != 3)
2201         {
2202                 eDebug("[parseExpression] malformed query: missing stuff");
2203                 res = 0;
2204                 return 1;
2205         }
2206
2207         res->m_type = decodeType(type);
2208
2209         if (res->m_type == -1)
2210         {
2211                 eDebug("[parseExpression] malformed query: invalid type %s", type.c_str());
2212                 res = 0;
2213                 return 1;
2214         }
2215
2216         if (op == "==")
2217                 res->m_inverse = 0;
2218         else if (op == "!=")
2219                 res->m_inverse = 1;
2220         else
2221         {
2222                 eDebug("[parseExpression] invalid operator %s", op.c_str());
2223                 res = 0;
2224                 return 1;
2225         }
2226
2227         res->m_string = val;
2228
2229         if (res->m_type == eDVBChannelQuery::tChannelID)
2230         {
2231                 int ns, tsid, onid;
2232                 if (sscanf(val.c_str(), "%08x%04x%04x", &ns, &tsid, &onid) == 3)
2233                         res->m_channelid = eDVBChannelID(eDVBNamespace(ns), eTransportStreamID(tsid), eOriginalNetworkID(onid));
2234                 else
2235                         eDebug("[parseExpression] couldn't parse channelid !! format should be hex NNNNNNNNTTTTOOOO (namespace, tsid, onid)");
2236         }
2237         else
2238                 res->m_int = atoi(val.c_str());
2239
2240         return 0;
2241 }
2242
2243 RESULT eDVBChannelQuery::compile(ePtr<eDVBChannelQuery> &res, std::string query)
2244 {
2245         std::list<std::string> tokens;
2246
2247         std::string current_token;
2248         std::string bouquet_name;
2249
2250 //      eDebug("[eDVBChannelQuery] splitting %s....", query.c_str());
2251         unsigned int i = 0;
2252         const char *splitchars="()";
2253         int quotemode = 0, lastsplit = 0, lastalnum = 0;
2254         while (i <= query.size())
2255         {
2256                 int c = (i < query.size()) ? query[i] : ' ';
2257                 ++i;
2258
2259                 int issplit = !!strchr(splitchars, c);
2260                 int isaln = isalnum(c);
2261                 int iswhite = c == ' ';
2262                 int isquot = c == '\"';
2263
2264                 if (quotemode)
2265                 {
2266                         iswhite = issplit = 0;
2267                         isaln = lastalnum;
2268                 }
2269
2270                 if (issplit || iswhite || isquot || lastsplit || (lastalnum != isaln))
2271                 {
2272                         if (current_token.size())
2273                                 tokens.push_back(current_token);
2274                         current_token.clear();
2275                 }
2276
2277                 if (!(iswhite || isquot))
2278                         current_token += c;
2279
2280                 if (isquot)
2281                         quotemode = !quotemode;
2282                 lastsplit = issplit;
2283                 lastalnum = isaln;
2284         }
2285
2286 //      for (std::list<std::string>::const_iterator a(tokens.begin()); a != tokens.end(); ++a)
2287 //      {
2288 //              printf("%s\n", a->c_str());
2289 //      }
2290
2291         int sort = eDVBChannelQuery::tName;
2292                 /* check for "ORDER BY ..." */
2293
2294         std::list<std::string>::iterator it = tokens.begin();
2295         while (it != tokens.end())
2296         {
2297                 if (*it == "ORDER")
2298                 {
2299                         tokens.erase(it++);
2300                         if (it != tokens.end() && *it == "BY")
2301                         {
2302                                 tokens.erase(it++);
2303                                 sort = decodeType(*it);
2304                                 tokens.erase(it++);
2305                         } else
2306                                 sort = -1;
2307                 }
2308                 else if (*it == "FROM")
2309                 {
2310                         tokens.erase(it++);
2311                         if (it != tokens.end() && *it == "BOUQUET")
2312                         {
2313                                 tokens.erase(it++);
2314                                 bouquet_name = *it;
2315                                 tokens.erase(it++);
2316                         }
2317                         else if (it != tokens.end() && *it == "SATELLITES")
2318                                 tokens.erase(it++);
2319                         else if (it != tokens.end() && *it == "PROVIDERS")
2320                                 tokens.erase(it++);
2321                         else
2322                         {
2323                                 eDebug("[eDVBChannelQuery] FROM unknown %s", (*it).c_str());
2324                                 tokens.erase(it++);
2325                         }
2326                 }
2327                 else
2328                         ++it;
2329         }
2330
2331         if (sort == -1)
2332         {
2333                 eWarning("[eDVBChannelQuery] ORDER BY .. string invalid.");
2334                 res = 0;
2335                 return -1;
2336         }
2337
2338 //      eDebug("[eDVBChannelQuery] sort by %d", sort);
2339
2340                 /* now we recursivly parse that. */
2341         int r = parseExpression(res, tokens.begin(), tokens.end());
2342
2343                 /* we have an empty (but valid!) expression */
2344         if (!r && !res)
2345         {
2346                 res = new eDVBChannelQuery();
2347                 res->m_inverse = 0;
2348                 res->m_type = eDVBChannelQuery::tAny;
2349         }
2350
2351         if (res)
2352         {
2353                 res->m_sort = sort;
2354                 res->m_bouquet_name = bouquet_name;
2355         }
2356
2357 //      eDebug("[eDVBChannelQuery] return: %d", r);
2358         return r;
2359 }
2360
2361 DEFINE_REF(eDVBChannelQuery);