1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
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 #include <lib/base/nconfig.h> // access to python config
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
21 #include <lib/gui/esubtitle.h>
26 #include <netinet/in.h>
28 #include <dvbsi++/event_information_section.h>
30 #define INTERNAL_TELETEXT
33 #error no byte order defined!
36 #define TSPATH "/media/hdd"
38 class eStaticServiceDVBInformation: public iStaticServiceInformation
40 DECLARE_REF(eStaticServiceDVBInformation);
42 RESULT getName(const eServiceReference &ref, std::string &name);
43 int getLength(const eServiceReference &ref);
46 DEFINE_REF(eStaticServiceDVBInformation);
48 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
50 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
51 if ( !ref.name.empty() )
53 if (service.getParentTransportStreamID().get()) // linkage subservice
55 ePtr<iServiceHandler> service_center;
56 if (!eServiceCenter::getInstance(service_center))
58 eServiceReferenceDVB parent = service;
59 parent.setTransportStreamID( service.getParentTransportStreamID() );
60 parent.setServiceID( service.getParentServiceID() );
61 parent.setParentTransportStreamID(eTransportStreamID(0));
62 parent.setParentServiceID(eServiceID(0));
64 ePtr<iStaticServiceInformation> service_info;
65 if (!service_center->info(parent, service_info))
67 if (!service_info->getName(parent, name))
69 // just show short name
70 unsigned int pos = name.find("\xc2\x86");
71 if ( pos != std::string::npos )
73 pos = name.find("\xc2\x87");
74 if ( pos != std::string::npos )
90 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
95 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
97 DECLARE_REF(eStaticServiceDVBBouquetInformation);
99 RESULT getName(const eServiceReference &ref, std::string &name);
100 int getLength(const eServiceReference &ref);
103 DEFINE_REF(eStaticServiceDVBBouquetInformation);
105 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
107 ePtr<iDVBChannelList> db;
108 ePtr<eDVBResourceManager> res;
111 if ((err = eDVBResourceManager::getInstance(res)) != 0)
113 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
116 if ((err = res->getChannelList(db)) != 0)
118 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
123 if ((err = db->getBouquet(ref, bouquet)) != 0)
125 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
129 if ( bouquet && bouquet->m_bouquet_name.length() )
131 name = bouquet->m_bouquet_name;
138 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
143 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
145 DECLARE_REF(eStaticServiceDVBPVRInformation);
146 eServiceReference m_ref;
147 eDVBMetaParser m_parser;
149 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
150 RESULT getName(const eServiceReference &ref, std::string &name);
151 int getLength(const eServiceReference &ref);
153 int getInfo(const eServiceReference &ref, int w);
154 std::string getInfoString(const eServiceReference &ref,int w);
157 DEFINE_REF(eStaticServiceDVBPVRInformation);
159 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
162 m_parser.parseFile(ref.path);
165 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
167 ASSERT(ref == m_ref);
168 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
172 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
174 ASSERT(ref == m_ref);
178 if (tstools.openFile(ref.path.c_str()))
182 if (tstools.calcLen(len))
188 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
192 case iServiceInformation::sDescription:
193 return iServiceInformation::resIsString;
194 case iServiceInformation::sServiceref:
195 return iServiceInformation::resIsString;
196 case iServiceInformation::sTimeCreate:
197 if (m_parser.m_time_create)
198 return m_parser.m_time_create;
200 return iServiceInformation::resNA;
202 return iServiceInformation::resNA;
206 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
210 case iServiceInformation::sDescription:
211 return m_parser.m_description;
212 case iServiceInformation::sServiceref:
213 return m_parser.m_ref.toString();
219 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
221 DECLARE_REF(eDVBPVRServiceOfflineOperations);
222 eServiceReferenceDVB m_ref;
224 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
226 RESULT deleteFromDisk(int simulate);
227 RESULT getListOfFilenames(std::list<std::string> &);
230 DEFINE_REF(eDVBPVRServiceOfflineOperations);
232 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
236 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
242 std::list<std::string> res;
243 if (getListOfFilenames(res))
246 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
248 eDebug("FATAL !! can't get background file eraser");
250 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
252 eDebug("Removing %s...", i->c_str());
254 eraser->erase(i->c_str());
256 ::unlink(i->c_str());
263 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
266 res.push_back(m_ref.path);
268 // handling for old splitted recordings (enigma 1)
273 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
275 if (stat(buf, &s) < 0)
280 res.push_back(m_ref.path + ".meta");
281 res.push_back(m_ref.path + ".ap");
282 res.push_back(m_ref.path + ".cuts");
283 std::string tmp = m_ref.path;
284 tmp.erase(m_ref.path.length()-3);
285 res.push_back(tmp + ".eit");
289 DEFINE_REF(eServiceFactoryDVB)
291 eServiceFactoryDVB::eServiceFactoryDVB()
293 ePtr<eServiceCenter> sc;
295 eServiceCenter::getPrivInstance(sc);
297 sc->addServiceFactory(eServiceFactoryDVB::id, this);
300 eServiceFactoryDVB::~eServiceFactoryDVB()
302 ePtr<eServiceCenter> sc;
304 eServiceCenter::getPrivInstance(sc);
306 sc->removeServiceFactory(eServiceFactoryDVB::id);
309 DEFINE_REF(eDVBServiceList);
311 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
315 eDVBServiceList::~eDVBServiceList()
319 RESULT eDVBServiceList::startQuery()
321 ePtr<iDVBChannelList> db;
322 ePtr<eDVBResourceManager> res;
325 if ((err = eDVBResourceManager::getInstance(res)) != 0)
327 eDebug("no resource manager");
330 if ((err = res->getChannelList(db)) != 0)
332 eDebug("no channel list");
336 ePtr<eDVBChannelQuery> q;
338 if (!m_parent.path.empty())
340 eDVBChannelQuery::compile(q, m_parent.path);
343 eDebug("compile query failed");
348 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
350 eDebug("startQuery failed");
357 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
359 eServiceReferenceDVB ref;
364 while (!m_query->getNextResult(ref))
368 list.sort(iListableServiceCompare(this));
373 // The first argument of this function is a format string to specify the order and
374 // the content of the returned list
375 // useable format options are
376 // R = Service Reference (as swig object .. this is very slow)
377 // S = Service Reference (as python string object .. same as ref.toString())
378 // N = Service Name (as python string object)
379 // when exactly one return value per service is selected in the format string,
380 // then each value is directly a list entry
381 // when more than one value is returned per service, then the list is a list of
383 // unknown format string chars are returned as python None values !
384 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
387 std::list<eServiceReference> tmplist;
390 if (!format || !(retcount=strlen(format)))
391 format = "R"; // just return service reference swig object ...
393 if (!getContent(tmplist, sorted))
395 int services=tmplist.size();
396 ePtr<iStaticServiceInformation> sptr;
397 eServiceCenterPtr service_center;
399 if (strchr(format, 'N'))
400 eServiceCenter::getPrivInstance(service_center);
402 ret = PyList_New(services);
403 std::list<eServiceReference>::iterator it(tmplist.begin());
405 for (int cnt=0; cnt < services; ++cnt)
407 eServiceReference &ref=*it++;
408 PyObject *tuple = retcount > 1 ? PyTuple_New(retcount) : 0;
409 for (int i=0; i < retcount; ++i)
414 case 'R': // service reference (swig)object
415 tmp = New_eServiceReference(ref);
417 case 'S': // service reference string
418 tmp = PyString_FromString(ref.toString().c_str());
420 case 'N': // service name
423 service_center->info(ref, sptr);
427 sptr->getName(ref, name);
429 tmp = PyString_FromString(name.c_str());
433 tmp = PyString_FromString("<n/a>");
446 PyTuple_SET_ITEM(tuple, i, tmp);
448 PyList_SET_ITEM(ret, cnt, tmp);
452 PyList_SET_ITEM(ret, cnt, tuple);
455 return ret ? ret : PyList_New(0);
458 RESULT eDVBServiceList::getNext(eServiceReference &ref)
463 return m_query->getNextResult((eServiceReferenceDVB&)ref);
466 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
468 return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
471 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
473 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
475 ePtr<iDVBChannelList> db;
476 ePtr<eDVBResourceManager> resm;
478 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
481 if (db->getBouquet(m_parent, m_bouquet) != 0)
492 RESULT eDVBServiceList::addService(eServiceReference &ref)
496 return m_bouquet->addService(ref);
499 RESULT eDVBServiceList::removeService(eServiceReference &ref)
503 return m_bouquet->removeService(ref);
506 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
510 return m_bouquet->moveService(ref, pos);
513 RESULT eDVBServiceList::flushChanges()
517 return m_bouquet->flushChanges();
520 RESULT eDVBServiceList::setListName(const std::string &name)
524 return m_bouquet->setListName(name);
527 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
529 ePtr<eDVBService> service;
530 int r = lookupService(service, ref);
533 // check resources...
534 ptr = new eDVBServicePlay(ref, service);
538 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
540 if (ref.path.empty())
542 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
551 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
553 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
554 if (list->startQuery())
564 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
566 /* is a listable service? */
567 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
569 if ( !ref.name.empty() ) // satellites or providers list
570 ptr = new eStaticServiceDVBInformation;
571 else // a dvb bouquet
572 ptr = new eStaticServiceDVBBouquetInformation;
574 else if (!ref.path.empty()) /* do we have a PVR service? */
575 ptr = new eStaticServiceDVBPVRInformation(ref);
576 else // normal dvb service
578 ePtr<eDVBService> service;
579 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
580 ptr = new eStaticServiceDVBInformation;
582 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
588 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
590 if (ref.path.empty())
596 ptr = new eDVBPVRServiceOfflineOperations(ref);
601 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
603 // TODO: handle the listing itself
604 // if (ref.... == -1) .. return "... bouquets ...";
605 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
607 ePtr<iDVBChannelList> db;
608 ePtr<eDVBResourceManager> res;
611 if ((err = eDVBResourceManager::getInstance(res)) != 0)
613 eDebug("no resource manager");
616 if ((err = res->getChannelList(db)) != 0)
618 eDebug("no channel list");
622 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
623 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
625 eDebug("getService failed!");
632 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
633 m_reference(ref), m_dvb_service(service), m_is_paused(0)
636 m_is_pvr = !m_reference.path.empty();
638 m_timeshift_enabled = m_timeshift_active = 0;
641 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
642 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
643 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
645 m_cuesheet_changed = 0;
646 m_cutlist_enabled = 1;
648 m_subtitle_widget = 0;
650 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
653 eDVBServicePlay::~eDVBServicePlay()
655 delete m_subtitle_widget;
658 void eDVBServicePlay::gotNewEvent()
662 ePtr<eServiceEvent> m_event_now, m_event_next;
663 getEvent(m_event_now, 0);
664 getEvent(m_event_next, 1);
667 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
669 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
671 m_event((iPlayableService*)this, evUpdatedEventInfo);
674 void eDVBServicePlay::serviceEvent(int event)
678 case eDVBServicePMTHandler::eventTuned:
680 ePtr<iDVBDemux> m_demux;
681 if (!m_service_handler.getDataDemux(m_demux))
683 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
684 int sid = ref.getParentServiceID().get();
686 sid = ref.getServiceID().get();
687 if ( ref.getParentTransportStreamID().get() &&
688 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
689 m_event_handler.startOther(m_demux, sid);
691 m_event_handler.start(m_demux, sid);
695 case eDVBServicePMTHandler::eventTuneFailed:
697 eDebug("DVB service failed to tune");
698 m_event((iPlayableService*)this, evTuneFailed);
701 case eDVBServicePMTHandler::eventNewProgramInfo:
703 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
704 if (m_timeshift_enabled)
705 updateTimeshiftPids();
706 if (!m_timeshift_active)
708 if (m_first_program_info && m_is_pvr)
710 m_first_program_info = 0;
713 m_event((iPlayableService*)this, evUpdatedInfo);
716 case eDVBServicePMTHandler::eventEOF:
717 m_event((iPlayableService*)this, evEOF);
719 case eDVBServicePMTHandler::eventSOF:
720 m_event((iPlayableService*)this, evSOF);
725 void eDVBServicePlay::serviceEventTimeshift(int event)
729 case eDVBServicePMTHandler::eventNewProgramInfo:
730 if (m_timeshift_active)
733 case eDVBServicePMTHandler::eventSOF:
734 m_event((iPlayableService*)this, evSOF);
736 case eDVBServicePMTHandler::eventEOF:
742 RESULT eDVBServicePlay::start()
745 /* in pvr mode, we only want to use one demux. in tv mode, we're using
746 two (one for decoding, one for data source), as we must be prepared
747 to start recording from the data demux. */
749 m_cue = new eCueSheet();
751 m_first_program_info = 1;
752 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
753 r = m_service_handler.tune(service, m_is_pvr, m_cue);
755 /* inject EIT if there is a stored one */
758 std::string filename = service.path;
759 filename.erase(filename.length()-2, 2);
761 int fd = ::open( filename.c_str(), O_RDONLY );
765 int rd = ::read(fd, buf, 4096);
767 if ( rd > 12 /*EIT_LOOP_SIZE*/ )
770 ePtr<eServiceEvent> event = new eServiceEvent;
771 ePtr<eServiceEvent> empty;
772 event->parseFrom(&ev, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get());
773 m_event_handler.inject(event, 0);
774 m_event_handler.inject(empty, 1);
783 m_event(this, evStart);
784 m_event((iPlayableService*)this, evSeekableStatusChanged);
788 RESULT eDVBServicePlay::stop()
790 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
792 m_service_handler_timeshift.free();
793 m_service_handler.free();
795 if (m_is_pvr && m_cuesheet_changed)
801 RESULT eDVBServicePlay::setTarget(int target)
803 m_is_primary = !target;
807 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
809 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
813 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
815 /* note: we check for timeshift to be enabled,
816 not neccessary active. if you pause when timeshift
817 is not active, you should activate it when unpausing */
818 if ((!m_is_pvr) && (!m_timeshift_enabled))
828 RESULT eDVBServicePlay::setSlowMotion(int ratio)
831 return m_decoder->setSlowMotion(ratio);
836 RESULT eDVBServicePlay::setFastForward(int ratio)
838 int skipmode, ffratio;
844 } else if (ratio > 0)
852 } else // if (ratio < 0)
858 if (m_skipmode != skipmode)
860 eDebug("setting cue skipmode to %d", skipmode);
862 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
865 m_skipmode = skipmode;
870 return m_decoder->setFastForward(ffratio);
873 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
875 if (m_is_pvr || m_timeshift_enabled)
885 /* TODO: when timeshift is enabled but not active, this doesn't work. */
886 RESULT eDVBServicePlay::getLength(pts_t &len)
888 ePtr<iDVBPVRChannel> pvr_channel;
890 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
893 return pvr_channel->getLength(len);
896 RESULT eDVBServicePlay::pause()
898 if (!m_is_paused && m_decoder)
901 return m_decoder->freeze(0);
906 RESULT eDVBServicePlay::unpause()
908 if (m_is_paused && m_decoder)
911 return m_decoder->unfreeze();
916 RESULT eDVBServicePlay::seekTo(pts_t to)
918 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
923 ePtr<iDVBPVRChannel> pvr_channel;
925 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
931 m_cue->seekTo(0, to);
935 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
937 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
942 ePtr<iDVBPVRChannel> pvr_channel;
944 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
949 /* HACK until we have skip-AP api */
950 if ((to > 0) && (to < 100))
958 m_cue->seekTo(mode, to);
962 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
964 ePtr<iDVBPVRChannel> pvr_channel;
969 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
974 /* if there is a decoder, use audio or video PTS */
977 r = m_decoder->getPTS(0, pos);
983 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
986 RESULT eDVBServicePlay::setTrickmode(int trick)
989 m_decoder->setTrickmode(trick);
993 RESULT eDVBServicePlay::isCurrentlySeekable()
995 return m_is_pvr || m_timeshift_active;
998 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1004 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1010 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1016 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1022 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1028 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1031 if (m_timeshift_enabled || !m_is_pvr)
1033 if (!m_timeshift_enabled)
1035 /* we need enough diskspace */
1037 if (statfs(TSPATH "/.", &fs) < 0)
1039 eDebug("statfs failed!");
1043 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1045 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1055 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1066 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1072 RESULT eDVBServicePlay::getName(std::string &name)
1076 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1077 return i->getName(m_reference, name);
1081 m_dvb_service->getName(m_reference, name);
1085 else if (!m_reference.name.empty())
1086 eStaticServiceDVBInformation().getName(m_reference, name);
1088 name = "DVB service";
1092 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1094 return m_event_handler.getEvent(evt, nownext);
1097 int eDVBServicePlay::getInfo(int w)
1099 eDVBServicePMTHandler::program program;
1102 return resIsPyObject;
1104 if (m_service_handler.getProgramInfo(program))
1110 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1112 ePtr<eServiceEvent> evt;
1113 if (!m_event_handler.getEvent(evt, 0))
1115 ePtr<eComponentData> data;
1116 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1118 if ( data->getStreamContent() == 1 )
1120 switch(data->getComponentType())
1123 case 1: // 4:3 SD PAL
1125 case 3: // 16:9 SD PAL
1126 case 4: // > 16:9 PAL
1127 case 5: // 4:3 SD NTSC
1129 case 7: // 16:9 SD NTSC
1130 case 8: // > 16:9 NTSC
1133 case 9: // 4:3 HD PAL
1135 case 0xB: // 16:9 HD PAL
1136 case 0xC: // > 16:9 HD PAL
1137 case 0xD: // 4:3 HD NTSC
1139 case 0xF: // 16:9 HD NTSC
1140 case 0x10: // > 16:9 HD PAL
1141 return data->getComponentType();
1148 case sIsCrypted: return program.isCrypted();
1149 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1150 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1151 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
1152 case sPCRPID: return program.pcrPid;
1153 case sPMTPID: return program.pmtPid;
1154 case sTXTPID: return program.textPid;
1155 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1156 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1157 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1158 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1159 case sProvider: if (!m_dvb_service) return -1; return -2;
1165 std::string eDVBServicePlay::getInfoString(int w)
1170 if (!m_dvb_service) return "";
1171 return m_dvb_service->m_provider_name;
1175 return iServiceInformation::getInfoString(w);
1178 PyObject *eDVBServicePlay::getInfoObject(int w)
1183 return m_service_handler.getCaIds();
1187 return iServiceInformation::getInfoObject(w);
1190 int eDVBServicePlay::getNumberOfTracks()
1192 eDVBServicePMTHandler::program program;
1193 if (m_service_handler.getProgramInfo(program))
1195 return program.audioStreams.size();
1198 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1200 int ret = selectAudioStream(i);
1202 if (m_decoder->start())
1208 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1210 eDVBServicePMTHandler::program program;
1212 if (m_service_handler.getProgramInfo(program))
1215 if (i >= program.audioStreams.size())
1218 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1219 info.m_description = "MPEG";
1220 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1221 info.m_description = "AC3";
1222 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1223 info.m_description = "AAC";
1224 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1225 info.m_description = "DTS";
1227 info.m_description = "???";
1229 if (program.audioStreams[i].component_tag != -1)
1231 ePtr<eServiceEvent> evt;
1232 if (!m_event_handler.getEvent(evt, 0))
1234 ePtr<eComponentData> data;
1235 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1236 info.m_language = data->getText();
1240 if (info.m_language.empty())
1241 info.m_language = program.audioStreams[i].language_code;
1246 int eDVBServicePlay::selectAudioStream(int i)
1248 eDVBServicePMTHandler::program program;
1250 if (m_service_handler.getProgramInfo(program))
1253 if ((unsigned int)i >= program.audioStreams.size())
1259 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1262 if (m_dvb_service && !m_is_pvr)
1264 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1266 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1267 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1270 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1271 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1275 m_current_audio_stream = i;
1280 int eDVBServicePlay::getCurrentChannel()
1282 int curChannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1283 return curChannel == -1 ? STEREO : curChannel;
1286 RESULT eDVBServicePlay::selectChannel(int i)
1288 if (i < iAudioChannelSelection::LEFT || i > iAudioChannelSelection::RIGHT)
1290 if (m_dvb_service->getCacheEntry(eDVBService::cACHANNEL) != i)
1292 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1294 m_decoder->setAudioChannel(i);
1299 int eDVBServiceBase::getFrontendInfo(int w)
1301 eUsePtr<iDVBChannel> channel;
1302 if(m_service_handler.getChannel(channel))
1304 ePtr<iDVBFrontend> fe;
1305 if(channel->getFrontend(fe))
1307 return fe->readFrontendData(w);
1310 PyObject *eDVBServiceBase::getFrontendData(bool original)
1314 eUsePtr<iDVBChannel> channel;
1315 if(!m_service_handler.getChannel(channel))
1317 ePtr<iDVBFrontend> fe;
1318 if(!channel->getFrontend(fe))
1320 ret = fe->readTransponderData(original);
1323 ePtr<iDVBFrontendParameters> feparm;
1324 channel->getCurrentFrontendParameters(feparm);
1327 eDVBFrontendParametersSatellite osat;
1328 if (!feparm->getDVBS(osat))
1330 void PutToDict(PyObject *, const char*, long);
1331 void PutToDict(PyObject *, const char*, const char*);
1332 PutToDict(ret, "orbital_position", osat.orbital_position);
1333 const char *tmp = "UNKNOWN";
1334 switch(osat.polarisation)
1336 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1337 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1338 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1339 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1342 PutToDict(ret, "polarization", tmp);
1356 int eDVBServicePlay::getNumberOfSubservices()
1358 ePtr<eServiceEvent> evt;
1359 if (!m_event_handler.getEvent(evt, 0))
1360 return evt->getNumOfLinkageServices();
1364 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1366 ePtr<eServiceEvent> evt;
1367 if (!m_event_handler.getEvent(evt, 0))
1369 if (!evt->getLinkageService(sub, m_reference, n))
1372 sub.type=eServiceReference::idInvalid;
1376 RESULT eDVBServicePlay::startTimeshift()
1378 ePtr<iDVBDemux> demux;
1380 eDebug("Start timeshift!");
1382 if (m_timeshift_enabled)
1385 /* start recording with the data demux. */
1386 if (m_service_handler.getDataDemux(demux))
1389 demux->createTSRecorder(m_record);
1393 char templ[]=TSPATH "/timeshift.XXXXXX";
1394 m_timeshift_fd = mkstemp(templ);
1395 m_timeshift_file = templ;
1397 eDebug("recording to %s", templ);
1399 if (m_timeshift_fd < 0)
1405 m_record->setTargetFD(m_timeshift_fd);
1407 m_timeshift_enabled = 1;
1409 updateTimeshiftPids();
1415 RESULT eDVBServicePlay::stopTimeshift()
1417 if (!m_timeshift_enabled)
1422 m_timeshift_enabled = 0;
1427 close(m_timeshift_fd);
1428 eDebug("remove timeshift file");
1429 remove(m_timeshift_file.c_str());
1434 int eDVBServicePlay::isTimeshiftActive()
1436 return m_timeshift_enabled && m_timeshift_active;
1439 RESULT eDVBServicePlay::activateTimeshift()
1441 if (!m_timeshift_enabled)
1444 if (!m_timeshift_active)
1446 switchToTimeshift();
1453 PyObject *eDVBServicePlay::getCutList()
1455 PyObject *list = PyList_New(0);
1457 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1459 PyObject *tuple = PyTuple_New(2);
1460 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1461 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1462 PyList_Append(list, tuple);
1469 void eDVBServicePlay::setCutList(PyObject *list)
1471 if (!PyList_Check(list))
1473 int size = PyList_Size(list);
1476 m_cue_entries.clear();
1478 for (i=0; i<size; ++i)
1480 PyObject *tuple = PyList_GetItem(list, i);
1481 if (!PyTuple_Check(tuple))
1483 eDebug("non-tuple in cutlist");
1486 if (PyTuple_Size(tuple) != 2)
1488 eDebug("cutlist entries need to be a 2-tuple");
1491 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1492 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1494 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1497 pts_t pts = PyLong_AsLongLong(ppts);
1498 int type = PyInt_AsLong(ptype);
1499 m_cue_entries.insert(cueEntry(pts, type));
1500 eDebug("adding %08llx, %d", pts, type);
1502 m_cuesheet_changed = 1;
1504 cutlistToCuesheet();
1505 m_event((iPlayableService*)this, evCuesheetChanged);
1508 void eDVBServicePlay::setCutListEnable(int enable)
1510 m_cutlist_enabled = enable;
1511 cutlistToCuesheet();
1514 void eDVBServicePlay::updateTimeshiftPids()
1519 eDVBServicePMTHandler::program program;
1520 if (m_service_handler.getProgramInfo(program))
1524 std::set<int> pids_to_record;
1525 pids_to_record.insert(0); // PAT
1526 if (program.pmtPid != -1)
1527 pids_to_record.insert(program.pmtPid); // PMT
1529 if (program.textPid != -1)
1530 pids_to_record.insert(program.textPid); // Videotext
1532 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1533 i(program.videoStreams.begin());
1534 i != program.videoStreams.end(); ++i)
1535 pids_to_record.insert(i->pid);
1537 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1538 i(program.audioStreams.begin());
1539 i != program.audioStreams.end(); ++i)
1540 pids_to_record.insert(i->pid);
1542 std::set<int> new_pids, obsolete_pids;
1544 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1545 m_pids_active.begin(), m_pids_active.end(),
1546 std::inserter(new_pids, new_pids.begin()));
1548 std::set_difference(
1549 m_pids_active.begin(), m_pids_active.end(),
1550 pids_to_record.begin(), pids_to_record.end(),
1551 std::inserter(new_pids, new_pids.begin())
1554 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1555 m_record->addPID(*i);
1557 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1558 m_record->removePID(*i);
1562 void eDVBServicePlay::switchToLive()
1564 if (!m_timeshift_active)
1570 m_teletext_parser = 0;
1572 /* free the timeshift service handler, we need the resources */
1573 m_service_handler_timeshift.free();
1574 m_timeshift_active = 0;
1576 m_event((iPlayableService*)this, evSeekableStatusChanged);
1581 void eDVBServicePlay::switchToTimeshift()
1583 if (m_timeshift_active)
1588 m_teletext_parser = 0;
1590 m_timeshift_active = 1;
1592 m_event((iPlayableService*)this, evSeekableStatusChanged);
1594 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1595 r.path = m_timeshift_file;
1597 m_cue = new eCueSheet();
1598 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1599 updateDecoder(); /* mainly to switch off PCR */
1602 void eDVBServicePlay::updateDecoder()
1604 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1;
1605 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1607 bool defaultac3=false;
1608 std::string default_ac3;
1610 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1611 defaultac3 = default_ac3 == "enable";
1613 eDVBServicePMTHandler::program program;
1614 if (h.getProgramInfo(program))
1615 eDebug("getting program info failed.");
1618 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1619 if (!program.videoStreams.empty())
1621 eDebugNoNewLine(" (");
1622 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1623 i(program.videoStreams.begin());
1624 i != program.videoStreams.end(); ++i)
1631 if (i != program.videoStreams.begin())
1632 eDebugNoNewLine(", ");
1633 eDebugNoNewLine("%04x", i->pid);
1635 eDebugNoNewLine(")");
1637 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1638 if (!program.audioStreams.empty())
1640 eDebugNoNewLine(" (");
1641 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1642 i(program.audioStreams.begin());
1643 i != program.audioStreams.end(); ++i)
1645 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1647 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1653 if (i != program.audioStreams.begin())
1654 eDebugNoNewLine(", ");
1655 eDebugNoNewLine("%04x", i->pid);
1657 eDebugNoNewLine(")");
1659 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1660 pcrpid = program.pcrPid;
1661 eDebug(", and the text pid is %04x", program.textPid);
1662 tpid = program.textPid;
1663 achannel = program.audioChannel;
1668 h.getDecodeDemux(m_decode_demux);
1670 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1672 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1673 #ifdef INTERNAL_TELETEXT
1674 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1675 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1681 m_decoder->setVideoPID(vpid, vpidtype);
1682 m_current_audio_stream = 0;
1683 m_decoder->setAudioPID(apid, apidtype);
1684 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1685 m_decoder->setSyncPCR(pcrpid);
1687 m_decoder->setSyncPCR(-1);
1688 #ifndef INTERNAL_TELETEXT
1689 m_decoder->setTextPID(tpid);
1691 if (m_teletext_parser)
1692 m_teletext_parser->start(tpid);
1696 m_decoder->setTrickmode(1);
1700 m_decoder->setAudioChannel(achannel);
1702 // how we can do this better?
1703 // update cache pid when the user changed the audio track or video track
1704 // TODO handling of difference audio types.. default audio types..
1706 /* don't worry about non-existing services, nor pvr services */
1707 if (m_dvb_service && !m_is_pvr)
1709 if (apidtype == eDVBAudio::aMPEG)
1711 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1712 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1716 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1717 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1719 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1720 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1721 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1722 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1727 void eDVBServicePlay::loadCuesheet()
1729 std::string filename = m_reference.path + ".cuts";
1731 m_cue_entries.clear();
1733 FILE *f = fopen(filename.c_str(), "rb");
1737 eDebug("loading cuts..");
1740 unsigned long long where;
1743 if (!fread(&where, sizeof(where), 1, f))
1745 if (!fread(&what, sizeof(what), 1, f))
1748 #if BYTE_ORDER == LITTLE_ENDIAN
1749 where = bswap_64(where);
1756 m_cue_entries.insert(cueEntry(where, what));
1759 eDebug("%d entries", m_cue_entries.size());
1761 eDebug("cutfile not found!");
1763 m_cuesheet_changed = 0;
1764 cutlistToCuesheet();
1765 m_event((iPlayableService*)this, evCuesheetChanged);
1768 void eDVBServicePlay::saveCuesheet()
1770 std::string filename = m_reference.path + ".cuts";
1772 FILE *f = fopen(filename.c_str(), "wb");
1776 unsigned long long where;
1779 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1781 #if BYTE_ORDER == BIG_ENDIAN
1784 where = bswap_64(i->where);
1786 what = htonl(i->what);
1787 fwrite(&where, sizeof(where), 1, f);
1788 fwrite(&what, sizeof(what), 1, f);
1794 m_cuesheet_changed = 0;
1797 void eDVBServicePlay::cutlistToCuesheet()
1801 eDebug("no cue sheet");
1806 if (!m_cutlist_enabled)
1808 m_cue->commitSpans();
1809 eDebug("cutlists where disabled");
1813 pts_t in = 0, out = 0, length = 0;
1817 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1821 if (i == m_cue_entries.end())
1824 if (i->what == 0) /* in */
1828 } else if (i->what == 1) /* out */
1838 m_cue->addSourceSpan(in, out);
1842 if (i == m_cue_entries.end())
1845 m_cue->commitSpans();
1848 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1850 if (m_subtitle_widget)
1851 disableSubtitles(parent);
1853 if (!m_teletext_parser)
1856 if (!PyInt_Check(entry))
1859 m_subtitle_widget = new eSubtitleWidget(parent);
1860 m_subtitle_widget->resize(parent->size()); /* full size */
1862 int page = PyInt_AsLong(entry);
1864 m_teletext_parser->setPage(page);
1869 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
1871 delete m_subtitle_widget;
1872 m_subtitle_widget = 0;
1876 PyObject *eDVBServicePlay::getSubtitleList()
1878 if (!m_teletext_parser)
1884 PyObject *l = PyList_New(0);
1886 for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
1888 PyObject *tuple = PyTuple_New(2);
1890 sprintf(desc, "Page %x", *i);
1891 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
1892 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
1893 PyList_Append(l, tuple);
1899 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
1901 if (m_subtitle_widget)
1903 m_subtitle_pages.push_back(page);
1905 checkSubtitleTiming();
1909 void eDVBServicePlay::checkSubtitleTiming()
1913 if (m_subtitle_pages.empty())
1916 eDVBTeletextSubtitlePage p = m_subtitle_pages.front();
1921 m_decoder->getPTS(0, pos);
1923 int diff = p.m_pts - pos;
1926 eDebug("[late (%d ms)]", -diff / 90);
1931 eDebug("[invalid]");
1937 m_subtitle_widget->setPage(p);
1938 m_subtitle_pages.pop_front();
1941 m_subtitle_sync_timer.start(diff / 90, 1);
1947 DEFINE_REF(eDVBServicePlay)
1949 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");