bbc2fbe649721ba8e8055d18160b3af6c36064fd
[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 /etc/tuxbox/satellites.xml!!");
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         tree.setFilename("/etc/tuxbox/cables.xml");
1225         tree.read();
1226         Element *root = tree.getRoot();
1227         if (!root)
1228         {
1229                 eDebug("[eDVBDB] couldn't open /etc/tuxbox/cables.xml!!");
1230                 Py_INCREF(Py_False);
1231                 return Py_False;
1232         }
1233         const Attribute *at;
1234         int tmp, *dest,
1235                 modulation, fec, freq, sr, inversion, system;
1236         std::string name;
1237         char *end_ptr;
1238         const ElementList &root_elements = root->getElementList();
1239         for (ElementConstIterator it(root_elements.begin()); it != root_elements.end(); ++it)
1240         {
1241 //              eDebug("[eDVBDB] element: %s", el->name().c_str());
1242                 const Element *el = *it;
1243                 const ElementList &cab_elements = el->getElementList();
1244                 const AttributeList &cab_attributes = el->getAttributeList();
1245                 ePyObject cab_name;
1246                 ePyObject cab_flags;
1247                 for (AttributeConstIterator it(cab_attributes.begin()); it != cab_attributes.end(); ++it)
1248                 {
1249 //                      eDebug("[eDVBDB]\tattr: %s", at->name().c_str());
1250                         at = *it;
1251                         name = at->name();
1252                         if (name == "name")
1253                                 cab_name = PyString_FromString(at->value().c_str());
1254                         else if (name == "flags")
1255                         {
1256                                 tmp = strtol(at->value().c_str(), &end_ptr, 10);
1257                                 if (!*end_ptr)
1258                                         cab_flags = PyInt_FromLong(tmp);
1259                         }
1260                 }
1261                 if (cab_name)
1262                 {
1263                         ePyObject tplist = PyList_New(0);
1264                         ePyObject tuple = PyTuple_New(2);
1265                         if (!cab_flags)
1266                                 cab_flags = PyInt_FromLong(0);
1267                         PyTuple_SET_ITEM(tuple, 0, cab_name);
1268                         PyTuple_SET_ITEM(tuple, 1, cab_flags);
1269                         PyList_Append(cab_list, tuple);
1270                         Py_DECREF(tuple);
1271                         PyDict_SetItem(tp_dict, cab_name, tplist);
1272                         for (ElementConstIterator it(cab_elements.begin()); it != cab_elements.end(); ++it)
1273                         {
1274 //                              eDebug("[eDVBDB]\telement: %s", (*it)->name().c_str());
1275                                 const AttributeList &tp_attributes = (*it)->getAttributeList();
1276                                 AttributeConstIterator end = tp_attributes.end();
1277                                 modulation = eDVBFrontendParametersCable::Modulation_QAM64;
1278                                 fec = eDVBFrontendParametersCable::FEC_Auto;
1279                                 system = eDVBFrontendParametersCable::System_DVB_C_ANNEX_A;
1280                                 inversion = eDVBFrontendParametersCable::Inversion_Unknown;
1281                                 freq = 0;
1282                                 sr = 0;
1283                                 for (AttributeConstIterator it(tp_attributes.begin()); it != end; ++it)
1284                                 {
1285 //                                      eDebug("[eDVBDB]\t\tattr: %s", at->name().c_str());
1286                                         at = *it;
1287                                         dest = 0;
1288                                         name = at->name();
1289                                         if (name == "modulation") dest = &modulation;
1290                                         else if (name == "frequency") dest = &freq;
1291                                         else if (name == "symbol_rate") dest = &sr;
1292                                         else if (name == "fec_inner") dest = &fec;
1293                                         else if (name == "inversion") dest = &inversion;
1294                                         else if (name == "system") dest = &system;
1295                                         else continue;
1296                                         if (dest)
1297                                         {
1298                                                 tmp = strtol(at->value().c_str(), &end_ptr, 10);
1299                                                 if (!*end_ptr)
1300                                                         *dest = tmp;
1301                                         }
1302                                 }
1303                                 if (freq && sr)
1304                                 {
1305                                         while (freq > 999999)
1306                                                 freq /= 10;
1307                                         tuple = PyTuple_New(7);
1308                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
1309                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(freq));
1310                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(sr));
1311                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(modulation));
1312                                         PyTuple_SET_ITEM(tuple, 4, PyInt_FromLong(fec));
1313                                         PyTuple_SET_ITEM(tuple, 5, PyInt_FromLong(inversion));
1314                                         PyTuple_SET_ITEM(tuple, 6, PyInt_FromLong(system));
1315                                         PyList_Append(tplist, tuple);
1316                                         Py_DECREF(tuple);
1317                                 }
1318                         }
1319                         Py_DECREF(tplist);
1320                 }
1321                 else if (cab_flags)
1322                         Py_DECREF(cab_flags);
1323         }
1324         Py_INCREF(Py_True);
1325         return Py_True;
1326 }
1327
1328 PyObject *eDVBDB::readTerrestrials(ePyObject ter_list, ePyObject tp_dict)
1329 {
1330         if (!PyDict_Check(tp_dict)) {
1331                 PyErr_SetString(PyExc_StandardError,
1332                         "type error");
1333                         eDebug("[eDVBDB] readTerrestrials arg 1 is not a python dict");
1334                 return NULL;
1335         }
1336         else if (!PyList_Check(ter_list))
1337         {
1338                 PyErr_SetString(PyExc_StandardError,
1339                         "type error");
1340                         eDebug("[eDVBDB] readTerrestrials arg 0 is not a python list");
1341                 return NULL;
1342         }
1343         XMLTree tree;
1344         tree.setFilename("/etc/tuxbox/terrestrial.xml");
1345         tree.read();
1346         Element *root = tree.getRoot();
1347         if (!root)
1348         {
1349                 eDebug("[eDVBDB] couldn't open /etc/tuxbox/terrestrial.xml!!");
1350                 Py_INCREF(Py_False);
1351                 return Py_False;
1352         }
1353         const Attribute *at;
1354         std::string name;
1355         int tmp, *dest,
1356                 freq, bw, constellation, crh, crl, guard, transm, hierarchy, inv, system, plpid;
1357         char *end_ptr;
1358         const ElementList &root_elements = root->getElementList();
1359         for (ElementConstIterator it(root_elements.begin()); it != root_elements.end(); ++it)
1360         {
1361 //              eDebug("[eDVBDB] element: %s", el->name().c_str());
1362                 const Element *el = *it;
1363                 const ElementList &ter_elements = el->getElementList();
1364                 const AttributeList &ter_attributes = el->getAttributeList();
1365                 ePyObject ter_name;
1366                 ePyObject ter_flags;
1367                 for (AttributeConstIterator it(ter_attributes.begin()); it != ter_attributes.end(); ++it)
1368                 {
1369 //                      eDebug("[eDVBDB]\tattr: %s", at->name().c_str());
1370                         at = *it;
1371                         name = at->name();
1372                         if (name == "name")
1373                                 ter_name = PyString_FromString(at->value().c_str());
1374                         else if (name == "flags")
1375                         {
1376                                 tmp = strtol(at->value().c_str(), &end_ptr, 10);
1377                                 if (!*end_ptr)
1378                                         ter_flags = PyInt_FromLong(tmp);
1379                         }
1380                 }
1381                 if (ter_name)
1382                 {
1383                         ePyObject tplist = PyList_New(0);
1384                         ePyObject tuple = PyTuple_New(2);
1385                         if (!ter_flags)
1386                                 ter_flags = PyInt_FromLong(0);
1387                         PyTuple_SET_ITEM(tuple, 0, ter_name);
1388                         PyTuple_SET_ITEM(tuple, 1, ter_flags);
1389                         PyList_Append(ter_list, tuple);
1390                         Py_DECREF(tuple);
1391                         PyDict_SetItem(tp_dict, ter_name, tplist);
1392                         for (ElementConstIterator it(ter_elements.begin()); it != ter_elements.end(); ++it)
1393                         {
1394 //                              eDebug("[eDVBDB]\telement: %s", (*it)->name().c_str());
1395                                 const AttributeList &tp_attributes = (*it)->getAttributeList();
1396                                 AttributeConstIterator end = tp_attributes.end();
1397                                 freq = 0;
1398                                 bw = eDVBFrontendParametersTerrestrial::Bandwidth_Auto;
1399                                 constellation = eDVBFrontendParametersTerrestrial::Modulation_Auto;
1400                                 crh = eDVBFrontendParametersTerrestrial::FEC_Auto;
1401                                 crl = eDVBFrontendParametersTerrestrial::FEC_Auto;
1402                                 guard = eDVBFrontendParametersTerrestrial::GuardInterval_Auto;
1403                                 transm = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto;
1404                                 hierarchy = eDVBFrontendParametersTerrestrial::Hierarchy_Auto;
1405                                 inv = eDVBFrontendParametersTerrestrial::Inversion_Unknown;
1406                                 system = eDVBFrontendParametersTerrestrial::System_DVB_T_T2;
1407                                 plpid = 0;
1408                                 for (AttributeConstIterator it(tp_attributes.begin()); it != end; ++it)
1409                                 {
1410 //                                      eDebug("[eDVBDB]\t\tattr: %s", at->name().c_str());
1411                                         at = *it;
1412                                         dest = 0;
1413                                         name = at->name();
1414                                         if (name == "centre_frequency") dest = &freq;
1415                                         else if (name == "bandwidth") dest = &bw;
1416                                         else if (name == "constellation") dest = &constellation;
1417                                         else if (name == "code_rate_hp") dest = &crh;
1418                                         else if (name == "code_rate_lp") dest = &crl;
1419                                         else if (name == "guard_interval") dest = &guard;
1420                                         else if (name == "transmission_mode") dest = &transm;
1421                                         else if (name == "hierarchy_information") dest = &hierarchy;
1422                                         else if (name == "inversion") dest = &inv;
1423                                         else if (name == "system") dest = &system;
1424                                         else if (name == "plp_id") dest = &plpid;
1425                                         else continue;
1426                                         if (dest)
1427                                         {
1428                                                 tmp = strtol(at->value().c_str(), &end_ptr, 10);
1429                                                 if (!*end_ptr)
1430                                                         *dest = tmp;
1431                                         }
1432                                 }
1433                                 if (freq)
1434                                 {
1435                                         switch (bw)
1436                                         {
1437                                         case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz: bw = 8000000; break;
1438                                         case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz: bw = 7000000; break;
1439                                         case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz: bw = 6000000; break;
1440                                         default:
1441                                         case eDVBFrontendParametersTerrestrial::Bandwidth_Auto: bw = 0; break;
1442                                         case eDVBFrontendParametersTerrestrial::Bandwidth_5MHz: bw = 5000000; break;
1443                                         case eDVBFrontendParametersTerrestrial::Bandwidth_1_712MHz: bw = 1712000; break;
1444                                         case eDVBFrontendParametersTerrestrial::Bandwidth_10MHz: bw = 10000000; break;
1445                                         }
1446                                         if (crh > eDVBFrontendParametersTerrestrial::FEC_8_9)
1447                                                 crh = eDVBFrontendParametersTerrestrial::FEC_Auto;
1448                                         if (crl > eDVBFrontendParametersTerrestrial::FEC_8_9)
1449                                                 crl = eDVBFrontendParametersTerrestrial::FEC_Auto;
1450                                         tuple = PyTuple_New(12);
1451                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(2));
1452                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(freq));
1453                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(bw));
1454                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(constellation));
1455                                         PyTuple_SET_ITEM(tuple, 4, PyInt_FromLong(crh));
1456                                         PyTuple_SET_ITEM(tuple, 5, PyInt_FromLong(crl));
1457                                         PyTuple_SET_ITEM(tuple, 6, PyInt_FromLong(guard));
1458                                         PyTuple_SET_ITEM(tuple, 7, PyInt_FromLong(transm));
1459                                         PyTuple_SET_ITEM(tuple, 8, PyInt_FromLong(hierarchy));
1460                                         PyTuple_SET_ITEM(tuple, 9, PyInt_FromLong(inv));
1461                                         PyTuple_SET_ITEM(tuple, 10, PyInt_FromLong(system));
1462                                         PyTuple_SET_ITEM(tuple, 11, PyInt_FromLong(plpid));
1463                                         PyList_Append(tplist, tuple);
1464                                         Py_DECREF(tuple);
1465                                 }
1466                         }
1467                         Py_DECREF(tplist);
1468                 }
1469                 else if (ter_flags)
1470                         Py_DECREF(ter_flags);
1471         }
1472         Py_INCREF(Py_True);
1473         return Py_True;
1474 }
1475
1476 eDVBDB::~eDVBDB()
1477 {
1478         instance=NULL;
1479 }
1480
1481 RESULT eDVBDB::removeService(const eServiceReference &ref)
1482 {
1483         if (ref.type == eServiceReference::idDVB)
1484         {
1485                 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
1486                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(service));
1487                 if (it != m_services.end())
1488                 {
1489                         m_services.erase(it);
1490                         return 0;
1491                 }
1492         }
1493         return -1;
1494 }
1495
1496 RESULT eDVBDB::removeServices(int dvb_namespace, int tsid, int onid, unsigned int orb_pos)
1497 {
1498         return removeServices(eDVBChannelID(eDVBNamespace(dvb_namespace), eTransportStreamID(tsid), eOriginalNetworkID(onid)), orb_pos);
1499 }
1500
1501 RESULT eDVBDB::removeServices(eDVBChannelID chid, unsigned int orbpos)
1502 {
1503         RESULT ret=-1;
1504         eDVBNamespace eNs;
1505         eTransportStreamID eTsid;
1506         eOriginalNetworkID eOnid;
1507         std::map<eDVBChannelID, channel>::iterator it(m_channels.begin());
1508         std::set<eDVBChannelID> removed_chids;
1509         while (it != m_channels.end())
1510         {
1511                 const eDVBChannelID &ch = it->first;
1512                 bool remove=true;
1513                 int system;
1514                 it->second.m_frontendParameters->getSystem(system);
1515                 if ( system == iDVBFrontend::feSatellite )
1516                 {
1517                         eDVBFrontendParametersSatellite sat;
1518                         it->second.m_frontendParameters->getDVBS(sat);
1519                         if ((unsigned int)sat.orbital_position != orbpos)
1520                                 remove=false;
1521                 }
1522                 if ( remove && chid.dvbnamespace != eNs ) // namespace given?
1523                 {
1524                         if ( system == iDVBFrontend::feCable && chid.dvbnamespace.get() == (int)0xFFFF0000 )
1525                                 ;
1526                         else if ( system == iDVBFrontend::feTerrestrial && chid.dvbnamespace.get() == (int)0xEEEE0000 )
1527                                 ;
1528                         else if ( chid.dvbnamespace != ch.dvbnamespace )
1529                                 remove=false;
1530                 }
1531                 else if ( system == iDVBFrontend::feCable || system == iDVBFrontend::feTerrestrial )
1532                         remove=false;
1533                 if ( remove && chid.original_network_id != eOnid && chid.original_network_id != ch.original_network_id )
1534                         remove=false;
1535                 if ( remove && chid.transport_stream_id != eTsid && chid.transport_stream_id != ch.transport_stream_id )
1536                         remove=false;
1537                 if ( remove )
1538                 {
1539                         eDebug("[eDVBDB] remove %08x %04x %04x",
1540                                 ch.dvbnamespace.get(),
1541                                 ch.original_network_id.get(),
1542                                 ch.transport_stream_id.get());
1543                         removed_chids.insert(it->first);
1544                         m_channels.erase(it++);
1545                 }
1546                 else
1547                         ++it;
1548         }
1549         if (!removed_chids.empty())
1550         {
1551                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator service(m_services.begin());
1552                 while(service != m_services.end())
1553                 {
1554                         eDVBChannelID chid;
1555                         service->first.getChannelID(chid);
1556                         std::set<eDVBChannelID>::iterator it(removed_chids.find(chid));
1557                         if (it != removed_chids.end())
1558                                 m_services.erase(service++);
1559                         else
1560                                 ++service;
1561                         ret=0;
1562                 }
1563         }
1564         return ret;
1565 }
1566
1567 RESULT eDVBDB::removeServices(iDVBFrontendParameters *feparm)
1568 {
1569         int ret = -1;
1570         std::set<eDVBChannelID> removed_chids;
1571         std::map<eDVBChannelID, channel>::iterator it(m_channels.begin());
1572         while (it != m_channels.end())
1573         {
1574                 int diff;
1575                 if (!feparm->calculateDifference(&(*it->second.m_frontendParameters), diff, false))
1576                 {
1577                         if (diff < 4000)
1578                         {
1579                                 removed_chids.insert(it->first);
1580                                 m_channels.erase(it++);
1581                         }
1582                         else
1583                                 ++it;
1584                 }
1585                 else
1586                         ++it;
1587         }
1588         if (!removed_chids.empty())
1589         {
1590                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator service(m_services.begin());
1591                 while(service != m_services.end())
1592                 {
1593                         eDVBChannelID chid;
1594                         service->first.getChannelID(chid);
1595                         std::set<eDVBChannelID>::iterator it(removed_chids.find(chid));
1596                         if (it != removed_chids.end())
1597                                 m_services.erase(service++);
1598                         else
1599                                 ++service;
1600                 }
1601                 ret = 0;
1602         }
1603         return ret;
1604 }
1605
1606 PyObject *eDVBDB::getFlag(const eServiceReference &ref)
1607 {
1608         if (ref.type == eServiceReference::idDVB)
1609         {
1610                 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
1611                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(service));
1612                 if (it != m_services.end())
1613                         return PyInt_FromLong(it->second->m_flags);
1614         }
1615         return PyInt_FromLong(0);
1616 }
1617
1618 RESULT eDVBDB::addFlag(const eServiceReference &ref, unsigned int flagmask)
1619 {
1620         if (ref.type == eServiceReference::idDVB)
1621         {
1622                 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
1623                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(service));
1624                 if (it != m_services.end())
1625                         it->second->m_flags |= flagmask;
1626                 return 0;
1627         }
1628         return -1;
1629 }
1630
1631 RESULT eDVBDB::removeFlag(const eServiceReference &ref, unsigned int flagmask)
1632 {
1633         if (ref.type == eServiceReference::idDVB)
1634         {
1635                 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
1636                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(service));
1637                 if (it != m_services.end())
1638                         it->second->m_flags &= ~flagmask;
1639                 return 0;
1640         }
1641         return -1;
1642 }
1643
1644 RESULT eDVBDB::removeFlags(unsigned int flagmask, int dvb_namespace, int tsid, int onid, unsigned int orb_pos)
1645 {
1646         return removeFlags(flagmask, eDVBChannelID(eDVBNamespace(dvb_namespace), eTransportStreamID(tsid), eOriginalNetworkID(onid)), orb_pos);
1647 }
1648
1649 RESULT eDVBDB::removeFlags(unsigned int flagmask, eDVBChannelID chid, unsigned int orbpos)
1650 {
1651         eDVBNamespace eNs;
1652         eTransportStreamID eTsid;
1653         eOriginalNetworkID eOnid;
1654         std::map<eDVBChannelID, channel>::iterator it(m_channels.begin());
1655         std::set<eDVBChannelID> removed_chids;
1656         while (it != m_channels.end())
1657         {
1658                 const eDVBChannelID &ch = it->first;
1659                 bool remove=true;
1660                 int system;
1661                 it->second.m_frontendParameters->getSystem(system);
1662                 if ( orbpos != 0xFFFFFFFF && system == iDVBFrontend::feSatellite )
1663                 {
1664                         eDVBFrontendParametersSatellite sat;
1665                         it->second.m_frontendParameters->getDVBS(sat);
1666                         if ((unsigned int)sat.orbital_position != orbpos)
1667                                 remove=false;
1668                 }
1669                 if ( remove && chid.dvbnamespace != eNs )
1670                 {
1671                         if (system == iDVBFrontend::feCable && chid.dvbnamespace.get() == (int)0xFFFF0000)
1672                                 ;
1673                         else if (system == iDVBFrontend::feTerrestrial && chid.dvbnamespace.get() == (int)0xEEEE0000)
1674                                 ;
1675                         else if ( chid.dvbnamespace != ch.dvbnamespace )
1676                                 remove=false;
1677                 }
1678                 if ( remove && chid.original_network_id != eOnid && chid.original_network_id != ch.original_network_id )
1679                         remove=false;
1680                 if ( remove && chid.transport_stream_id != eTsid && chid.transport_stream_id != ch.transport_stream_id )
1681                         remove=false;
1682                 if ( remove )
1683                         removed_chids.insert(it->first);
1684                 ++it;
1685         }
1686         if (!removed_chids.empty())
1687         {
1688                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator service(m_services.begin());
1689                 while(service != m_services.end())
1690                 {
1691                         eDVBChannelID chid;
1692                         service->first.getChannelID(chid);
1693                         std::set<eDVBChannelID>::iterator it(removed_chids.find(chid));
1694                         if (it != removed_chids.end())
1695                                 service->second->m_flags &= ~flagmask;
1696                         ++service;
1697                 }
1698         }
1699         return 0;
1700 }
1701
1702 RESULT eDVBDB::addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm)
1703 {
1704         channel ch;
1705         std::map<eDVBChannelID, channel>::iterator it = m_channels.find(id);
1706         ASSERT(feparm);
1707         ch.m_frontendParameters = feparm;
1708         if (it != m_channels.end())
1709                 it->second = ch;
1710         else
1711                 m_channels.insert(std::pair<eDVBChannelID, channel>(id, ch));
1712         return 0;
1713 }
1714
1715 RESULT eDVBDB::removeChannel(const eDVBChannelID &id)
1716 {
1717         m_channels.erase(id);
1718         return 0;
1719 }
1720
1721 RESULT eDVBDB::getChannelFrontendData(const eDVBChannelID &id, ePtr<iDVBFrontendParameters> &parm)
1722 {
1723         std::map<eDVBChannelID, channel>::iterator i = m_channels.find(id);
1724         if (i == m_channels.end())
1725         {
1726                 parm = 0;
1727                 return -ENOENT;
1728         }
1729         parm = i->second.m_frontendParameters;
1730         return 0;
1731 }
1732
1733 RESULT eDVBDB::addService(const eServiceReferenceDVB &serviceref, eDVBService *service)
1734 {
1735         std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(serviceref));
1736         if (it == m_services.end())
1737                 m_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(serviceref, service));
1738         return 0;
1739 }
1740
1741 RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr<eDVBService> &service)
1742 {
1743         std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator i;
1744         i = m_services.find(reference);
1745         if (i == m_services.end())
1746         {
1747                 service = 0;
1748                 return -ENOENT;
1749         }
1750         service = i->second;
1751         return 0;
1752 }
1753
1754 RESULT eDVBDB::flush()
1755 {
1756         saveServicelist();
1757         return 0;
1758 }
1759
1760 RESULT eDVBDB::getBouquet(const eServiceReference &ref, eBouquet* &bouquet)
1761 {
1762         std::string str = ref.path;
1763         if (str.empty())
1764         {
1765                 eDebug("[eDVBDB] getBouquet failed.. no path given!");
1766                 return -1;
1767         }
1768         size_t pos = str.find("FROM BOUQUET \"");
1769         if ( pos != std::string::npos )
1770         {
1771                 str.erase(0, pos+14);
1772                 pos = str.find('"');
1773                 if ( pos != std::string::npos )
1774                         str.erase(pos);
1775                 else
1776                         str.clear();
1777         }
1778         if (str.empty())
1779         {
1780                 eDebug("[eDVBDB] getBouquet failed.. couldn't parse bouquet name");
1781                 return -1;
1782         }
1783         std::map<std::string, eBouquet>::iterator i =
1784                 m_bouquets.find(str);
1785         if (i == m_bouquets.end())
1786         {
1787                 bouquet = 0;
1788                 return -ENOENT;
1789         }
1790         bouquet = &i->second;
1791         return 0;
1792 }
1793
1794 RESULT eDVBDB::startQuery(ePtr<iDVBChannelListQuery> &query, eDVBChannelQuery *q, const eServiceReference &source)
1795 {
1796         if ( source.path.find("FROM") != std::string::npos )
1797         {
1798                 if ( source.path.find("BOUQUET") != std::string::npos )
1799                         query = new eDVBDBBouquetQuery(this, source, q);
1800                 else if ( source.path.find("SATELLITES") != std::string::npos )
1801                         query = new eDVBDBSatellitesQuery(this, source, q);
1802                 else if ( source.path.find("PROVIDERS") != std::string::npos )
1803                         query = new eDVBDBProvidersQuery(this, source, q);
1804                 else
1805                         eFatal("[eDVBDB] invalid query %s", source.toString().c_str());
1806         }
1807         else
1808                 query = new eDVBDBQuery(this, source, q);
1809         return 0;
1810 }
1811
1812 eServiceReference eDVBDB::searchReference(int tsid, int onid, int sid)
1813 {
1814         eServiceID Sid(sid);
1815         eTransportStreamID Tsid(tsid);
1816         eOriginalNetworkID Onid(onid);
1817         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator sit(m_services.begin());
1818                 sit != m_services.end(); ++sit)
1819         {
1820                 if (sit->first.getTransportStreamID() == Tsid &&
1821                         sit->first.getOriginalNetworkID() == Onid &&
1822                         sit->first.getServiceID() == Sid)
1823                         return sit->first;
1824         }
1825         return eServiceReference();
1826 }
1827
1828 void eDVBDB::searchAllReferences(std::vector<eServiceReference> &result, int tsid, int onid, int sid)
1829 {
1830         eServiceID Sid(sid);
1831         eTransportStreamID Tsid(tsid);
1832         eOriginalNetworkID Onid(onid);
1833         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator sit(m_services.begin());
1834                 sit != m_services.end(); ++sit)
1835         {
1836                 if (sit->first.getTransportStreamID() == Tsid &&
1837                         sit->first.getOriginalNetworkID() == Onid &&
1838                         sit->first.getServiceID() == Sid)
1839                         result.push_back(sit->first);
1840         }
1841 }
1842
1843 DEFINE_REF(eDVBDBQueryBase);
1844
1845 eDVBDBQueryBase::eDVBDBQueryBase(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
1846         :m_db(db), m_query(query), m_source(source)
1847 {
1848 }
1849
1850 int eDVBDBQueryBase::compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b)
1851 {
1852         ePtr<eDVBService> a_service, b_service;
1853         int sortmode = m_query ? m_query->m_sort : eDVBChannelQuery::tName;
1854
1855         if ((sortmode == eDVBChannelQuery::tName) || (sortmode == eDVBChannelQuery::tProvider))
1856         {
1857                 if (a.name.empty() && m_db->getService(a, a_service))
1858                         return 1;
1859                 if (b.name.empty() && m_db->getService(b, b_service))
1860                         return 1;
1861         }
1862
1863         switch (sortmode)
1864         {
1865         case eDVBChannelQuery::tName:
1866                 if (a_service)
1867                 {
1868                         if (b_service)
1869                                 return a_service->m_service_name_sort < b_service->m_service_name_sort;
1870                         else
1871                         {
1872                                 std::string str = b.name;
1873                                 makeUpper(str);
1874                                 return a_service->m_service_name_sort < str;
1875                         }
1876                 }
1877                 else if (b_service)
1878                 {
1879                         std::string str = a.name;
1880                         makeUpper(str);
1881                         return str < b_service->m_service_name_sort;
1882                 }
1883                 else
1884                 {
1885                         std::string aa = a.name, bb = b.name;
1886                         makeUpper(aa);
1887                         makeUpper(bb);
1888                         return aa < bb;
1889                 }
1890         case eDVBChannelQuery::tProvider:
1891                 return a_service->m_provider_name < b_service->m_provider_name;
1892         case eDVBChannelQuery::tType:
1893                 return a.getServiceType() < b.getServiceType();
1894         case eDVBChannelQuery::tBouquet:
1895                 return 0;
1896         case eDVBChannelQuery::tSatellitePosition:
1897                 return (a.getDVBNamespace().get() >> 16) < (b.getDVBNamespace().get() >> 16);
1898         default:
1899                 return 1;
1900         }
1901         return 0;
1902 }
1903
1904 eDVBDBQuery::eDVBDBQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
1905         :eDVBDBQueryBase(db, source, query)
1906 {
1907         m_cursor = m_db->m_services.begin();
1908 }
1909
1910 RESULT eDVBDBQuery::getNextResult(eServiceReferenceDVB &ref)
1911 {
1912         while (m_cursor != m_db->m_services.end())
1913         {
1914                 ePtr<eDVBService> service = m_cursor->second;
1915                 if (service->isHidden())
1916                         ++m_cursor;
1917                 else
1918                 {
1919                         ref = m_cursor->first;
1920
1921                         int res = (!m_query) || service->checkFilter(ref, *m_query);
1922
1923                         ++m_cursor;
1924
1925                         if (res)
1926                                 return 0;
1927                 }
1928         }
1929
1930         ref.type = eServiceReference::idInvalid;
1931
1932         return 1;
1933 }
1934
1935 eDVBDBBouquetQuery::eDVBDBBouquetQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
1936         :eDVBDBQueryBase(db, source, query), m_cursor(db->m_bouquets[query->m_bouquet_name].m_services.begin())
1937 {
1938 }
1939
1940 RESULT eDVBDBBouquetQuery::getNextResult(eServiceReferenceDVB &ref)
1941 {
1942         eBouquet &bouquet = m_db->m_bouquets[m_query->m_bouquet_name];
1943         std::list<eServiceReference> &list = bouquet.m_services;
1944         while (m_cursor != list.end())
1945         {
1946                 ref = *((eServiceReferenceDVB*)&(*m_cursor));
1947
1948                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it =
1949                         m_db->m_services.find(ref);
1950
1951                 int res = (!m_query) || it == m_db->m_services.end() || !(it->second->isHidden() && it->second->checkFilter(ref, *m_query));
1952
1953                 ++m_cursor;
1954
1955                 if (res)
1956                         return 0;
1957         }
1958
1959         ref.type = eServiceReference::idInvalid;
1960
1961         return 1;
1962 }
1963
1964 eDVBDBListQuery::eDVBDBListQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
1965         :eDVBDBQueryBase(db, source, query), m_cursor(m_list.end())
1966 {
1967 }
1968
1969 RESULT eDVBDBListQuery::getNextResult(eServiceReferenceDVB &ref)
1970 {
1971         if (m_cursor != m_list.end())
1972         {
1973                 ref = *m_cursor++;
1974                 return 0;
1975         }
1976         ref.type = eServiceReference::idInvalid;
1977         return 1;
1978 }
1979
1980 int eDVBDBListQuery::compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b)
1981 {
1982         if ( m_query->m_sort == eDVBChannelQuery::tSatellitePosition )
1983         {
1984                 int x = (a.getDVBNamespace().get() >> 16);
1985                 int y = (b.getDVBNamespace().get() >> 16);
1986                 if ( x > 1800 )
1987                         x -= 3600;
1988                 if ( y > 1800 )
1989                         y -= 3600;
1990                 return x < y;
1991         }
1992         std::string aa = a.name, bb = b.name;
1993         makeUpper(aa);
1994         makeUpper(bb);
1995         return aa < bb;
1996 }
1997
1998 eDVBDBSatellitesQuery::eDVBDBSatellitesQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
1999         :eDVBDBListQuery(db, source, query)
2000 {
2001         std::set<unsigned int> found;
2002         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_db->m_services.begin());
2003                 it != m_db->m_services.end(); ++it)
2004         {
2005                 int res = !it->second->isHidden() && it->second->checkFilter(it->first, *query);
2006                 if (res)
2007                 {
2008                         unsigned int dvbnamespace = it->first.getDVBNamespace().get()&0xFFFF0000;
2009                         if (found.find(dvbnamespace) == found.end())
2010                         {
2011                                 found.insert(dvbnamespace);
2012                                 eServiceReferenceDVB ref;
2013                                 ref.setDVBNamespace(dvbnamespace);
2014                                 ref.flags=eServiceReference::flagDirectory;
2015                                 char buf[128];
2016                                 snprintf(buf, sizeof(buf), "(satellitePosition == %d) && ", dvbnamespace>>16);
2017
2018                                 ref.path=buf+source.path;
2019                                 unsigned int pos=ref.path.find("FROM");
2020                                 ref.path.erase(pos);
2021                                 ref.path+="ORDER BY name";
2022 //                              eDebug("[eDVBDB] ref.path now %s", ref.path.c_str());
2023                                 m_list.push_back(ref);
2024
2025                                 ref.path=buf+source.path;
2026                                 pos=ref.path.find("FROM");
2027                                 ref.path.erase(pos+5);
2028                                 ref.path+="PROVIDERS ORDER BY name";
2029 //                              eDebug("[eDVBDB] ref.path now %s", ref.path.c_str());
2030                                 m_list.push_back(ref);
2031
2032                                 snprintf(buf, sizeof(buf), "(satellitePosition == %d) && (flags == %d) && ", dvbnamespace>>16, eDVBService::dxNewFound);
2033                                 ref.path=buf+source.path;
2034                                 pos=ref.path.find("FROM");
2035                                 ref.path.erase(pos);
2036                                 ref.path+="ORDER BY name";
2037 //                              eDebug("[eDVBDB] ref.path now %s", ref.path.c_str());
2038                                 m_list.push_back(ref);
2039                         }
2040                 }
2041         }
2042         m_cursor=m_list.begin();
2043 }
2044
2045 eDVBDBProvidersQuery::eDVBDBProvidersQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
2046         :eDVBDBListQuery(db, source, query)
2047 {
2048         std::set<std::string> found;
2049         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_db->m_services.begin());
2050                 it != m_db->m_services.end(); ++it)
2051         {
2052                 int res = !it->second->isHidden() && it->second->checkFilter(it->first, *query);
2053                 if (res)
2054                 {
2055                         const char *provider_name = it->second->m_provider_name.length() ?
2056                                 it->second->m_provider_name.c_str() :
2057                                 "Unknown";
2058                         if (found.find(std::string(provider_name)) == found.end())
2059                         {
2060                                 found.insert(std::string(provider_name));
2061                                 eServiceReferenceDVB ref;
2062                                 char buf[64];
2063                                 ref.name=provider_name;
2064                                 snprintf(buf, sizeof(buf), "(provider == \"%s\") && ", provider_name);
2065                                 ref.path=buf+source.path;
2066                                 unsigned int pos = ref.path.find("FROM");
2067                                 ref.flags=eServiceReference::flagDirectory;
2068                                 ref.path.erase(pos);
2069                                 ref.path+="ORDER BY name";
2070 //                              eDebug("[eDVBDB] ref.path now %s", ref.path.c_str());
2071                                 m_list.push_back(ref);
2072                         }
2073                 }
2074         }
2075         m_cursor=m_list.begin();
2076 }
2077
2078 /* (<name|provider|type|bouquet|satpos|chid> <==|...> <"string"|int>)[||,&& (..)] */
2079
2080 static int decodeType(const std::string &type)
2081 {
2082         if (type == "name")
2083                 return eDVBChannelQuery::tName;
2084         else if (type == "provider")
2085                 return eDVBChannelQuery::tProvider;
2086         else if (type == "type")
2087                 return eDVBChannelQuery::tType;
2088         else if (type == "bouquet")
2089                 return eDVBChannelQuery::tBouquet;
2090         else if (type == "satellitePosition")
2091                 return eDVBChannelQuery::tSatellitePosition;
2092         else if (type == "channelID")
2093                 return eDVBChannelQuery::tChannelID;
2094         else if (type == "flags")
2095                 return eDVBChannelQuery::tFlags;
2096         else
2097                 return -1;
2098 }
2099
2100         /* never, NEVER write a parser in C++! */
2101 RESULT parseExpression(ePtr<eDVBChannelQuery> &res, std::list<std::string>::const_iterator begin, std::list<std::string>::const_iterator end)
2102 {
2103         std::list<std::string>::const_iterator end_of_exp;
2104
2105         if (begin == end)
2106                 return 0;
2107
2108         if (*begin == "(")
2109         {
2110                 end_of_exp = begin;
2111                 while (end_of_exp != end)
2112                         if (*end_of_exp == ")")
2113                                 break;
2114                         else
2115                                 ++end_of_exp;
2116
2117                 if (end_of_exp == end)
2118                 {
2119                         eDebug("[parseExpression] end of expression while searching for closing brace");
2120                         return -1;
2121                 }
2122
2123                 ++begin;
2124                 // begin..end_of_exp
2125                 int r = parseExpression(res, begin, end_of_exp);
2126                 if (r)
2127                         return r;
2128                 ++end_of_exp;
2129
2130                         /* we had only one sub expression */
2131                 if (end_of_exp == end)
2132                 {
2133 //                      eDebug("[parseExpression] only one sub expression");
2134                         return 0;
2135                 }
2136
2137                         /* otherwise we have an operator here.. */
2138
2139                 ePtr<eDVBChannelQuery> r2 = res;
2140                 res = new eDVBChannelQuery();
2141                 res->m_sort = 0;
2142                 res->m_p1 = r2;
2143                 res->m_inverse = 0;
2144                 r2 = 0;
2145
2146                 if (*end_of_exp == "||")
2147                         res->m_type = eDVBChannelQuery::tOR;
2148                 else if (*end_of_exp == "&&")
2149                         res->m_type = eDVBChannelQuery::tAND;
2150                 else
2151                 {
2152                         eDebug("[parseExpression] found operator %s, but only && and || are allowed!", end_of_exp->c_str());
2153                         res = 0;
2154                         return 1;
2155                 }
2156
2157                 ++end_of_exp;
2158
2159                 return parseExpression(res->m_p2, end_of_exp, end);
2160         }
2161
2162         // "begin" <op> "end"
2163         std::string type, op, val;
2164
2165         res = new eDVBChannelQuery();
2166         res->m_sort = 0;
2167
2168         int cnt = 0;
2169         while (begin != end)
2170         {
2171                 switch (cnt)
2172                 {
2173                 case 0:
2174                         type = *begin;
2175                         break;
2176                 case 1:
2177                         op = *begin;
2178                         break;
2179                 case 2:
2180                         val = *begin;
2181                         break;
2182                 case 3:
2183                         eDebug("[parseExpression] malformed query: got '%s', but expected only <type> <op> <val>", begin->c_str());
2184                         return 1;
2185                 }
2186                 ++begin;
2187                 ++cnt;
2188         }
2189
2190         if (cnt != 3)
2191         {
2192                 eDebug("[parseExpression] malformed query: missing stuff");
2193                 res = 0;
2194                 return 1;
2195         }
2196
2197         res->m_type = decodeType(type);
2198
2199         if (res->m_type == -1)
2200         {
2201                 eDebug("[parseExpression] malformed query: invalid type %s", type.c_str());
2202                 res = 0;
2203                 return 1;
2204         }
2205
2206         if (op == "==")
2207                 res->m_inverse = 0;
2208         else if (op == "!=")
2209                 res->m_inverse = 1;
2210         else
2211         {
2212                 eDebug("[parseExpression] invalid operator %s", op.c_str());
2213                 res = 0;
2214                 return 1;
2215         }
2216
2217         res->m_string = val;
2218
2219         if (res->m_type == eDVBChannelQuery::tChannelID)
2220         {
2221                 int ns, tsid, onid;
2222                 if (sscanf(val.c_str(), "%08x%04x%04x", &ns, &tsid, &onid) == 3)
2223                         res->m_channelid = eDVBChannelID(eDVBNamespace(ns), eTransportStreamID(tsid), eOriginalNetworkID(onid));
2224                 else
2225                         eDebug("[parseExpression] couldn't parse channelid !! format should be hex NNNNNNNNTTTTOOOO (namespace, tsid, onid)");
2226         }
2227         else
2228                 res->m_int = atoi(val.c_str());
2229
2230         return 0;
2231 }
2232
2233 RESULT eDVBChannelQuery::compile(ePtr<eDVBChannelQuery> &res, std::string query)
2234 {
2235         std::list<std::string> tokens;
2236
2237         std::string current_token;
2238         std::string bouquet_name;
2239
2240 //      eDebug("[eDVBChannelQuery] splitting %s....", query.c_str());
2241         unsigned int i = 0;
2242         const char *splitchars="()";
2243         int quotemode = 0, lastsplit = 0, lastalnum = 0;
2244         while (i <= query.size())
2245         {
2246                 int c = (i < query.size()) ? query[i] : ' ';
2247                 ++i;
2248
2249                 int issplit = !!strchr(splitchars, c);
2250                 int isaln = isalnum(c);
2251                 int iswhite = c == ' ';
2252                 int isquot = c == '\"';
2253
2254                 if (quotemode)
2255                 {
2256                         iswhite = issplit = 0;
2257                         isaln = lastalnum;
2258                 }
2259
2260                 if (issplit || iswhite || isquot || lastsplit || (lastalnum != isaln))
2261                 {
2262                         if (current_token.size())
2263                                 tokens.push_back(current_token);
2264                         current_token.clear();
2265                 }
2266
2267                 if (!(iswhite || isquot))
2268                         current_token += c;
2269
2270                 if (isquot)
2271                         quotemode = !quotemode;
2272                 lastsplit = issplit;
2273                 lastalnum = isaln;
2274         }
2275
2276 //      for (std::list<std::string>::const_iterator a(tokens.begin()); a != tokens.end(); ++a)
2277 //      {
2278 //              printf("%s\n", a->c_str());
2279 //      }
2280
2281         int sort = eDVBChannelQuery::tName;
2282                 /* check for "ORDER BY ..." */
2283
2284         std::list<std::string>::iterator it = tokens.begin();
2285         while (it != tokens.end())
2286         {
2287                 if (*it == "ORDER")
2288                 {
2289                         tokens.erase(it++);
2290                         if (it != tokens.end() && *it == "BY")
2291                         {
2292                                 tokens.erase(it++);
2293                                 sort = decodeType(*it);
2294                                 tokens.erase(it++);
2295                         } else
2296                                 sort = -1;
2297                 }
2298                 else if (*it == "FROM")
2299                 {
2300                         tokens.erase(it++);
2301                         if (it != tokens.end() && *it == "BOUQUET")
2302                         {
2303                                 tokens.erase(it++);
2304                                 bouquet_name = *it;
2305                                 tokens.erase(it++);
2306                         }
2307                         else if (it != tokens.end() && *it == "SATELLITES")
2308                                 tokens.erase(it++);
2309                         else if (it != tokens.end() && *it == "PROVIDERS")
2310                                 tokens.erase(it++);
2311                         else
2312                         {
2313                                 eDebug("[eDVBChannelQuery] FROM unknown %s", (*it).c_str());
2314                                 tokens.erase(it++);
2315                         }
2316                 }
2317                 else
2318                         ++it;
2319         }
2320
2321         if (sort == -1)
2322         {
2323                 eWarning("[eDVBChannelQuery] ORDER BY .. string invalid.");
2324                 res = 0;
2325                 return -1;
2326         }
2327
2328 //      eDebug("[eDVBChannelQuery] sort by %d", sort);
2329
2330                 /* now we recursivly parse that. */
2331         int r = parseExpression(res, tokens.begin(), tokens.end());
2332
2333                 /* we have an empty (but valid!) expression */
2334         if (!r && !res)
2335         {
2336                 res = new eDVBChannelQuery();
2337                 res->m_inverse = 0;
2338                 res->m_type = eDVBChannelQuery::tAny;
2339         }
2340
2341         if (res)
2342         {
2343                 res->m_sort = sort;
2344                 res->m_bouquet_name = bouquet_name;
2345         }
2346
2347 //      eDebug("[eDVBChannelQuery] return: %d", r);
2348         return r;
2349 }
2350
2351 DEFINE_REF(eDVBChannelQuery);