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