a9329f18a80c9b5e30a71f39f488466daa4a5c59
[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();
655         return 1;
656 }
657
658 eDVBDBBouquetQuery::eDVBDBBouquetQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
659         :eDVBDBQueryBase(db, source, query), m_cursor(db->m_bouquets[query->m_bouquet_name].m_services.begin())
660 {
661 }
662
663 RESULT eDVBDBBouquetQuery::getNextResult(eServiceReferenceDVB &ref)
664 {
665         eBouquet &bouquet = m_db->m_bouquets[m_query->m_bouquet_name];
666         std::list<eServiceReference> &list = bouquet.m_services;
667         while (m_cursor != list.end())
668         {
669                 ref = *((eServiceReferenceDVB*)&(*m_cursor));
670
671                 std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it =
672                         m_db->m_services.find(ref);
673
674                 int res = (!m_query) || it == m_db->m_services.end() || it->second->checkFilter(ref, *m_query);
675
676                 ++m_cursor;
677
678                 if (res)
679                         return 0;
680         }
681
682         ref = eServiceReferenceDVB();
683
684         return 1;
685 }
686
687 /* (<name|provider|type|bouquet|satpos|chid> <==|...> <"string"|int>)[||,&& (..)] */
688
689 static int decodeType(const std::string &type)
690 {
691         if (type == "name")
692                 return eDVBChannelQuery::tName;
693         else if (type == "provider")
694                 return eDVBChannelQuery::tProvider;
695         else if (type == "type")
696                 return eDVBChannelQuery::tType;
697         else if (type == "bouquet")
698                 return eDVBChannelQuery::tBouquet;
699         else if (type == "satellitePosition")
700                 return eDVBChannelQuery::tSatellitePosition;
701         else if (type == "channelID")
702                 return eDVBChannelQuery::tChannelID;
703         else
704                 return -1;
705 }
706
707         /* never, NEVER write a parser in C++! */
708 RESULT parseExpression(ePtr<eDVBChannelQuery> &res, std::list<std::string>::const_iterator begin, std::list<std::string>::const_iterator end)
709 {
710         std::list<std::string>::const_iterator end_of_exp;
711         if (*begin == "(")
712         {
713                 end_of_exp = begin;
714                 while (end_of_exp != end)
715                         if (*end_of_exp == ")")
716                                 break;
717                         else
718                                 ++end_of_exp;
719         
720                 if (end_of_exp == end)
721                 {
722                         eDebug("expression parse: end of expression while searching for closing brace");
723                         return -1;
724                 }
725                 
726                 ++begin;
727                 // begin..end_of_exp
728                 int r = parseExpression(res, begin, end_of_exp);
729                 if (r)
730                         return r;
731                 ++end_of_exp;
732                 
733                         /* we had only one sub expression */
734                 if (end_of_exp == end)
735                 {
736 //                      eDebug("only one sub expression");
737                         return 0;
738                 }
739                 
740                         /* otherwise we have an operator here.. */
741                 
742                 ePtr<eDVBChannelQuery> r2 = res;
743                 res = new eDVBChannelQuery();
744                 res->m_sort = 0;
745                 res->m_p1 = r2;
746                 res->m_inverse = 0;
747                 r2 = 0;
748                 
749                 if (*end_of_exp == "||")
750                         res->m_type = eDVBChannelQuery::tOR;
751                 else if (*end_of_exp == "&&")
752                         res->m_type = eDVBChannelQuery::tAND;
753                 else
754                 {
755                         eDebug("found operator %s, but only && and || are allowed!", end_of_exp->c_str());
756                         res = 0;
757                         return 1;
758                 }
759                 
760                 ++end_of_exp;
761                 
762                 return parseExpression(res->m_p2, end_of_exp, end);
763         }
764         
765         // "begin" <op> "end"
766         std::string type, op, val;
767         
768         res = new eDVBChannelQuery();
769         res->m_sort = 0;
770         
771         int cnt = 0;
772         while (begin != end)
773         {
774                 switch (cnt)
775                 {
776                 case 0:
777                         type = *begin;
778                         break;
779                 case 1:
780                         op = *begin;
781                         break;
782                 case 2:
783                         val = *begin;
784                         break;
785                 case 3:
786                         eDebug("malformed query: got '%s', but expected only <type> <op> <val>", begin->c_str());
787                         return 1;
788                 }
789                 ++begin;
790                 ++cnt;
791         }
792         
793         if (cnt != 3)
794         {
795                 eDebug("malformed query: missing stuff");
796                 res = 0;
797                 return 1;
798         }
799         
800         res->m_type = decodeType(type);
801         
802         if (res->m_type == -1)
803         {
804                 eDebug("malformed query: invalid type %s", type.c_str());
805                 res = 0;
806                 return 1;
807         }
808         
809         if (op == "==")
810                 res->m_inverse = 0;
811         else if (op == "!=")
812                 res->m_inverse = 1;
813         else
814         {
815                 eDebug("invalid operator %s", op.c_str());
816                 res = 0;
817                 return 1;
818         }
819         
820         res->m_string = val;
821         res->m_int = atoi(val.c_str());
822 //      res->m_channelid = eDVBChannelID(val);
823         
824         return 0;
825 }
826
827 RESULT eDVBChannelQuery::compile(ePtr<eDVBChannelQuery> &res, std::string query)
828 {
829         std::list<std::string> tokens;
830         
831         std::string current_token;
832         std::string bouquet_name;
833
834 //      eDebug("splitting %s....", query.c_str());
835         unsigned int i = 0;
836         const char *splitchars="()";
837         int quotemode = 0, lastsplit = 0, lastalnum = 0;
838         while (i <= query.size())
839         {
840                 int c = (i < query.size()) ? query[i] : ' ';
841                 ++i;
842                 
843                 int issplit = !!strchr(splitchars, c);
844                 int isaln = isalnum(c);
845                 int iswhite = c == ' ';
846                 int isquot = c == '\"';
847                 
848                 if (quotemode)
849                 {
850                         iswhite = issplit = 0;
851                         isaln = lastalnum;
852                 }
853                 
854                 if (issplit || iswhite || isquot || lastsplit || (lastalnum != isaln))
855                 {
856                         if (current_token.size())
857                                 tokens.push_back(current_token);
858                         current_token.clear();
859                 }
860                 
861                 if (!(iswhite || isquot))
862                         current_token += c;
863                 
864                 if (isquot)
865                         quotemode = !quotemode;
866                 lastsplit = issplit;
867                 lastalnum = isaln;
868         }
869         
870 //      for (std::list<std::string>::const_iterator a(tokens.begin()); a != tokens.end(); ++a)
871 //      {
872 //              printf("%s\n", a->c_str());
873 //      }
874
875         int sort = eDVBChannelQuery::tName;
876                 /* check for "ORDER BY ..." */
877
878         while (tokens.size() > 2)
879         {
880                 std::list<std::string>::iterator it = tokens.end();
881                 --it; --it; --it;
882                 if (*it == "ORDER")
883                 {
884                         ++it;
885                         if (*it == "BY")
886                         {
887                                 ++it;
888                                 sort = decodeType(*it);
889                                 tokens.pop_back(); // ...
890                                 tokens.pop_back(); // BY
891                                 tokens.pop_back(); // ORDER
892                         } else
893                                 sort = -1;
894                 }
895                 else if (*it == "FROM")
896                 {
897                         ++it;
898                         if (*it == "BOUQUET")
899                         {
900                                 ++it;
901                                 bouquet_name = *it;
902                                 tokens.pop_back(); // ...
903                                 tokens.pop_back(); // FROM
904                                 tokens.pop_back(); // BOUQUET
905                         }
906                 }
907                 else
908                         break;
909         }
910
911         if (sort == -1)
912         {
913                 eWarning("ORDER BY .. string invalid.");
914                 res = 0;
915                 return -1;
916         }
917         
918 //      eDebug("sort by %d", sort);
919         
920                 /* now we recursivly parse that. */
921         int r = parseExpression(res, tokens.begin(), tokens.end());
922         
923         if (res)
924         {
925                 res->m_sort = sort;
926                 res->m_bouquet_name = bouquet_name;
927         }
928
929 //      eDebug("return: %d", r);
930         return r;
931 }
932
933 DEFINE_REF(eDVBChannelQuery);