convert event_id from string to long
[enigma2.git] / lib / service / servicedvb.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
3 #include <string>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/init_num.h>
7 #include <lib/base/init.h>
8
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
12
13 #include <lib/service/servicedvbrecord.h>
14 #include <lib/dvb/metaparser.h>
15 #include <lib/dvb/tstools.h>
16
17 class eStaticServiceDVBInformation: public iStaticServiceInformation
18 {
19         DECLARE_REF(eStaticServiceDVBInformation);
20 public:
21         RESULT getName(const eServiceReference &ref, std::string &name);
22         int getLength(const eServiceReference &ref);
23 };
24
25 DEFINE_REF(eStaticServiceDVBInformation);
26
27 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
28 {
29         eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
30         if ( !ref.name.empty() )
31         {
32                 if (service.getParentTransportStreamID().get()) // linkage subservice
33                 {
34                         ePtr<iServiceHandler> service_center;
35                         if (!eServiceCenter::getInstance(service_center))
36                         {
37                                 eServiceReferenceDVB parent = service;
38                                 parent.setTransportStreamID( service.getParentTransportStreamID() );
39                                 parent.setServiceID( service.getParentServiceID() );
40                                 parent.setParentTransportStreamID(eTransportStreamID(0));
41                                 parent.setParentServiceID(eServiceID(0));
42                                 parent.name="";
43                                 ePtr<iStaticServiceInformation> service_info;
44                                 if (!service_center->info(parent, service_info))
45                                 {
46                                         if (!service_info->getName(parent, name))
47                                         {
48                                                 // just show short name
49                                                 unsigned int pos = name.find("\xc2\x86");
50                                                 if ( pos != std::string::npos )
51                                                         name.erase(0, pos+2);
52                                                 pos = name.find("\xc2\x87");
53                                                 if ( pos != std::string::npos )
54                                                         name.erase(pos);
55                                                 name+=" - ";
56                                         }
57                                 }
58                         }
59                 }
60                 else
61                         name="";
62                 name += ref.name;
63                 return 0;
64         }
65         else
66                 return -1;
67 }
68
69 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
70 {
71         return -1;
72 }
73
74 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
75 {
76         DECLARE_REF(eStaticServiceDVBBouquetInformation);
77 public:
78         RESULT getName(const eServiceReference &ref, std::string &name);
79         int getLength(const eServiceReference &ref);
80 };
81
82 DEFINE_REF(eStaticServiceDVBBouquetInformation);
83
84 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
85 {
86         ePtr<iDVBChannelList> db;
87         ePtr<eDVBResourceManager> res;
88
89         int err;
90         if ((err = eDVBResourceManager::getInstance(res)) != 0)
91         {
92                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
93                 return err;
94         }
95         if ((err = res->getChannelList(db)) != 0)
96         {
97                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
98                 return err;
99         }
100
101         eBouquet *bouquet=0;
102         if ((err = db->getBouquet(ref, bouquet)) != 0)
103         {
104                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
105                 return -1;
106         }
107
108         if ( bouquet && bouquet->m_bouquet_name.length() )
109         {
110                 name = bouquet->m_bouquet_name;
111                 return 0;
112         }
113         else
114                 return -1;
115 }
116
117 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
118 {
119         return -1;
120 }
121
122 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
123 {
124         DECLARE_REF(eStaticServiceDVBPVRInformation);
125         eServiceReference m_ref;
126         eDVBMetaParser m_parser;
127 public:
128         eStaticServiceDVBPVRInformation(const eServiceReference &ref);
129         RESULT getName(const eServiceReference &ref, std::string &name);
130         int getLength(const eServiceReference &ref);
131         
132         int getInfo(const eServiceReference &ref, int w);
133         std::string getInfoString(const eServiceReference &ref,int w);
134 };
135
136 DEFINE_REF(eStaticServiceDVBPVRInformation);
137
138 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
139 {
140         m_ref = ref;
141         m_parser.parseFile(ref.path);
142 }
143
144 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
145 {
146         ASSERT(ref == m_ref);
147         name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
148         return 0;
149 }
150
151 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
152 {
153         ASSERT(ref == m_ref);
154         
155         eDVBTSTools tstools;
156         
157         if (tstools.openFile(ref.path.c_str()))
158                 return 0;
159
160         pts_t len;
161         if (tstools.calcLen(len))
162                 return 0;
163
164         return len / 90000;
165 }
166
167 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
168 {
169         switch (w)
170         {
171         case iServiceInformation::sDescription:
172                 return iServiceInformation::resIsString;
173         case iServiceInformation::sTimeCreate:
174                 if (m_parser.m_time_create)
175                         return m_parser.m_time_create;
176                 else
177                         return iServiceInformation::resNA;
178         default:
179                 return iServiceInformation::resNA;
180         }
181 }
182
183 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
184 {
185         switch (w)
186         {
187         case iServiceInformation::sDescription:
188                 return m_parser.m_description;
189         default:
190                 return "";
191         }
192 }
193
194 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
195 {
196         DECLARE_REF(eDVBPVRServiceOfflineOperations);
197         eServiceReferenceDVB m_ref;
198 public:
199         eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
200         
201         RESULT deleteFromDisk(int simulate);
202         RESULT getListOfFilenames(std::list<std::string> &);
203 };
204
205 DEFINE_REF(eDVBPVRServiceOfflineOperations);
206
207 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
208 {
209 }
210
211 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
212 {
213         if (simulate)
214                 return 0;
215         else
216         {
217                 std::list<std::string> res;
218                 if (getListOfFilenames(res))
219                         return -1;
220                 
221                                 /* TODO: deferred removing.. */
222                 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
223                 {
224                         eDebug("Removing %s...", i->c_str());
225                         ::unlink(i->c_str());
226                 }
227                 
228                 return 0;
229         }
230 }
231
232 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
233 {
234         res.clear();
235         res.push_back(m_ref.path);
236         res.push_back(m_ref.path + ".meta");
237         return 0;
238 }
239
240 DEFINE_REF(eServiceFactoryDVB)
241
242 eServiceFactoryDVB::eServiceFactoryDVB()
243 {
244         ePtr<eServiceCenter> sc;
245         
246         eServiceCenter::getPrivInstance(sc);
247         if (sc)
248                 sc->addServiceFactory(eServiceFactoryDVB::id, this);
249 }
250
251 eServiceFactoryDVB::~eServiceFactoryDVB()
252 {
253         ePtr<eServiceCenter> sc;
254         
255         eServiceCenter::getPrivInstance(sc);
256         if (sc)
257                 sc->removeServiceFactory(eServiceFactoryDVB::id);
258 }
259
260 DEFINE_REF(eDVBServiceList);
261
262 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
263 {
264 }
265
266 eDVBServiceList::~eDVBServiceList()
267 {
268 }
269
270 RESULT eDVBServiceList::startQuery()
271 {
272         ePtr<iDVBChannelList> db;
273         ePtr<eDVBResourceManager> res;
274         
275         int err;
276         if ((err = eDVBResourceManager::getInstance(res)) != 0)
277         {
278                 eDebug("no resource manager");
279                 return err;
280         }
281         if ((err = res->getChannelList(db)) != 0)
282         {
283                 eDebug("no channel list");
284                 return err;
285         }
286         
287         ePtr<eDVBChannelQuery> q;
288         
289         if (!m_parent.path.empty())
290         {
291                 eDVBChannelQuery::compile(q, m_parent.path);
292                 if (!q)
293                 {
294                         eDebug("compile query failed");
295                         return err;
296                 }
297         }
298         
299         if ((err = db->startQuery(m_query, q, m_parent)) != 0)
300         {
301                 eDebug("startQuery failed");
302                 return err;
303         }
304
305         return 0;
306 }
307
308 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list)
309 {
310         eServiceReferenceDVB ref;
311         
312         if (!m_query)
313                 return -1;
314         
315         while (!m_query->getNextResult(ref))
316                 list.push_back(ref);
317         return 0;
318 }
319
320 RESULT eDVBServiceList::getNext(eServiceReference &ref)
321 {
322         if (!m_query)
323                 return -1;
324         
325         return m_query->getNextResult((eServiceReferenceDVB&)ref);
326 }
327
328 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
329 {
330         return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
331 }
332
333 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
334 {
335         if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
336         {
337                 ePtr<iDVBChannelList> db;
338                 ePtr<eDVBResourceManager> resm;
339
340                 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
341                         return -1;
342
343                 if (db->getBouquet(m_parent, m_bouquet) != 0)
344                         return -1;
345
346                 res = this;
347                 
348                 return 0;
349         }
350         res = 0;
351         return -1;
352 }
353
354 RESULT eDVBServiceList::addService(eServiceReference &ref)
355 {
356         if (!m_bouquet)
357                 return -1;
358         return m_bouquet->addService(ref);
359 }
360
361 RESULT eDVBServiceList::removeService(eServiceReference &ref)
362 {
363         if (!m_bouquet)
364                 return -1;
365         return m_bouquet->removeService(ref);
366 }
367
368 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
369 {
370         if (!m_bouquet)
371                 return -1;
372         return m_bouquet->moveService(ref, pos);
373 }
374
375 RESULT eDVBServiceList::flushChanges()
376 {
377         if (!m_bouquet)
378                 return -1;
379         return m_bouquet->flushChanges();
380 }
381
382 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
383 {
384         ePtr<eDVBService> service;
385         int r = lookupService(service, ref);
386         if (r)
387                 service = 0;
388                 // check resources...
389         ptr = new eDVBServicePlay(ref, service);
390         return 0;
391 }
392
393 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
394 {
395         if (ref.path.empty())
396         {
397                 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
398                 return 0;
399         } else
400         {
401                 ptr = 0;
402                 return -1;
403         }
404 }
405
406 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
407 {
408         ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
409         if (list->startQuery())
410         {
411                 ptr = 0;
412                 return -1;
413         }
414         
415         ptr = list;
416         return 0;
417 }
418
419 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
420 {
421         /* is a listable service? */
422         if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
423         {
424                 if ( !ref.name.empty() )  // satellites or providers list
425                         ptr = new eStaticServiceDVBInformation;
426                 else // a dvb bouquet
427                         ptr = new eStaticServiceDVBBouquetInformation;
428         }
429         else if (!ref.path.empty()) /* do we have a PVR service? */
430                 ptr = new eStaticServiceDVBPVRInformation(ref);
431         else // normal dvb service
432         {
433                 ePtr<eDVBService> service;
434                 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
435                         ptr = new eStaticServiceDVBInformation;
436                 else
437                         /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
438                         ptr = service;
439         }
440         return 0;
441 }
442
443 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
444 {
445         if (ref.path.empty())
446         {
447                 ptr = 0;
448                 return -1;
449         } else
450         {
451                 ptr = new eDVBPVRServiceOfflineOperations(ref);
452                 return 0;
453         }
454 }
455
456 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
457 {
458                         // TODO: handle the listing itself
459         // if (ref.... == -1) .. return "... bouquets ...";
460         // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
461                         // TODO: cache
462         ePtr<iDVBChannelList> db;
463         ePtr<eDVBResourceManager> res;
464         
465         int err;
466         if ((err = eDVBResourceManager::getInstance(res)) != 0)
467         {
468                 eDebug("no resource manager");
469                 return err;
470         }
471         if ((err = res->getChannelList(db)) != 0)
472         {
473                 eDebug("no channel list");
474                 return err;
475         }
476         
477                 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
478         if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
479         {
480                 eDebug("getService failed!");
481                 return err;
482         }
483
484         return 0;
485 }
486
487 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service): 
488         m_reference(ref), m_dvb_service(service), m_is_paused(0)
489 {
490         m_is_pvr = !ref.path.empty();
491         m_timeshift_enabled = m_timeshift_active = 0;
492         
493         CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
494         CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
495         CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
496 }
497
498 eDVBServicePlay::~eDVBServicePlay()
499 {
500 }
501
502 void eDVBServicePlay::gotNewEvent()
503 {
504 #if 0
505                 // debug only
506         ePtr<eServiceEvent> m_event_now, m_event_next;
507         getEvent(m_event_now, 0);
508         getEvent(m_event_next, 1);
509
510         if (m_event_now)
511                 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
512         if (m_event_next)
513                 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
514 #endif
515         m_event((iPlayableService*)this, evUpdatedEventInfo);
516 }
517
518 void eDVBServicePlay::serviceEvent(int event)
519 {
520         switch (event)
521         {
522         case eDVBServicePMTHandler::eventTuned:
523         {
524                 ePtr<iDVBDemux> m_demux;
525                 if (!m_service_handler.getDataDemux(m_demux))
526                 {
527                         eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
528                         int sid = ref.getParentServiceID().get();
529                         if (!sid)
530                                 sid = ref.getServiceID().get();
531                         if ( ref.getParentTransportStreamID().get() &&
532                                 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
533                                 m_event_handler.startOther(m_demux, sid);
534                         else
535                                 m_event_handler.start(m_demux, sid);
536                 }
537                 break;
538         }
539         case eDVBServicePMTHandler::eventTuneFailed:
540         {
541                 eDebug("DVB service failed to tune");
542                 m_event((iPlayableService*)this, evTuneFailed);
543                 break;
544         }
545         case eDVBServicePMTHandler::eventNewProgramInfo:
546         {
547                 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
548                 if (m_timeshift_enabled)
549                         updateTimeshiftPids();
550                 if (!m_timeshift_active)
551                         updateDecoder();
552                 m_event((iPlayableService*)this, evUpdatedInfo);
553                 break;
554         }
555         case eDVBServicePMTHandler::eventEOF:
556         {
557                 m_event((iPlayableService*)this, evEnd);
558                 break;
559         }
560         }
561 }
562
563 void eDVBServicePlay::serviceEventTimeshift(int event)
564 {
565         switch (event)
566         {
567         case eDVBServicePMTHandler::eventNewProgramInfo:
568                 if (m_timeshift_active)
569                         updateDecoder();
570                 break;
571         case eDVBServicePMTHandler::eventEOF:
572                 switchToLive();
573                 break;
574         }
575 }
576
577 RESULT eDVBServicePlay::start()
578 {
579         int r;
580                 /* in pvr mode, we only want to use one demux. in tv mode, we're using 
581                    two (one for decoding, one for data source), as we must be prepared
582                    to start recording from the data demux. */
583         r = m_service_handler.tune((eServiceReferenceDVB&)m_reference, m_is_pvr);
584         m_event(this, evStart);
585         m_event((iPlayableService*)this, evSeekableStatusChanged);
586         return 0;
587 }
588
589 RESULT eDVBServicePlay::stop()
590 {
591         return 0;
592 }
593
594 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
595 {
596         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
597         return 0;
598 }
599
600 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
601 {
602                 /* note: we check for timeshift to be enabled,
603                    not neccessary active. if you pause when timeshift
604                    is not active, you should activate it when unpausing */
605         if ((!m_is_pvr) && (!m_timeshift_enabled))
606         {
607                 ptr = 0;
608                 return -1;
609         }
610
611         ptr = this;
612         return 0;
613 }
614
615 RESULT eDVBServicePlay::setSlowMotion(int ratio)
616 {
617         if (m_decoder)
618                 return m_decoder->setSlowMotion(ratio);
619         else
620                 return -1;
621 }
622
623 RESULT eDVBServicePlay::setFastForward(int ratio)
624 {
625         if (m_decoder)
626                 return m_decoder->setFastForward(ratio);
627         else
628                 return -1;
629 }
630     
631 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
632 {
633         if (m_is_pvr || m_timeshift_active)
634         {
635                 ptr = this;
636                 return 0;
637         }
638         
639         ptr = 0;
640         return -1;
641 }
642
643 RESULT eDVBServicePlay::getLength(pts_t &len)
644 {
645         ePtr<iDVBPVRChannel> pvr_channel;
646         
647         if (m_service_handler.getPVRChannel(pvr_channel))
648         {
649                 eDebug("getPVRChannel failed!");
650                 return -1;
651         }
652         
653         return pvr_channel->getLength(len);
654 }
655
656 RESULT eDVBServicePlay::pause()
657 {
658         if (!m_is_paused && m_decoder)
659         {
660                 m_is_paused = 1;
661                 return m_decoder->freeze(0);
662         } else
663                 return -1;
664 }
665
666 RESULT eDVBServicePlay::unpause()
667 {
668         if (m_is_paused && m_decoder)
669         {
670                 m_is_paused = 0;
671                 return m_decoder->unfreeze();
672         } else
673                 return -1;
674 }
675
676 RESULT eDVBServicePlay::seekTo(pts_t to)
677 {
678         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
679         
680         if (!m_decode_demux)
681                 return -1;
682
683         ePtr<iDVBPVRChannel> pvr_channel;
684         
685         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
686                 return -1;
687         
688         return pvr_channel->seekTo(m_decode_demux, 0, to);
689 }
690
691 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
692 {
693         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
694         
695         if (!m_decode_demux)
696                 return -1;
697
698         ePtr<iDVBPVRChannel> pvr_channel;
699         
700         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
701                 return -1;
702         
703         to *= direction;
704         
705         return pvr_channel->seekTo(m_decode_demux, 1, to);
706 }
707
708 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
709 {
710         ePtr<iDVBPVRChannel> pvr_channel;
711         
712         if (!m_decode_demux)
713                 return -1;
714         
715         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
716                 return -1;
717         
718         return pvr_channel->getCurrentPosition(m_decode_demux, pos, 1);
719 }
720
721 RESULT eDVBServicePlay::setTrickmode(int trick)
722 {
723         if (m_decoder)
724                 m_decoder->setTrickmode(trick);
725         return 0;
726 }
727
728 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
729 {
730         ptr = this;
731         return 0;
732 }
733
734 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
735 {
736         ptr = this;
737         return 0;
738 }
739
740 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
741 {
742         ptr = this;
743         return 0;
744 }
745
746 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
747 {
748         ptr = this;
749         return 0;
750 }
751
752 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
753 {
754         if (m_timeshift_enabled || !m_is_pvr)
755         {
756                 ptr = this;
757                 return 0;
758         }
759         ptr = 0;
760         return -1;
761 }
762
763 RESULT eDVBServicePlay::getName(std::string &name)
764 {
765         if (m_is_pvr)
766         {
767                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
768                 return i->getName(m_reference, name);
769         }
770         if (m_dvb_service)
771         {
772                 m_dvb_service->getName(m_reference, name);
773                 if (name.empty())
774                         name = "(...)";
775         }
776         else if (!m_reference.name.empty())
777                 eStaticServiceDVBInformation().getName(m_reference, name);
778         else
779                 name = "DVB service";
780         return 0;
781 }
782
783 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
784 {
785         return m_event_handler.getEvent(evt, nownext);
786 }
787
788 int eDVBServicePlay::getInfo(int w)
789 {
790         eDVBServicePMTHandler::program program;
791
792         if (m_service_handler.getProgramInfo(program))
793                 return -1;
794         
795         switch (w)
796         {
797         case sAspect:
798                 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
799                 {
800                         ePtr<eServiceEvent> evt;
801                         if (!m_event_handler.getEvent(evt, 0))
802                         {
803                                 ePtr<eComponentData> data;
804                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
805                                 {
806                                         if ( data->getStreamContent() == 1 )
807                                         {
808                                                 switch(data->getComponentType())
809                                                 {
810                                                         // SD
811                                                         case 1: // 4:3 SD PAL
812                                                         case 2:
813                                                         case 3: // 16:9 SD PAL
814                                                         case 4: // > 16:9 PAL
815                                                         case 5: // 4:3 SD NTSC
816                                                         case 6: 
817                                                         case 7: // 16:9 SD NTSC
818                                                         case 8: // > 16:9 NTSC
819
820                                                         // HD
821                                                         case 9: // 4:3 HD PAL
822                                                         case 0xA:
823                                                         case 0xB: // 16:9 HD PAL
824                                                         case 0xC: // > 16:9 HD PAL
825                                                         case 0xD: // 4:3 HD NTSC
826                                                         case 0xE:
827                                                         case 0xF: // 16:9 HD NTSC
828                                                         case 0x10: // > 16:9 HD PAL
829                                                                 return data->getComponentType();
830                                                 }
831                                         }
832                                 }
833                         }
834                 }
835                 return -1;
836         case sIsCrypted: return program.isCrypted;
837         case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
838         case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
839         case sPCRPID: return program.pcrPid;
840         case sPMTPID: return program.pmtPid;
841         case sTXTPID: return program.textPid;
842         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
843         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
844         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
845         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
846         case sProvider: if (!m_dvb_service) return -1; return -2;
847         default:
848                 return -1;
849         }
850 }
851
852 std::string eDVBServicePlay::getInfoString(int w)
853 {       
854         switch (w)
855         {
856         case sProvider:
857                 if (!m_dvb_service) return "";
858                 return m_dvb_service->m_provider_name;
859         default:
860                 return "";
861         }
862 }
863
864 int eDVBServicePlay::getNumberOfTracks()
865 {
866         eDVBServicePMTHandler::program program;
867         if (m_service_handler.getProgramInfo(program))
868                 return 0;
869         return program.audioStreams.size();
870 }
871
872 RESULT eDVBServicePlay::selectTrack(unsigned int i)
873 {
874         int ret = selectAudioStream(i);
875
876         if (m_decoder->start())
877                 return -5;
878
879         return ret;
880 }
881
882 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
883 {
884         eDVBServicePMTHandler::program program;
885
886         if (m_service_handler.getProgramInfo(program))
887                 return -1;
888         
889         if (i >= program.audioStreams.size())
890                 return -2;
891         
892         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
893                 info.m_description = "MPEG";
894         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
895                 info.m_description = "AC3";
896         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
897                 info.m_description = "DTS";
898         else
899                 info.m_description = "???";
900
901         if (program.audioStreams[i].component_tag != -1)
902         {
903                 ePtr<eServiceEvent> evt;
904                 if (!m_event_handler.getEvent(evt, 0))
905                 {
906                         ePtr<eComponentData> data;
907                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
908                                 info.m_language = data->getText();
909                 }
910         }
911
912         if (info.m_language.empty())
913                 info.m_language = program.audioStreams[i].language_code;
914         
915         return 0;
916 }
917
918 int eDVBServicePlay::selectAudioStream(int i)
919 {
920         eDVBServicePMTHandler::program program;
921
922         if (m_service_handler.getProgramInfo(program))
923                 return -1;
924         
925         if ((unsigned int)i >= program.audioStreams.size())
926                 return -2;
927         
928         if (!m_decoder)
929                 return -3;
930         
931         if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
932                 return -4;
933
934         if (m_dvb_service && !m_is_pvr)
935         {
936                 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
937                 {
938                         m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
939                         m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
940                 }       else
941                 {
942                         m_dvb_service->setCachePID(eDVBService::cAPID, -1);
943                         m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
944                 }
945         }
946
947         m_current_audio_stream = i;
948
949         return 0;
950 }
951
952 int eDVBServicePlay::getFrontendInfo(int w)
953 {
954         if (m_is_pvr)
955                 return 0;
956         eUsePtr<iDVBChannel> channel;
957         if(m_service_handler.getChannel(channel))
958                 return 0;
959         ePtr<iDVBFrontend> fe;
960         if(channel->getFrontend(fe))
961                 return 0;
962         return fe->readFrontendData(w);
963 }
964
965 int eDVBServicePlay::getNumberOfSubservices()
966 {
967         ePtr<eServiceEvent> evt;
968         if (!m_event_handler.getEvent(evt, 0))
969                 return evt->getNumOfLinkageServices();
970         return 0;
971 }
972
973 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
974 {
975         ePtr<eServiceEvent> evt;
976         if (!m_event_handler.getEvent(evt, 0))
977         {
978                 if (!evt->getLinkageService(sub, m_reference, n))
979                         return 0;
980         }
981         sub.type=eServiceReference::idInvalid;
982         return -1;
983 }
984
985 RESULT eDVBServicePlay::startTimeshift()
986 {
987         ePtr<iDVBDemux> demux;
988         
989         eDebug("Start timeshift!");
990         
991         if (m_timeshift_enabled)
992                 return -1;
993         
994                 /* start recording with the data demux. */
995         if (m_service_handler.getDataDemux(demux))
996                 return -2;
997
998         demux->createTSRecorder(m_record);
999         if (!m_record)
1000                 return -3;
1001
1002         char templ[]="/media/hdd/timeshift.XXXXXX";
1003         m_timeshift_fd = mkstemp(templ);
1004         m_timeshift_file = templ;
1005         
1006         eDebug("recording to %s", templ);
1007         
1008         if (m_timeshift_fd < 0)
1009         {
1010                 m_record = 0;
1011                 return -4;
1012         }
1013                 
1014         m_record->setTargetFD(m_timeshift_fd);
1015
1016         m_timeshift_enabled = 1;
1017         
1018         updateTimeshiftPids();
1019         m_record->start();
1020
1021         return 0;
1022 }
1023
1024 RESULT eDVBServicePlay::stopTimeshift()
1025 {
1026         if (!m_timeshift_enabled)
1027                 return -1;
1028         
1029         switchToLive();
1030         
1031         m_timeshift_enabled = 0;
1032         
1033         m_record->stop();
1034         m_record = 0;
1035         
1036         close(m_timeshift_fd);
1037         remove(m_timeshift_file.c_str());
1038         
1039         return 0;
1040 }
1041
1042 int eDVBServicePlay::isTimeshiftActive()
1043 {
1044         return m_timeshift_enabled && m_timeshift_active;
1045 }
1046
1047 RESULT eDVBServicePlay::activateTimeshift()
1048 {
1049         if (!m_timeshift_enabled)
1050                 return -1;
1051         
1052         if (!m_timeshift_active)
1053         {
1054                 switchToTimeshift();
1055                 return 0;
1056         }
1057         
1058         return -2;
1059 }
1060
1061 void eDVBServicePlay::updateTimeshiftPids()
1062 {
1063         if (!m_record)
1064                 return;
1065         
1066         eDVBServicePMTHandler::program program;
1067         if (m_service_handler.getProgramInfo(program))
1068                 return;
1069         else
1070         {
1071                 std::set<int> pids_to_record;
1072                 pids_to_record.insert(0); // PAT
1073                 if (program.pmtPid != -1)
1074                         pids_to_record.insert(program.pmtPid); // PMT
1075
1076                 if (program.textPid != -1)
1077                         pids_to_record.insert(program.textPid); // Videotext
1078
1079                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1080                         i(program.videoStreams.begin()); 
1081                         i != program.videoStreams.end(); ++i)
1082                         pids_to_record.insert(i->pid);
1083
1084                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1085                         i(program.audioStreams.begin()); 
1086                         i != program.audioStreams.end(); ++i)
1087                                 pids_to_record.insert(i->pid);
1088
1089                 std::set<int> new_pids, obsolete_pids;
1090                 
1091                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
1092                                 m_pids_active.begin(), m_pids_active.end(),
1093                                 std::inserter(new_pids, new_pids.begin()));
1094                 
1095                 std::set_difference(
1096                                 m_pids_active.begin(), m_pids_active.end(),
1097                                 pids_to_record.begin(), pids_to_record.end(), 
1098                                 std::inserter(new_pids, new_pids.begin())
1099                                 );
1100
1101                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1102                         m_record->addPID(*i);
1103
1104                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1105                         m_record->removePID(*i);
1106         }
1107 }
1108
1109 void eDVBServicePlay::switchToLive()
1110 {
1111         if (!m_timeshift_active)
1112                 return;
1113         
1114         m_decoder = 0;
1115         m_decode_demux = 0;
1116                 /* free the timeshift service handler, we need the resources */
1117         m_service_handler_timeshift.free();
1118         m_timeshift_active = 0;
1119         
1120         m_event((iPlayableService*)this, evSeekableStatusChanged);
1121         
1122         updateDecoder();
1123 }
1124
1125 void eDVBServicePlay::switchToTimeshift()
1126 {
1127         if (m_timeshift_active)
1128                 return;
1129         
1130         m_decode_demux = 0;
1131         m_decoder = 0;
1132         
1133         m_timeshift_active = 1;
1134
1135         m_event((iPlayableService*)this, evSeekableStatusChanged);
1136         
1137         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1138         r.path = m_timeshift_file;
1139         
1140         m_service_handler_timeshift.tune(r, 1); /* use the decoder demux for everything */
1141 }
1142
1143 void eDVBServicePlay::updateDecoder()
1144 {
1145         int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
1146         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1147
1148         eDVBServicePMTHandler::program program;
1149         if (h.getProgramInfo(program))
1150                 eDebug("getting program info failed.");
1151         else
1152         {
1153                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1154                 if (!program.videoStreams.empty())
1155                 {
1156                         eDebugNoNewLine(" (");
1157                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1158                                 i(program.videoStreams.begin()); 
1159                                 i != program.videoStreams.end(); ++i)
1160                         {
1161                                 if (vpid == -1)
1162                                         vpid = i->pid;
1163                                 if (i != program.videoStreams.begin())
1164                                         eDebugNoNewLine(", ");
1165                                 eDebugNoNewLine("%04x", i->pid);
1166                         }
1167                         eDebugNoNewLine(")");
1168                 }
1169                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1170                 if (!program.audioStreams.empty())
1171                 {
1172                         eDebugNoNewLine(" (");
1173                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1174                                 i(program.audioStreams.begin()); 
1175                                 i != program.audioStreams.end(); ++i)
1176                         {
1177                                 if (apid == -1)
1178                                 {
1179                                         apid = i->pid;
1180                                         apidtype = i->type;
1181                                 }
1182                                 if (i != program.audioStreams.begin())
1183                                         eDebugNoNewLine(", ");
1184                                 eDebugNoNewLine("%04x", i->pid);
1185                         }
1186                         eDebugNoNewLine(")");
1187                 }
1188                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1189                 pcrpid = program.pcrPid;
1190                 eDebug(", and the text pid is %04x", program.textPid);
1191                 tpid = program.textPid;
1192         }
1193
1194         if (!m_decoder)
1195         {
1196                 h.getDecodeDemux(m_decode_demux);
1197                 if (m_decode_demux)
1198                         m_decode_demux->getMPEGDecoder(m_decoder);
1199         }
1200
1201         if (m_decoder)
1202         {
1203                 m_decoder->setVideoPID(vpid);
1204                 m_current_audio_stream = 0;
1205                 m_decoder->setAudioPID(apid, apidtype);
1206                 if (!(m_is_pvr || m_timeshift_active))
1207                         m_decoder->setSyncPCR(pcrpid);
1208                 else
1209                         m_decoder->setSyncPCR(-1);
1210                 m_decoder->setTextPID(tpid);
1211                 m_decoder->start();
1212 // how we can do this better?
1213 // update cache pid when the user changed the audio track or video track
1214 // TODO handling of difference audio types.. default audio types..
1215                                 
1216                 /* don't worry about non-existing services, nor pvr services */
1217                 if (m_dvb_service && !m_is_pvr)
1218                 {
1219                         if (apidtype == eDVBAudio::aMPEG)
1220                         {
1221                                 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
1222                                 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1223                         }
1224                         else
1225                         {
1226                                 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1227                                 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
1228                         }
1229                         m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
1230                         m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
1231                         m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
1232                 }
1233         }
1234 }
1235
1236 DEFINE_REF(eDVBServicePlay)
1237
1238 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");