fix
[enigma2.git] / lib / dvb / db.cpp
1 #include <errno.h>
2 #include <lib/dvb/db.h>
3 #include <lib/dvb/frontend.h>
4 #include <lib/base/eerror.h>
5 #include <lib/base/estring.h>
6 #include <dvbsi++/service_description_section.h>
7 #include <dvbsi++/descriptor_tag.h>
8 #include <dvbsi++/service_descriptor.h>
9 #include <dvbsi++/satellite_delivery_system_descriptor.h>
10
11 DEFINE_REF(eDVBService);
12
13 // the following three methodes are declared in idvb.h
14 RESULT eBouquet::addService(const eServiceReference &ref)
15 {
16         list::iterator it =
17                 std::find(m_services.begin(), m_services.end(), ref);
18         if ( it != m_services.end() )
19                 return -1;
20         m_services.push_back(ref);
21         return 0;
22 }
23
24 RESULT eBouquet::removeService(const eServiceReference &ref)
25 {
26         list::iterator it =
27                 std::find(m_services.begin(), m_services.end(), ref);
28         if ( it == m_services.end() )
29                 return -1;
30         m_services.erase(it);
31         return 0;
32 }
33
34 RESULT eBouquet::moveService(const eServiceReference &ref, unsigned int pos)
35 {
36         if ( pos < 0 || pos >= m_services.size() )
37                 return -1;
38         list::iterator source=m_services.end();
39         list::iterator dest=m_services.end();
40         for (list::iterator it(m_services.begin()); it != m_services.end(); ++it)
41         {
42                 if (dest == m_services.end() && !pos--)
43                         dest = it;
44                 if (*it == ref)
45                         source = it;
46                 if (dest != m_services.end() && source != m_services.end())
47                         break;
48         }
49         if (dest == m_services.end() || source == m_services.end() || source == dest)
50                 return -1;
51         std::iter_swap(source,dest);
52         return 0;
53 }
54
55 eDVBService::eDVBService()
56 {
57 }
58
59 eDVBService::~eDVBService()
60 {
61 }
62
63 eDVBService &eDVBService::operator=(const eDVBService &s)
64 {
65         m_service_name = s.m_service_name;
66         m_service_name_sort = s.m_service_name_sort;
67         m_provider_name = s.m_provider_name;
68         m_flags = s.m_flags;
69         m_ca = s.m_ca;
70         m_cache = s.m_cache;
71         return *this;
72 }
73
74 RESULT eDVBService::getName(const eServiceReference &ref, std::string &name)
75 {
76         if (!ref.name.empty())
77                 name = ref.name;
78         else if (!m_service_name.empty())
79                 name = m_service_name;
80         else
81                 name = "(...)";
82         return 0;
83 }
84
85 int eDVBService::getLength(const eServiceReference &ref)
86 {
87         return -1;
88 }
89
90 int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQuery &query)
91 {
92         int res = 0;
93         switch (query.m_type)
94         {
95         case eDVBChannelQuery::tName:
96                 res = m_service_name_sort.find(query.m_string) != std::string::npos;
97                 break;
98         case eDVBChannelQuery::tProvider:
99                 res = m_provider_name.find(query.m_string) != std::string::npos;
100                 break;
101         case eDVBChannelQuery::tType:
102                 res = ref.getServiceType() == query.m_int;
103                 break;
104         case eDVBChannelQuery::tBouquet:
105                 res = 0;
106                 break;
107         case eDVBChannelQuery::tSatellitePosition:
108                 res = (ref.getDVBNamespace().get() >> 16) == query.m_int;
109                 break;
110         case eDVBChannelQuery::tChannelID:
111         {
112                 eDVBChannelID chid;
113                 ref.getChannelID(chid);
114                 res = chid == query.m_channelid;
115                 break;
116         }
117         case eDVBChannelQuery::tAND:
118                 res = checkFilter(ref, *query.m_p1) && checkFilter(ref, *query.m_p2);
119                 break;
120         case eDVBChannelQuery::tOR:
121                 res = checkFilter(ref, *query.m_p1) || checkFilter(ref, *query.m_p2);
122                 break;
123         }
124
125         if (query.m_inverse)
126                 return !res;
127         else
128                 return res;
129 }
130
131 int eDVBService::getCachePID(cacheID id)
132 {
133         std::map<int, int>::iterator it = m_cache.find(id);
134         if ( it != m_cache.end() )
135                 return it->second;
136         return -1;
137 }
138
139 void eDVBService::setCachePID(cacheID id, int pid)
140 {
141         m_cache[id] = pid;
142 }
143
144 DEFINE_REF(eDVBDB);
145
146         /* THIS CODE IS BAD. it should be replaced by somethine better. */
147 void eDVBDB::load()
148 {
149         eDebug("---- opening lame channel db");
150         FILE *f=fopen("lamedb", "rt");
151         if (!f)
152                 return;
153         char line[256];
154         if ((!fgets(line, 256, f)) || strncmp(line, "eDVB services", 13))
155         {
156                 eDebug("not a servicefile");
157                 fclose(f);
158                 return;
159         }
160         eDebug("reading services");
161         if ((!fgets(line, 256, f)) || strcmp(line, "transponders\n"))
162         {
163                 eDebug("services invalid, no transponders");
164                 fclose(f);
165                 return;
166         }
167
168         // clear all transponders
169
170         while (!feof(f))
171         {
172                 if (!fgets(line, 256, f))
173                         break;
174                 if (!strcmp(line, "end\n"))
175                         break;
176                 int dvb_namespace=-1, transport_stream_id=-1, original_network_id=-1;
177                 sscanf(line, "%x:%x:%x", &dvb_namespace, &transport_stream_id, &original_network_id);
178                 if (original_network_id == -1)
179                         continue;
180                 eDVBChannelID channelid = eDVBChannelID(
181                         eDVBNamespace(dvb_namespace),
182                         eTransportStreamID(transport_stream_id),
183                         eOriginalNetworkID(original_network_id));
184
185                 ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters;
186                 while (!feof(f))
187                 {
188                         fgets(line, 256, f);
189                         if (!strcmp(line, "/\n"))
190                                 break;
191                         if (line[1]=='s')
192                         {
193                                 eDVBFrontendParametersSatellite sat;
194                                 int frequency, symbol_rate, polarisation, fec, orbital_position, inversion;
195                                 sscanf(line+2, "%d:%d:%d:%d:%d:%d", &frequency, &symbol_rate, &polarisation, &fec, &orbital_position, &inversion);
196                                 sat.frequency = frequency;
197                                 sat.symbol_rate = symbol_rate;
198                                 sat.polarisation = polarisation;
199                                 sat.fec = fec;
200                                 sat.orbital_position = orbital_position;
201                                 sat.inversion = inversion;
202                                 feparm->setDVBS(sat);
203                         } else if (line[1]=='t')
204                         {
205                                 eDVBFrontendParametersTerrestrial ter;
206                                 int frequency, bandwidth, code_rate_HP, code_rate_LP, modulation, transmission_mode, guard_interval, hierarchy, inversion;
207                                 sscanf(line+2, "%d:%d:%d:%d:%d:%d:%d:%d:%d", &frequency, &bandwidth, &code_rate_HP, &code_rate_LP, &modulation, &transmission_mode, &guard_interval, &hierarchy, &inversion);
208                                 ter.frequency = frequency;
209                                 ter.bandwidth = bandwidth;
210                                 ter.code_rate_HP = code_rate_HP;
211                                 ter.code_rate_LP = code_rate_LP;
212                                 ter.modulation = modulation;
213                                 ter.transmission_mode = transmission_mode;
214                                 ter.guard_interval = guard_interval;
215                                 ter.hierarchy = hierarchy;
216                                 ter.inversion = inversion;
217                                 
218                                 feparm->setDVBT(ter);
219                         } else if (line[1]=='c')
220                         {
221                                 int frequency, symbol_rate, inversion=0, modulation=3;
222                                 sscanf(line+2, "%d:%d:%d:%d", &frequency, &symbol_rate, &inversion, &modulation);
223 //                              t.setCable(frequency, symbol_rate, inversion, modulation);
224                         }
225                 }
226                 addChannelToList(channelid, feparm);
227         }
228
229         if ((!fgets(line, 256, f)) || strcmp(line, "services\n"))
230         {
231                 eDebug("services invalid, no services");
232                 return;
233         }
234
235         // clear all services
236
237         int count=0;
238
239         while (!feof(f))
240         {
241                 if (!fgets(line, 256, f))
242                         break;
243                 if (!strcmp(line, "end\n"))
244                         break;
245
246                 int service_id=-1, dvb_namespace, transport_stream_id=-1, original_network_id=-1, service_type=-1, service_number=-1;
247                 sscanf(line, "%x:%x:%x:%x:%d:%d", &service_id, &dvb_namespace, &transport_stream_id, &original_network_id, &service_type, &service_number);
248                 if (service_number == -1)
249                         continue;
250                 ePtr<eDVBService> s = new eDVBService;
251                 eServiceReferenceDVB ref =
252                                                 eServiceReferenceDVB(
253                                                 eDVBNamespace(dvb_namespace),
254                                                 eTransportStreamID(transport_stream_id),
255                                                 eOriginalNetworkID(original_network_id),
256                                                 eServiceID(service_id),
257                                                 service_type);
258                 count++;
259                 fgets(line, 256, f);
260                 if (strlen(line))
261                         line[strlen(line)-1]=0;
262
263                 s->m_service_name = line;
264                 s->m_service_name_sort = removeDVBChars(line);
265                 makeUpper(s->m_service_name_sort);
266                 while ((!s->m_service_name_sort.empty()) && s->m_service_name_sort[0] == ' ')
267                         s->m_service_name_sort.erase(0, 1);
268                 
269                         /* put unnamed services at the end, not at the beginning. */
270                 if (s->m_service_name_sort.empty())
271                         s->m_service_name_sort = "\xFF";
272                 
273                 fgets(line, 256, f);
274                 if (strlen(line))
275                         line[strlen(line)-1]=0;
276
277                 std::string str=line;
278
279                 if (str[1]!=':')        // old ... (only service_provider)
280                 {
281                         s->m_provider_name=line;
282                 } else
283                         while ((!str.empty()) && str[1]==':') // new: p:, f:, c:%02d...
284                         {
285                                 unsigned int c=str.find(',');
286                                 char p=str[0];
287                                 std::string v;
288                                 if (c == std::string::npos)
289                                 {
290                                         v=str.substr(2);
291                                         str="";
292                                 } else
293                                 {
294                                         v=str.substr(2, c-2);
295                                         str=str.substr(c+1);
296                                 }
297 //                              eDebug("%c ... %s", p, v.c_str());
298                                 if (p == 'p')
299                                         s->m_provider_name=v;
300                                 else if (p == 'f')
301                                 {
302                                         sscanf(v.c_str(), "%x", &s->m_flags);
303                                 } else if (p == 'c')
304                                 {
305                                         int cid, val;
306                                         sscanf(v.c_str(), "%02d%04x", &cid, &val);
307                                         s->m_cache[cid]=val;
308                                 } else if (p == 'C')
309                                 {
310                                         int val;
311                                         sscanf(v.c_str(), "%04x", &val);
312                                         s->m_ca.insert(val);
313                                 }
314                         }
315                 addService(ref, s);
316         }
317
318         eDebug("loaded %d services", count);
319
320         fclose(f);
321 }
322
323 void eDVBDB::save()
324 {
325         eDebug("---- saving lame channel db");
326         FILE *f=fopen("lamedb", "wt");
327         int channels=0, services=0;
328         if (!f)
329                 eFatal("couldn't save lame channel db!");
330         fprintf(f, "eDVB services /3/\n");
331         fprintf(f, "transponders\n");
332         for (std::map<eDVBChannelID, channel>::const_iterator i(m_channels.begin());
333                         i != m_channels.end(); ++i)
334         {
335                 const eDVBChannelID &chid = i->first;
336                 const channel &ch = i->second;
337
338                 fprintf(f, "%08x:%04x:%04x\n", chid.dvbnamespace.get(),
339                                 chid.transport_stream_id.get(), chid.original_network_id.get());
340                 eDVBFrontendParametersSatellite sat;
341                 eDVBFrontendParametersTerrestrial ter;
342                 if (!ch.m_frontendParameters->getDVBS(sat))
343                 {
344                         fprintf(f, "\ts %d:%d:%d:%d:%d:%d\n",
345                                 sat.frequency, sat.symbol_rate,
346                                 sat.polarisation, sat.fec, sat.orbital_position,
347                                 sat.inversion);
348                 }
349                 if (!ch.m_frontendParameters->getDVBT(ter))
350                 {
351                         fprintf(f, "\tt %d:%d:%d:%d:%d:%d:%d:%d:%d\n",
352                                 ter.frequency, ter.bandwidth, ter.code_rate_HP,
353                                 ter.code_rate_LP, ter.modulation, ter.transmission_mode,
354                                 ter.guard_interval, ter.hierarchy, ter.inversion);
355                 }
356                 fprintf(f, "/\n");
357                 channels++;
358         }
359         fprintf(f, "end\nservices\n");
360
361         for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator i(m_services.begin());
362                 i != m_services.end(); ++i)
363         {
364                 const eServiceReferenceDVB &s = i->first;
365                 fprintf(f, "%04x:%08x:%04x:%04x:%d:%d\n",
366                                 s.getServiceID().get(), s.getDVBNamespace().get(),
367                                 s.getTransportStreamID().get(),s.getOriginalNetworkID().get(),
368                                 s.getServiceType(),
369                                 0);
370
371                 fprintf(f, "%s\n", i->second->m_service_name.c_str());
372                 fprintf(f, "p:%s", i->second->m_provider_name.c_str());
373
374                 // write cached pids
375                 for (std::map<int,int>::const_iterator ca(i->second->m_cache.begin());
376                         ca != i->second->m_cache.end(); ++ca)
377                         fprintf(f, ",c:%02d%04x", ca->first, ca->second);
378
379                 // write cached ca pids
380                 for (std::set<int>::const_iterator ca(i->second->m_ca.begin());
381                         ca != i->second->m_ca.end(); ++ca)
382                         fprintf(f, ",C:%04x", *ca);
383
384                 fprintf(f, "\n");
385                 services++;
386         }
387         fprintf(f, "end\nHave a lot of bugs!\n");
388         eDebug("saved %d channels and %d services!", channels, services);
389         fclose(f);
390 }
391
392 void eDVBDB::loadBouquet(const char *path)
393 {
394         std::string bouquet_name = path;
395         if (!bouquet_name.length())
396         {
397                 eDebug("Bouquet load failed.. no path given..");
398                 return;
399         }
400         unsigned int pos = bouquet_name.rfind('/');
401         if ( pos != std::string::npos )
402                 bouquet_name.erase(0, pos+1);
403         if (bouquet_name.empty())
404         {
405                 eDebug("Bouquet load failed.. no filename given..");
406                 return;
407         }
408         eBouquet &bouquet = m_bouquets[bouquet_name];
409         bouquet.m_path = path;
410         std::list<eServiceReference> &list = bouquet.m_services;
411         list.clear();
412
413         eDebug("loading bouquet... %s", path);
414         FILE *fp=fopen(path, "rt");
415         int entries=0;
416         if (!fp)
417         {
418                 eDebug("failed to open.");
419                 return;
420         }
421         char line[256];
422         bool read_descr=false;
423         eServiceReference *e = NULL;
424         while (1)
425         {
426                 if (!fgets(line, 256, fp))
427                         break;
428                 line[strlen(line)-1]=0;
429                 if (strlen(line) && line[strlen(line)-1]=='\r')
430                         line[strlen(line)-1]=0;
431                 if (!line[0])
432                         break;
433                 if (line[0]=='#')
434                 {
435                         if (!strncmp(line, "#SERVICE ", 9) || !strncmp(line, "#SERVICE: ", 10))
436                         {
437                                 int offs = line[8] == ':' ? 10 : 9;
438                                 eServiceReference tmp(line+offs);
439                                 if (tmp.type != eServiceReference::idDVB)
440                                 {
441                                         eDebug("only DVB Bouquets supported");
442                                         continue;
443                                 }
444                                 if ( (tmp.flags&eServiceReference::flagDirectory) == eServiceReference::flagDirectory )
445                                 {
446                                         std::string str = tmp.path;
447                                         unsigned int pos = str.rfind('/');
448                                         if ( pos != std::string::npos )
449                                                 str.erase(0, pos+1);
450                                         if (str.empty())
451                                         {
452                                                 eDebug("Bouquet load failed.. no filename given..");
453                                                 continue;
454                                         }
455                                         loadBouquet(tmp.path.c_str());
456                                         char buf[256];
457                                         snprintf(buf, 256, "(type == %d) FROM BOUQUET \"%s\" ORDER BY bouquet", tmp.data[0], str.c_str());
458                                         tmp.path = buf;
459                                 }
460                                 list.push_back(tmp);
461                                 e = &list.back();
462                                 read_descr=true;
463                                 ++entries;
464                         }
465                         else if (read_descr && !strncmp(line, "#DESCRIPTION ", 13))
466                         {
467                                 e->name = line+13;
468                                 read_descr=false;
469                         }
470                         else if (!strncmp(line, "#NAME ", 6))
471                                 bouquet.m_bouquet_name=line+6;
472                         continue;
473                 }
474         }
475         fclose(fp);
476         eDebug("%d entries in Bouquet %s", entries, bouquet_name.c_str());
477 }
478
479 void eDVBDB::saveBouquet(const char *path)
480 {
481
482 }
483
484 void eDVBDB::loadBouquets()
485 {
486         loadBouquet("bouquets.tv");
487         loadBouquet("bouquets.radio");
488 }
489
490 void eDVBDB::saveBouquets()
491 {
492
493 }
494
495 eDVBDB::eDVBDB()
496 {
497         load();
498         loadBouquets();
499 }
500
501 eDVBDB::~eDVBDB()
502 {
503 //      save();
504 }
505
506 RESULT eDVBDB::addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm)
507 {
508         channel ch;
509         assert(feparm);
510         ch.m_frontendParameters = feparm;
511         m_channels.insert(std::pair<eDVBChannelID, channel>(id, ch));
512         return 0;
513 }
514
515 RESULT eDVBDB::removeChannel(const eDVBChannelID &id)
516 {
517         m_channels.erase(id);
518         return 0;
519 }
520
521 RESULT eDVBDB::getChannelFrontendData(const eDVBChannelID &id, ePtr<iDVBFrontendParameters> &parm)
522 {
523         std::map<eDVBChannelID, channel>::iterator i = m_channels.find(id);
524         if (i == m_channels.end())
525         {
526                 parm = 0;
527                 return -ENOENT;
528         }
529         parm = i->second.m_frontendParameters;
530         return 0;
531 }
532
533 RESULT eDVBDB::addService(const eServiceReferenceDVB &serviceref, eDVBService *service)
534 {
535         m_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(serviceref, service));
536         return 0;
537 }
538
539 RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr<eDVBService> &service)
540 {
541         std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator i;
542         i = m_services.find(reference);
543         if (i == m_services.end())
544         {
545                 service = 0;
546                 return -ENOENT;
547         }
548         service = i->second;
549         return 0;
550 }
551
552 RESULT eDVBDB::getBouquet(const eServiceReference &ref, eBouquet* &bouquet)
553 {
554         std::string str = ref.path;
555         if (str.empty())
556         {
557                 eDebug("getBouquet failed.. no path given!");
558                 return -1;
559         }
560         unsigned int pos = str.find("FROM BOUQUET \"");
561         if ( pos != std::string::npos )
562         {
563                 str.erase(0, pos+14);
564                 pos = str.find('"');
565                 if ( pos != std::string::npos )
566                         str.erase(pos);
567                 else
568                         str.clear();
569         }
570         if (str.empty())
571         {
572                 eDebug("getBouquet failed.. couldn't parse bouquet name");
573                 return -1;
574         }
575         std::map<std::string, eBouquet>::iterator i =
576                 m_bouquets.find(str);
577         if (i == m_bouquets.end())
578         {
579                 bouquet = 0;
580                 return -ENOENT;
581         }
582         bouquet = &i->second;
583         return 0;
584 }
585
586 RESULT eDVBDB::startQuery(ePtr<iDVBChannelListQuery> &query, eDVBChannelQuery *q, const eServiceReference &source)
587 {
588         if ( q && q->m_bouquet_name.length() )
589                 query = new eDVBDBBouquetQuery(this, source, q);
590         else
591                 query = new eDVBDBQuery(this, source, q);
592         return 0;
593 }
594
595 DEFINE_REF(eDVBDBQueryBase);
596
597 eDVBDBQueryBase::eDVBDBQueryBase(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
598         :m_db(db), m_query(query), m_source(source)
599 {
600 }
601
602 int eDVBDBQueryBase::compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b)
603 {
604         ePtr<eDVBService> a_service, b_service;
605         
606         int sortmode = m_query ? m_query->m_sort : eDVBChannelQuery::tName;
607         
608         if ((sortmode == eDVBChannelQuery::tName) || (sortmode == eDVBChannelQuery::tProvider))
609         {
610                 if (m_db->getService(a, a_service))
611                         return 1;
612                 if (m_db->getService(b, b_service))
613                         return 1;
614         }
615         
616         switch (sortmode)
617         {
618         case eDVBChannelQuery::tName:
619                 return a_service->m_service_name_sort < b_service->m_service_name_sort;
620         case eDVBChannelQuery::tProvider:
621                 return a_service->m_provider_name < b_service->m_provider_name;
622         case eDVBChannelQuery::tType:
623                 return a.getServiceType() < b.getServiceType();
624         case eDVBChannelQuery::tBouquet:
625                 return 0;
626         case eDVBChannelQuery::tSatellitePosition:
627                 return (a.getDVBNamespace().get() >> 16) < (b.getDVBNamespace().get() >> 16);
628         default:
629                 return 1;
630         }
631         return 0;
632 }
633
634 eDVBDBQuery::eDVBDBQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
635         :eDVBDBQueryBase(db, source, query)
636 {
637         m_cursor = m_db->m_services.begin();
638 }
639
640 RESULT eDVBDBQuery::getNextResult(eServiceReferenceDVB &ref)
641 {
642         while (m_cursor != m_db->m_services.end())
643         {
644                 ref = m_cursor->first;
645
646                 int res = (!m_query) || m_cursor->second->checkFilter(ref, *m_query);
647
648                 ++m_cursor;
649
650                 if (res)
651                         return 0;
652         }
653
654         ref = (eServiceReferenceDVB&)eServiceReference();
655
656         return 1;
657 }
658
659 eDVBDBBouquetQuery::eDVBDBBouquetQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
660         :eDVBDBQueryBase(db, source, query), m_cursor(db->m_bouquets[query->m_bouquet_name].m_services.begin())
661 {
662 }
663
664 RESULT eDVBDBBouquetQuery::getNextResult(eServiceReferenceDVB &ref)
665 {
666         eBouquet &bouquet = m_db->m_bouquets[m_query->m_bouquet_name];
667         std::list<eServiceReference> &list = bouquet.m_services;
668         while (m_cursor != list.end())
669         {
670                 ref = *((eServiceReferenceDVB*)&(*m_cursor));
671
672                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it =
673                         m_db->m_services.find(ref);
674
675                 int res = (!m_query) || it == m_db->m_services.end() || it->second->checkFilter(ref, *m_query);
676
677                 ++m_cursor;
678
679                 if (res)
680                         return 0;
681         }
682
683         ref = (eServiceReferenceDVB&)eServiceReference();
684
685         return 1;
686 }
687
688 /* (<name|provider|type|bouquet|satpos|chid> <==|...> <"string"|int>)[||,&& (..)] */
689
690 static int decodeType(const std::string &type)
691 {
692         if (type == "name")
693                 return eDVBChannelQuery::tName;
694         else if (type == "provider")
695                 return eDVBChannelQuery::tProvider;
696         else if (type == "type")
697                 return eDVBChannelQuery::tType;
698         else if (type == "bouquet")
699                 return eDVBChannelQuery::tBouquet;
700         else if (type == "satellitePosition")
701                 return eDVBChannelQuery::tSatellitePosition;
702         else if (type == "channelID")
703                 return eDVBChannelQuery::tChannelID;
704         else
705                 return -1;
706 }
707
708         /* never, NEVER write a parser in C++! */
709 RESULT parseExpression(ePtr<eDVBChannelQuery> &res, std::list<std::string>::const_iterator begin, std::list<std::string>::const_iterator end)
710 {
711         std::list<std::string>::const_iterator end_of_exp;
712         if (*begin == "(")
713         {
714                 end_of_exp = begin;
715                 while (end_of_exp != end)
716                         if (*end_of_exp == ")")
717                                 break;
718                         else
719                                 ++end_of_exp;
720         
721                 if (end_of_exp == end)
722                 {
723                         eDebug("expression parse: end of expression while searching for closing brace");
724                         return -1;
725                 }
726                 
727                 ++begin;
728                 // begin..end_of_exp
729                 int r = parseExpression(res, begin, end_of_exp);
730                 if (r)
731                         return r;
732                 ++end_of_exp;
733                 
734                         /* we had only one sub expression */
735                 if (end_of_exp == end)
736                 {
737 //                      eDebug("only one sub expression");
738                         return 0;
739                 }
740                 
741                         /* otherwise we have an operator here.. */
742                 
743                 ePtr<eDVBChannelQuery> r2 = res;
744                 res = new eDVBChannelQuery();
745                 res->m_sort = 0;
746                 res->m_p1 = r2;
747                 res->m_inverse = 0;
748                 r2 = 0;
749                 
750                 if (*end_of_exp == "||")
751                         res->m_type = eDVBChannelQuery::tOR;
752                 else if (*end_of_exp == "&&")
753                         res->m_type = eDVBChannelQuery::tAND;
754                 else
755                 {
756                         eDebug("found operator %s, but only && and || are allowed!", end_of_exp->c_str());
757                         res = 0;
758                         return 1;
759                 }
760                 
761                 ++end_of_exp;
762                 
763                 return parseExpression(res->m_p2, end_of_exp, end);
764         }
765         
766         // "begin" <op> "end"
767         std::string type, op, val;
768         
769         res = new eDVBChannelQuery();
770         res->m_sort = 0;
771         
772         int cnt = 0;
773         while (begin != end)
774         {
775                 switch (cnt)
776                 {
777                 case 0:
778                         type = *begin;
779                         break;
780                 case 1:
781                         op = *begin;
782                         break;
783                 case 2:
784                         val = *begin;
785                         break;
786                 case 3:
787                         eDebug("malformed query: got '%s', but expected only <type> <op> <val>", begin->c_str());
788                         return 1;
789                 }
790                 ++begin;
791                 ++cnt;
792         }
793         
794         if (cnt != 3)
795         {
796                 eDebug("malformed query: missing stuff");
797                 res = 0;
798                 return 1;
799         }
800         
801         res->m_type = decodeType(type);
802         
803         if (res->m_type == -1)
804         {
805                 eDebug("malformed query: invalid type %s", type.c_str());
806                 res = 0;
807                 return 1;
808         }
809         
810         if (op == "==")
811                 res->m_inverse = 0;
812         else if (op == "!=")
813                 res->m_inverse = 1;
814         else
815         {
816                 eDebug("invalid operator %s", op.c_str());
817                 res = 0;
818                 return 1;
819         }
820         
821         res->m_string = val;
822         res->m_int = atoi(val.c_str());
823 //      res->m_channelid = eDVBChannelID(val);
824         
825         return 0;
826 }
827
828 RESULT eDVBChannelQuery::compile(ePtr<eDVBChannelQuery> &res, std::string query)
829 {
830         std::list<std::string> tokens;
831         
832         std::string current_token;
833         std::string bouquet_name;
834
835 //      eDebug("splitting %s....", query.c_str());
836         unsigned int i = 0;
837         const char *splitchars="()";
838         int quotemode = 0, lastsplit = 0, lastalnum = 0;
839         while (i <= query.size())
840         {
841                 int c = (i < query.size()) ? query[i] : ' ';
842                 ++i;
843                 
844                 int issplit = !!strchr(splitchars, c);
845                 int isaln = isalnum(c);
846                 int iswhite = c == ' ';
847                 int isquot = c == '\"';
848                 
849                 if (quotemode)
850                 {
851                         iswhite = issplit = 0;
852                         isaln = lastalnum;
853                 }
854                 
855                 if (issplit || iswhite || isquot || lastsplit || (lastalnum != isaln))
856                 {
857                         if (current_token.size())
858                                 tokens.push_back(current_token);
859                         current_token.clear();
860                 }
861                 
862                 if (!(iswhite || isquot))
863                         current_token += c;
864                 
865                 if (isquot)
866                         quotemode = !quotemode;
867                 lastsplit = issplit;
868                 lastalnum = isaln;
869         }
870         
871 //      for (std::list<std::string>::const_iterator a(tokens.begin()); a != tokens.end(); ++a)
872 //      {
873 //              printf("%s\n", a->c_str());
874 //      }
875
876         int sort = eDVBChannelQuery::tName;
877                 /* check for "ORDER BY ..." */
878
879         while (tokens.size() > 2)
880         {
881                 std::list<std::string>::iterator it = tokens.end();
882                 --it; --it; --it;
883                 if (*it == "ORDER")
884                 {
885                         ++it;
886                         if (*it == "BY")
887                         {
888                                 ++it;
889                                 sort = decodeType(*it);
890                                 tokens.pop_back(); // ...
891                                 tokens.pop_back(); // BY
892                                 tokens.pop_back(); // ORDER
893                         } else
894                                 sort = -1;
895                 }
896                 else if (*it == "FROM")
897                 {
898                         ++it;
899                         if (*it == "BOUQUET")
900                         {
901                                 ++it;
902                                 bouquet_name = *it;
903                                 tokens.pop_back(); // ...
904                                 tokens.pop_back(); // FROM
905                                 tokens.pop_back(); // BOUQUET
906                         }
907                 }
908                 else
909                         break;
910         }
911
912         if (sort == -1)
913         {
914                 eWarning("ORDER BY .. string invalid.");
915                 res = 0;
916                 return -1;
917         }
918         
919 //      eDebug("sort by %d", sort);
920         
921                 /* now we recursivly parse that. */
922         int r = parseExpression(res, tokens.begin(), tokens.end());
923         
924         if (res)
925         {
926                 res->m_sort = sort;
927                 res->m_bouquet_name = bouquet_name;
928         }
929
930 //      eDebug("return: %d", r);
931         return r;
932 }
933
934 DEFINE_REF(eDVBChannelQuery);