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/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/base/nconfig.h> // access to python config
10 #include <lib/dvb/dvb.h>
11 #include <lib/dvb/db.h>
12 #include <lib/dvb/decoder.h>
14 #include <lib/components/file_eraser.h>
15 #include <lib/service/servicedvbrecord.h>
16 #include <lib/service/event.h>
17 #include <lib/dvb/metaparser.h>
18 #include <lib/dvb/tstools.h>
19 #include <lib/python/python.h>
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 #define TSPATH "/media/hdd"
36 class eStaticServiceDVBInformation: public iStaticServiceInformation
38 DECLARE_REF(eStaticServiceDVBInformation);
40 RESULT getName(const eServiceReference &ref, std::string &name);
41 int getLength(const eServiceReference &ref);
42 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
45 DEFINE_REF(eStaticServiceDVBInformation);
47 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
49 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
50 if ( !ref.name.empty() )
52 if (service.getParentTransportStreamID().get()) // linkage subservice
54 ePtr<iServiceHandler> service_center;
55 if (!eServiceCenter::getInstance(service_center))
57 eServiceReferenceDVB parent = service;
58 parent.setTransportStreamID( service.getParentTransportStreamID() );
59 parent.setServiceID( service.getParentServiceID() );
60 parent.setParentTransportStreamID(eTransportStreamID(0));
61 parent.setParentServiceID(eServiceID(0));
63 ePtr<iStaticServiceInformation> service_info;
64 if (!service_center->info(parent, service_info))
66 if (!service_info->getName(parent, name))
68 // just show short name
69 unsigned int pos = name.find("\xc2\x86");
70 if ( pos != std::string::npos )
72 pos = name.find("\xc2\x87");
73 if ( pos != std::string::npos )
89 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
94 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
96 ePtr<eDVBResourceManager> res_mgr;
97 if ( eDVBResourceManager::getInstance( res_mgr ) )
98 eDebug("isPlayble... no res manager!!");
101 eDVBChannelID chid, chid_ignore;
102 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
103 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
104 return res_mgr->canAllocateChannel(chid, chid_ignore);
110 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
112 DECLARE_REF(eStaticServiceDVBBouquetInformation);
114 eServiceReference m_playable_service;
115 RESULT getName(const eServiceReference &ref, std::string &name);
116 int getLength(const eServiceReference &ref);
117 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
120 DEFINE_REF(eStaticServiceDVBBouquetInformation);
122 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
124 ePtr<iDVBChannelList> db;
125 ePtr<eDVBResourceManager> res;
128 if ((err = eDVBResourceManager::getInstance(res)) != 0)
130 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
133 if ((err = res->getChannelList(db)) != 0)
135 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
140 if ((err = db->getBouquet(ref, bouquet)) != 0)
142 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
146 if ( bouquet && bouquet->m_bouquet_name.length() )
148 name = bouquet->m_bouquet_name;
155 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
157 if (ref.flags & eServiceReference::isGroup)
159 ePtr<iDVBChannelList> db;
160 ePtr<eDVBResourceManager> res;
162 if (eDVBResourceManager::getInstance(res))
164 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
168 if (res->getChannelList(db))
170 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
175 if (db->getBouquet(ref, bouquet))
177 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
181 eDVBChannelID chid, chid_ignore;
182 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
183 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
185 m_playable_service = *it;
186 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
187 if (res->canAllocateChannel(chid, chid_ignore))
191 m_playable_service = eServiceReference();
195 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
200 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
202 DECLARE_REF(eStaticServiceDVBPVRInformation);
203 eServiceReference m_ref;
204 eDVBMetaParser m_parser;
206 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
207 RESULT getName(const eServiceReference &ref, std::string &name);
208 int getLength(const eServiceReference &ref);
209 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
211 int getInfo(const eServiceReference &ref, int w);
212 std::string getInfoString(const eServiceReference &ref,int w);
215 DEFINE_REF(eStaticServiceDVBPVRInformation);
217 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
220 m_parser.parseFile(ref.path);
223 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
225 ASSERT(ref == m_ref);
226 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
230 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
232 ASSERT(ref == m_ref);
236 if (tstools.openFile(ref.path.c_str()))
240 if (tstools.calcLen(len))
246 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
250 case iServiceInformation::sDescription:
251 return iServiceInformation::resIsString;
252 case iServiceInformation::sServiceref:
253 return iServiceInformation::resIsString;
254 case iServiceInformation::sTimeCreate:
255 if (m_parser.m_time_create)
256 return m_parser.m_time_create;
258 return iServiceInformation::resNA;
260 return iServiceInformation::resNA;
264 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
268 case iServiceInformation::sDescription:
269 return m_parser.m_description;
270 case iServiceInformation::sServiceref:
271 return m_parser.m_ref.toString();
272 case iServiceInformation::sTags:
273 return m_parser.m_tags;
279 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
281 if (!ref.path.empty())
283 ePtr<eServiceEvent> event = new eServiceEvent;
284 std::string filename = ref.path;
285 filename.erase(filename.length()-2, 2);
287 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
297 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
299 DECLARE_REF(eDVBPVRServiceOfflineOperations);
300 eServiceReferenceDVB m_ref;
302 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
304 RESULT deleteFromDisk(int simulate);
305 RESULT getListOfFilenames(std::list<std::string> &);
308 DEFINE_REF(eDVBPVRServiceOfflineOperations);
310 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
314 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
320 std::list<std::string> res;
321 if (getListOfFilenames(res))
324 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
326 eDebug("FATAL !! can't get background file eraser");
328 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
330 eDebug("Removing %s...", i->c_str());
332 eraser->erase(i->c_str());
334 ::unlink(i->c_str());
341 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
344 res.push_back(m_ref.path);
346 // handling for old splitted recordings (enigma 1)
351 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
353 if (stat(buf, &s) < 0)
358 res.push_back(m_ref.path + ".meta");
359 res.push_back(m_ref.path + ".ap");
360 res.push_back(m_ref.path + ".cuts");
361 std::string tmp = m_ref.path;
362 tmp.erase(m_ref.path.length()-3);
363 res.push_back(tmp + ".eit");
367 DEFINE_REF(eServiceFactoryDVB)
369 eServiceFactoryDVB::eServiceFactoryDVB()
371 ePtr<eServiceCenter> sc;
373 eServiceCenter::getPrivInstance(sc);
375 sc->addServiceFactory(eServiceFactoryDVB::id, this);
377 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
378 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
381 eServiceFactoryDVB::~eServiceFactoryDVB()
383 ePtr<eServiceCenter> sc;
385 eServiceCenter::getPrivInstance(sc);
387 sc->removeServiceFactory(eServiceFactoryDVB::id);
390 DEFINE_REF(eDVBServiceList);
392 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
396 eDVBServiceList::~eDVBServiceList()
400 RESULT eDVBServiceList::startQuery()
402 ePtr<iDVBChannelList> db;
403 ePtr<eDVBResourceManager> res;
406 if ((err = eDVBResourceManager::getInstance(res)) != 0)
408 eDebug("no resource manager");
411 if ((err = res->getChannelList(db)) != 0)
413 eDebug("no channel list");
417 ePtr<eDVBChannelQuery> q;
419 if (!m_parent.path.empty())
421 eDVBChannelQuery::compile(q, m_parent.path);
424 eDebug("compile query failed");
429 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
431 eDebug("startQuery failed");
438 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
440 eServiceReferenceDVB ref;
445 while (!m_query->getNextResult(ref))
449 list.sort(iListableServiceCompare(this));
454 // The first argument of this function is a format string to specify the order and
455 // the content of the returned list
456 // useable format options are
457 // R = Service Reference (as swig object .. this is very slow)
458 // S = Service Reference (as python string object .. same as ref.toString())
459 // C = Service Reference (as python string object .. same as ref.toCompareString())
460 // N = Service Name (as python string object)
461 // when exactly one return value per service is selected in the format string,
462 // then each value is directly a list entry
463 // when more than one value is returned per service, then the list is a list of
465 // unknown format string chars are returned as python None values !
466 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
469 std::list<eServiceReference> tmplist;
472 if (!format || !(retcount=strlen(format)))
473 format = "R"; // just return service reference swig object ...
475 if (!getContent(tmplist, sorted))
477 int services=tmplist.size();
478 ePtr<iStaticServiceInformation> sptr;
479 eServiceCenterPtr service_center;
481 if (strchr(format, 'N'))
482 eServiceCenter::getPrivInstance(service_center);
484 ret = PyList_New(services);
485 std::list<eServiceReference>::iterator it(tmplist.begin());
487 for (int cnt=0; cnt < services; ++cnt)
489 eServiceReference &ref=*it++;
490 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
491 for (int i=0; i < retcount; ++i)
496 case 'R': // service reference (swig)object
497 tmp = NEW_eServiceReference(ref);
499 case 'C': // service reference compare string
500 tmp = PyString_FromString(ref.toCompareString().c_str());
502 case 'S': // service reference string
503 tmp = PyString_FromString(ref.toString().c_str());
505 case 'N': // service name
508 service_center->info(ref, sptr);
512 sptr->getName(ref, name);
514 tmp = PyString_FromString(name.c_str());
518 tmp = PyString_FromString("<n/a>");
531 PyTuple_SET_ITEM(tuple, i, tmp);
533 PyList_SET_ITEM(ret, cnt, tmp);
537 PyList_SET_ITEM(ret, cnt, tuple);
540 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
543 RESULT eDVBServiceList::getNext(eServiceReference &ref)
548 return m_query->getNextResult((eServiceReferenceDVB&)ref);
551 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
553 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
555 ePtr<iDVBChannelList> db;
556 ePtr<eDVBResourceManager> resm;
558 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
561 if (db->getBouquet(m_parent, m_bouquet) != 0)
572 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
576 return m_bouquet->addService(ref, before);
579 RESULT eDVBServiceList::removeService(eServiceReference &ref)
583 return m_bouquet->removeService(ref);
586 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
590 return m_bouquet->moveService(ref, pos);
593 RESULT eDVBServiceList::flushChanges()
597 return m_bouquet->flushChanges();
600 RESULT eDVBServiceList::setListName(const std::string &name)
604 return m_bouquet->setListName(name);
607 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
609 ePtr<eDVBService> service;
610 int r = lookupService(service, ref);
613 // check resources...
614 ptr = new eDVBServicePlay(ref, service);
618 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
620 if (ref.path.empty())
622 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
631 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
633 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
634 if (list->startQuery())
644 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
646 /* is a listable service? */
647 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
649 if ( !ref.name.empty() ) // satellites or providers list
650 ptr = m_StaticServiceDVBInfo;
651 else // a dvb bouquet
652 ptr = m_StaticServiceDVBBouquetInfo;
654 else if (!ref.path.empty()) /* do we have a PVR service? */
655 ptr = new eStaticServiceDVBPVRInformation(ref);
656 else // normal dvb service
658 ePtr<eDVBService> service;
659 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
660 ptr = m_StaticServiceDVBInfo;
662 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
668 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
670 if (ref.path.empty())
676 ptr = new eDVBPVRServiceOfflineOperations(ref);
681 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
683 // TODO: handle the listing itself
684 // if (ref.... == -1) .. return "... bouquets ...";
685 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
687 ePtr<iDVBChannelList> db;
688 ePtr<eDVBResourceManager> res;
691 if ((err = eDVBResourceManager::getInstance(res)) != 0)
693 eDebug("no resource manager");
696 if ((err = res->getChannelList(db)) != 0)
698 eDebug("no channel list");
702 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
703 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
705 eDebug("getService failed!");
712 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
713 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
716 m_is_pvr = !m_reference.path.empty();
718 m_timeshift_enabled = m_timeshift_active = 0;
721 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
722 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
723 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
725 m_cuesheet_changed = 0;
726 m_cutlist_enabled = 1;
728 m_subtitle_widget = 0;
730 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
733 eDVBServicePlay::~eDVBServicePlay()
735 delete m_subtitle_widget;
738 void eDVBServicePlay::gotNewEvent()
742 ePtr<eServiceEvent> m_event_now, m_event_next;
743 getEvent(m_event_now, 0);
744 getEvent(m_event_next, 1);
747 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
749 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
751 m_event((iPlayableService*)this, evUpdatedEventInfo);
754 void eDVBServicePlay::serviceEvent(int event)
758 case eDVBServicePMTHandler::eventTuned:
760 ePtr<iDVBDemux> m_demux;
761 if (!m_service_handler.getDataDemux(m_demux))
763 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
764 int sid = ref.getParentServiceID().get();
766 sid = ref.getServiceID().get();
767 if ( ref.getParentTransportStreamID().get() &&
768 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
769 m_event_handler.startOther(m_demux, sid);
771 m_event_handler.start(m_demux, sid);
775 case eDVBServicePMTHandler::eventTuneFailed:
777 eDebug("DVB service failed to tune");
778 m_event((iPlayableService*)this, evTuneFailed);
781 case eDVBServicePMTHandler::eventNewProgramInfo:
783 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
784 if (m_timeshift_enabled)
785 updateTimeshiftPids();
786 if (!m_timeshift_active)
788 if (m_first_program_info && m_is_pvr)
790 m_first_program_info = 0;
793 m_event((iPlayableService*)this, evUpdatedInfo);
796 case eDVBServicePMTHandler::eventEOF:
797 m_event((iPlayableService*)this, evEOF);
799 case eDVBServicePMTHandler::eventSOF:
800 m_event((iPlayableService*)this, evSOF);
805 void eDVBServicePlay::serviceEventTimeshift(int event)
809 case eDVBServicePMTHandler::eventNewProgramInfo:
810 if (m_timeshift_active)
813 case eDVBServicePMTHandler::eventSOF:
814 m_event((iPlayableService*)this, evSOF);
816 case eDVBServicePMTHandler::eventEOF:
822 RESULT eDVBServicePlay::start()
825 /* in pvr mode, we only want to use one demux. in tv mode, we're using
826 two (one for decoding, one for data source), as we must be prepared
827 to start recording from the data demux. */
829 m_cue = new eCueSheet();
831 m_first_program_info = 1;
832 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
833 r = m_service_handler.tune(service, m_is_pvr, m_cue);
835 /* inject EIT if there is a stored one */
838 std::string filename = service.path;
839 filename.erase(filename.length()-2, 2);
841 ePtr<eServiceEvent> event = new eServiceEvent;
842 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
844 ePtr<eServiceEvent> empty;
845 m_event_handler.inject(event, 0);
846 m_event_handler.inject(empty, 1);
853 m_event(this, evStart);
854 m_event((iPlayableService*)this, evSeekableStatusChanged);
858 RESULT eDVBServicePlay::stop()
860 /* add bookmark for last play position */
864 if (!getPlayPosition(play_position))
866 /* remove last position */
867 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
869 if (i->what == 3) /* current play position */
871 m_cue_entries.erase(i);
872 i = m_cue_entries.begin();
878 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
879 m_cuesheet_changed = 1;
883 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
885 m_service_handler_timeshift.free();
886 m_service_handler.free();
888 if (m_is_pvr && m_cuesheet_changed)
891 /* save cuesheet only when main file is accessible. */
892 if (!::stat(m_reference.path.c_str(), &s))
899 RESULT eDVBServicePlay::setTarget(int target)
901 m_is_primary = !target;
905 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
907 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
911 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
913 /* note: we check for timeshift to be enabled,
914 not neccessary active. if you pause when timeshift
915 is not active, you should activate it when unpausing */
916 if ((!m_is_pvr) && (!m_timeshift_enabled))
926 RESULT eDVBServicePlay::setSlowMotion(int ratio)
929 return m_decoder->setSlowMotion(ratio);
934 RESULT eDVBServicePlay::setFastForward(int ratio)
936 int skipmode, ffratio;
942 } else if (ratio > 0)
950 } else // if (ratio < 0)
956 if (m_skipmode != skipmode)
958 eDebug("setting cue skipmode to %d", skipmode);
960 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
963 m_skipmode = skipmode;
968 return m_decoder->setFastForward(ffratio);
971 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
973 if (m_is_pvr || m_timeshift_enabled)
983 /* TODO: when timeshift is enabled but not active, this doesn't work. */
984 RESULT eDVBServicePlay::getLength(pts_t &len)
986 ePtr<iDVBPVRChannel> pvr_channel;
988 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
991 return pvr_channel->getLength(len);
994 RESULT eDVBServicePlay::pause()
996 if (!m_is_paused && m_decoder)
999 return m_decoder->freeze(0);
1004 RESULT eDVBServicePlay::unpause()
1006 if (m_is_paused && m_decoder)
1009 return m_decoder->unfreeze();
1014 RESULT eDVBServicePlay::seekTo(pts_t to)
1016 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1018 if (!m_decode_demux)
1021 ePtr<iDVBPVRChannel> pvr_channel;
1023 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1029 m_cue->seekTo(0, to);
1033 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1035 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1037 if (!m_decode_demux)
1040 ePtr<iDVBPVRChannel> pvr_channel;
1042 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1047 /* HACK until we have skip-AP api */
1048 if ((to > 0) && (to < 100))
1056 m_cue->seekTo(mode, to);
1060 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1062 ePtr<iDVBPVRChannel> pvr_channel;
1064 if (!m_decode_demux)
1067 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1072 /* if there is a decoder, use audio or video PTS */
1075 r = m_decoder->getPTS(0, pos);
1081 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1084 RESULT eDVBServicePlay::setTrickmode(int trick)
1087 m_decoder->setTrickmode(trick);
1091 RESULT eDVBServicePlay::isCurrentlySeekable()
1093 return m_is_pvr || m_timeshift_active;
1096 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1102 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1108 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1114 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1120 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1126 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1129 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1130 (m_timeshift_enabled || !m_is_pvr))
1132 if (!m_timeshift_enabled)
1134 /* we need enough diskspace */
1136 if (statfs(TSPATH "/.", &fs) < 0)
1138 eDebug("statfs failed!");
1142 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1144 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1154 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1165 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1171 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1177 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1183 RESULT eDVBServicePlay::getName(std::string &name)
1187 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1188 return i->getName(m_reference, name);
1192 m_dvb_service->getName(m_reference, name);
1196 else if (!m_reference.name.empty())
1197 eStaticServiceDVBInformation().getName(m_reference, name);
1199 name = "DVB service";
1203 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1205 return m_event_handler.getEvent(evt, nownext);
1208 int eDVBServicePlay::getInfo(int w)
1210 eDVBServicePMTHandler::program program;
1213 return resIsPyObject;
1215 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1217 if (h.getProgramInfo(program))
1223 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1225 ePtr<eServiceEvent> evt;
1226 if (!m_event_handler.getEvent(evt, 0))
1228 ePtr<eComponentData> data;
1229 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1231 if ( data->getStreamContent() == 1 )
1233 switch(data->getComponentType())
1236 case 1: // 4:3 SD PAL
1238 case 3: // 16:9 SD PAL
1239 case 4: // > 16:9 PAL
1240 case 5: // 4:3 SD NTSC
1242 case 7: // 16:9 SD NTSC
1243 case 8: // > 16:9 NTSC
1246 case 9: // 4:3 HD PAL
1248 case 0xB: // 16:9 HD PAL
1249 case 0xC: // > 16:9 HD PAL
1250 case 0xD: // 4:3 HD NTSC
1252 case 0xF: // 16:9 HD NTSC
1253 case 0x10: // > 16:9 HD PAL
1254 return data->getComponentType();
1261 case sIsCrypted: return program.isCrypted();
1262 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1263 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1264 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1265 case sPCRPID: return program.pcrPid;
1266 case sPMTPID: return program.pmtPid;
1267 case sTXTPID: return program.textPid;
1268 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1269 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1270 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1271 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1272 case sProvider: if (!m_dvb_service) return -1; return -2;
1273 case sServiceref: return resIsString;
1279 std::string eDVBServicePlay::getInfoString(int w)
1284 if (!m_dvb_service) return "";
1285 return m_dvb_service->m_provider_name;
1287 return m_reference.toString();
1291 return iServiceInformation::getInfoString(w);
1294 PyObject *eDVBServicePlay::getInfoObject(int w)
1299 return m_service_handler.getCaIds();
1303 return iServiceInformation::getInfoObject(w);
1306 int eDVBServicePlay::getNumberOfTracks()
1308 eDVBServicePMTHandler::program program;
1309 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1310 if (h.getProgramInfo(program))
1312 return program.audioStreams.size();
1315 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1317 int ret = selectAudioStream(i);
1319 if (m_decoder->start())
1325 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1327 eDVBServicePMTHandler::program program;
1328 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1330 if (h.getProgramInfo(program))
1333 if (i >= program.audioStreams.size())
1336 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1337 info.m_description = "MPEG";
1338 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1339 info.m_description = "AC3";
1340 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1341 info.m_description = "AAC";
1342 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1343 info.m_description = "DTS";
1345 info.m_description = "???";
1347 if (program.audioStreams[i].component_tag != -1)
1349 ePtr<eServiceEvent> evt;
1350 if (!m_event_handler.getEvent(evt, 0))
1352 ePtr<eComponentData> data;
1353 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1354 info.m_language = data->getText();
1358 if (info.m_language.empty())
1359 info.m_language = program.audioStreams[i].language_code;
1364 int eDVBServicePlay::selectAudioStream(int i)
1366 eDVBServicePMTHandler::program program;
1367 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1369 if (h.getProgramInfo(program))
1372 if ((unsigned int)i >= program.audioStreams.size())
1378 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1381 if (m_radiotext_parser)
1382 m_radiotext_parser->start(program.audioStreams[i].pid);
1384 if (m_dvb_service && !m_is_pvr)
1386 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1388 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1389 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1393 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1394 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1398 h.resetCachedProgram();
1403 int eDVBServicePlay::getCurrentChannel()
1405 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1408 RESULT eDVBServicePlay::selectChannel(int i)
1410 if (i < LEFT || i > RIGHT || i == STEREO)
1413 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1415 m_decoder->setAudioChannel(i);
1419 std::string eDVBServicePlay::getRadioText(int x)
1421 if (m_radiotext_parser)
1425 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1430 void eDVBServicePlay::radioTextUpdated()
1432 m_event((iPlayableService*)this, evUpdatedRadioText);
1435 int eDVBServiceBase::getFrontendInfo(int w)
1437 eUsePtr<iDVBChannel> channel;
1438 if(m_service_handler.getChannel(channel))
1440 ePtr<iDVBFrontend> fe;
1441 if(channel->getFrontend(fe))
1443 return fe->readFrontendData(w);
1446 PyObject *eDVBServiceBase::getFrontendData(bool original)
1450 eUsePtr<iDVBChannel> channel;
1451 if(!m_service_handler.getChannel(channel))
1453 ePtr<iDVBFrontend> fe;
1454 if(!channel->getFrontend(fe))
1456 ret = fe->readTransponderData(original);
1459 ePtr<iDVBFrontendParameters> feparm;
1460 channel->getCurrentFrontendParameters(feparm);
1463 eDVBFrontendParametersSatellite osat;
1464 if (!feparm->getDVBS(osat))
1466 void PutToDict(ePyObject &, const char*, long);
1467 void PutToDict(ePyObject &, const char*, const char*);
1468 PutToDict(ret, "orbital_position", osat.orbital_position);
1469 const char *tmp = "UNKNOWN";
1470 switch(osat.polarisation)
1472 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1473 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1474 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1475 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1478 PutToDict(ret, "polarization", tmp);
1492 int eDVBServicePlay::getNumberOfSubservices()
1494 ePtr<eServiceEvent> evt;
1495 if (!m_event_handler.getEvent(evt, 0))
1496 return evt->getNumOfLinkageServices();
1500 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1502 ePtr<eServiceEvent> evt;
1503 if (!m_event_handler.getEvent(evt, 0))
1505 if (!evt->getLinkageService(sub, m_reference, n))
1508 sub.type=eServiceReference::idInvalid;
1512 RESULT eDVBServicePlay::startTimeshift()
1514 ePtr<iDVBDemux> demux;
1516 eDebug("Start timeshift!");
1518 if (m_timeshift_enabled)
1521 /* start recording with the data demux. */
1522 if (m_service_handler.getDataDemux(demux))
1525 demux->createTSRecorder(m_record);
1529 char templ[]=TSPATH "/timeshift.XXXXXX";
1530 m_timeshift_fd = mkstemp(templ);
1531 m_timeshift_file = templ;
1533 eDebug("recording to %s", templ);
1535 if (m_timeshift_fd < 0)
1541 m_record->setTargetFD(m_timeshift_fd);
1543 m_timeshift_enabled = 1;
1545 updateTimeshiftPids();
1551 RESULT eDVBServicePlay::stopTimeshift()
1553 if (!m_timeshift_enabled)
1558 m_timeshift_enabled = 0;
1563 close(m_timeshift_fd);
1564 eDebug("remove timeshift file");
1565 remove(m_timeshift_file.c_str());
1570 int eDVBServicePlay::isTimeshiftActive()
1572 return m_timeshift_enabled && m_timeshift_active;
1575 RESULT eDVBServicePlay::activateTimeshift()
1577 if (!m_timeshift_enabled)
1580 if (!m_timeshift_active)
1582 switchToTimeshift();
1589 PyObject *eDVBServicePlay::getCutList()
1591 ePyObject list = PyList_New(0);
1593 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1595 ePyObject tuple = PyTuple_New(2);
1596 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1597 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1598 PyList_Append(list, tuple);
1605 void eDVBServicePlay::setCutList(ePyObject list)
1607 if (!PyList_Check(list))
1609 int size = PyList_Size(list);
1612 m_cue_entries.clear();
1614 for (i=0; i<size; ++i)
1616 ePyObject tuple = PyList_GET_ITEM(list, i);
1617 if (!PyTuple_Check(tuple))
1619 eDebug("non-tuple in cutlist");
1622 if (PyTuple_Size(tuple) != 2)
1624 eDebug("cutlist entries need to be a 2-tuple");
1627 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1628 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1630 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1633 pts_t pts = PyLong_AsLongLong(ppts);
1634 int type = PyInt_AsLong(ptype);
1635 m_cue_entries.insert(cueEntry(pts, type));
1636 eDebug("adding %08llx, %d", pts, type);
1638 m_cuesheet_changed = 1;
1640 cutlistToCuesheet();
1641 m_event((iPlayableService*)this, evCuesheetChanged);
1644 void eDVBServicePlay::setCutListEnable(int enable)
1646 m_cutlist_enabled = enable;
1647 cutlistToCuesheet();
1650 void eDVBServicePlay::updateTimeshiftPids()
1655 eDVBServicePMTHandler::program program;
1656 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1658 if (h.getProgramInfo(program))
1662 std::set<int> pids_to_record;
1663 pids_to_record.insert(0); // PAT
1664 if (program.pmtPid != -1)
1665 pids_to_record.insert(program.pmtPid); // PMT
1667 if (program.textPid != -1)
1668 pids_to_record.insert(program.textPid); // Videotext
1670 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1671 i(program.videoStreams.begin());
1672 i != program.videoStreams.end(); ++i)
1673 pids_to_record.insert(i->pid);
1675 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1676 i(program.audioStreams.begin());
1677 i != program.audioStreams.end(); ++i)
1678 pids_to_record.insert(i->pid);
1680 std::set<int> new_pids, obsolete_pids;
1682 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1683 m_pids_active.begin(), m_pids_active.end(),
1684 std::inserter(new_pids, new_pids.begin()));
1686 std::set_difference(
1687 m_pids_active.begin(), m_pids_active.end(),
1688 pids_to_record.begin(), pids_to_record.end(),
1689 std::inserter(new_pids, new_pids.begin())
1692 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1693 m_record->addPID(*i);
1695 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1696 m_record->removePID(*i);
1700 void eDVBServicePlay::switchToLive()
1702 if (!m_timeshift_active)
1708 m_teletext_parser = 0;
1709 m_radiotext_parser = 0;
1710 m_subtitle_parser = 0;
1711 m_new_dvb_subtitle_page_connection = 0;
1712 m_new_subtitle_page_connection = 0;
1713 m_radiotext_updated_connection = 0;
1715 /* free the timeshift service handler, we need the resources */
1716 m_service_handler_timeshift.free();
1717 m_timeshift_active = 0;
1719 m_event((iPlayableService*)this, evSeekableStatusChanged);
1724 void eDVBServicePlay::switchToTimeshift()
1726 if (m_timeshift_active)
1731 m_teletext_parser = 0;
1732 m_radiotext_parser = 0;
1733 m_subtitle_parser = 0;
1734 m_new_subtitle_page_connection = 0;
1735 m_new_dvb_subtitle_page_connection = 0;
1736 m_radiotext_updated_connection = 0;
1738 m_timeshift_active = 1;
1740 m_event((iPlayableService*)this, evSeekableStatusChanged);
1742 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1743 r.path = m_timeshift_file;
1745 m_cue = new eCueSheet();
1746 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1747 updateDecoder(); /* mainly to switch off PCR */
1750 void eDVBServicePlay::updateDecoder()
1752 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1754 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1756 bool defaultac3=false;
1757 std::string default_ac3;
1759 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1760 defaultac3 = default_ac3 == "True";
1762 eDVBServicePMTHandler::program program;
1763 if (h.getProgramInfo(program))
1764 eDebug("getting program info failed.");
1767 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1768 if (!program.videoStreams.empty())
1770 eDebugNoNewLine(" (");
1771 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1772 i(program.videoStreams.begin());
1773 i != program.videoStreams.end(); ++i)
1780 if (i != program.videoStreams.begin())
1781 eDebugNoNewLine(", ");
1782 eDebugNoNewLine("%04x", i->pid);
1784 eDebugNoNewLine(")");
1786 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1787 if (!program.audioStreams.empty())
1789 eDebugNoNewLine(" (");
1790 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1791 i(program.audioStreams.begin());
1792 i != program.audioStreams.end(); ++i)
1794 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1796 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1802 if (i != program.audioStreams.begin())
1803 eDebugNoNewLine(", ");
1804 eDebugNoNewLine("%04x", i->pid);
1806 eDebugNoNewLine(")");
1808 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1809 pcrpid = program.pcrPid;
1810 eDebug(", and the text pid is %04x", program.textPid);
1811 tpid = program.textPid;
1816 h.getDecodeDemux(m_decode_demux);
1818 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1820 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1821 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1822 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1823 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1824 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
1831 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1832 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1833 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1835 else // subservice or recording
1837 eServiceReferenceDVB ref;
1838 m_service_handler.getServiceReference(ref);
1839 eServiceReferenceDVB parent = ref.getParentServiceReference();
1844 ePtr<eDVBResourceManager> res_mgr;
1845 if (!eDVBResourceManager::getInstance(res_mgr))
1847 ePtr<iDVBChannelList> db;
1848 if (!res_mgr->getChannelList(db))
1850 ePtr<eDVBService> origService;
1851 if (!db->getService(parent, origService))
1853 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1854 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1860 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1861 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1863 m_decoder->setVideoPID(vpid, vpidtype);
1864 m_decoder->setAudioPID(apid, apidtype);
1865 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1867 m_decoder->setSyncPCR(pcrpid);
1870 ePtr<iDVBDemux> data_demux;
1871 if (!h.getDataDemux(data_demux))
1873 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1874 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1875 m_radiotext_parser->start(apid);
1880 m_decoder->setSyncPCR(-1);
1882 m_decoder->setTextPID(tpid);
1884 m_teletext_parser->start(program.textPid);
1887 m_decoder->setTrickmode(1);
1891 if (vpid > 0 && vpid < 0x2000)
1895 std::string radio_pic;
1896 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1897 m_decoder->setRadioPic(radio_pic);
1900 m_decoder->setAudioChannel(achannel);
1902 // how we can do this better?
1903 // update cache pid when the user changed the audio track or video track
1904 // TODO handling of difference audio types.. default audio types..
1906 /* don't worry about non-existing services, nor pvr services */
1907 if (m_dvb_service && !m_is_pvr)
1909 if (apidtype == eDVBAudio::aMPEG)
1911 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1912 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1916 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1917 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1919 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1920 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1921 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1922 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1925 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1928 void eDVBServicePlay::loadCuesheet()
1930 std::string filename = m_reference.path + ".cuts";
1932 m_cue_entries.clear();
1934 FILE *f = fopen(filename.c_str(), "rb");
1938 eDebug("loading cuts..");
1941 unsigned long long where;
1944 if (!fread(&where, sizeof(where), 1, f))
1946 if (!fread(&what, sizeof(what), 1, f))
1949 #if BYTE_ORDER == LITTLE_ENDIAN
1950 where = bswap_64(where);
1957 m_cue_entries.insert(cueEntry(where, what));
1960 eDebug("%d entries", m_cue_entries.size());
1962 eDebug("cutfile not found!");
1964 m_cuesheet_changed = 0;
1965 cutlistToCuesheet();
1966 m_event((iPlayableService*)this, evCuesheetChanged);
1969 void eDVBServicePlay::saveCuesheet()
1971 std::string filename = m_reference.path + ".cuts";
1973 FILE *f = fopen(filename.c_str(), "wb");
1977 unsigned long long where;
1980 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1982 #if BYTE_ORDER == BIG_ENDIAN
1985 where = bswap_64(i->where);
1987 what = htonl(i->what);
1988 fwrite(&where, sizeof(where), 1, f);
1989 fwrite(&what, sizeof(what), 1, f);
1995 m_cuesheet_changed = 0;
1998 void eDVBServicePlay::cutlistToCuesheet()
2002 eDebug("no cue sheet");
2007 if (!m_cutlist_enabled)
2009 m_cue->commitSpans();
2010 eDebug("cutlists were disabled");
2014 pts_t in = 0, out = 0, length = 0;
2018 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2022 if (i == m_cue_entries.end())
2025 if (i->what == 0) /* in */
2029 } else if (i->what == 1) /* out */
2031 else /* mark (2) or last play position (3) */
2039 m_cue->addSourceSpan(in, out);
2043 if (i == m_cue_entries.end())
2046 m_cue->commitSpans();
2049 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2051 if (m_subtitle_widget)
2052 disableSubtitles(parent);
2055 int tuplesize = PyTuple_Size(tuple);
2058 if (!PyTuple_Check(tuple))
2064 entry = PyTuple_GET_ITEM(tuple, 0);
2066 if (!PyInt_Check(entry))
2069 type = PyInt_AsLong(entry);
2071 if (type == 1) // teletext subtitles
2073 int page, magazine, pid;
2077 if (!m_teletext_parser)
2079 eDebug("enable teletext subtitles.. no parser !!!");
2083 entry = PyTuple_GET_ITEM(tuple, 1);
2084 if (!PyInt_Check(entry))
2086 pid = PyInt_AsLong(entry);
2088 entry = PyTuple_GET_ITEM(tuple, 2);
2089 if (!PyInt_Check(entry))
2091 page = PyInt_AsLong(entry);
2093 entry = PyTuple_GET_ITEM(tuple, 3);
2094 if (!PyInt_Check(entry))
2096 magazine = PyInt_AsLong(entry);
2098 m_subtitle_widget = new eSubtitleWidget(parent);
2099 m_subtitle_widget->resize(parent->size()); /* full size */
2100 m_teletext_parser->setPageAndMagazine(page, magazine);
2102 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2106 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2107 if (!m_subtitle_parser)
2109 eDebug("enable dvb subtitles.. no parser !!!");
2115 entry = PyTuple_GET_ITEM(tuple, 1);
2116 if (!PyInt_Check(entry))
2118 pid = PyInt_AsLong(entry);
2120 entry = PyTuple_GET_ITEM(tuple, 2);
2121 if (!PyInt_Check(entry))
2123 composition_page_id = PyInt_AsLong(entry);
2125 entry = PyTuple_GET_ITEM(tuple, 3);
2126 if (!PyInt_Check(entry))
2128 ancillary_page_id = PyInt_AsLong(entry);
2130 m_subtitle_widget = new eSubtitleWidget(parent);
2131 m_subtitle_widget->resize(parent->size()); /* full size */
2132 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2134 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2140 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2141 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2142 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2146 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2148 delete m_subtitle_widget;
2149 m_subtitle_widget = 0;
2150 if (m_subtitle_parser)
2152 m_subtitle_parser->stop();
2153 m_dvb_subtitle_pages.clear();
2155 if (m_teletext_parser)
2157 m_teletext_parser->setPageAndMagazine(-1, -1);
2158 m_subtitle_pages.clear();
2161 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2165 PyObject *eDVBServicePlay::getCachedSubtitle()
2169 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2172 unsigned int data = (unsigned int)tmp;
2173 int pid = (data&0xFFFF0000)>>16;
2174 ePyObject tuple = PyTuple_New(4);
2175 eDVBServicePMTHandler::program program;
2176 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2177 if (!h.getProgramInfo(program))
2179 if (program.textPid==pid) // teletext
2180 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2182 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2183 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2184 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2185 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2194 PyObject *eDVBServicePlay::getSubtitleList()
2196 if (!m_teletext_parser)
2202 ePyObject l = PyList_New(0);
2203 std::set<int> added_ttx_pages;
2205 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2206 m_teletext_parser->m_found_subtitle_pages;
2208 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2209 eDVBServicePMTHandler::program program;
2210 if (h.getProgramInfo(program))
2211 eDebug("getting program info failed.");
2214 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2215 it != program.subtitleStreams.end(); ++it)
2217 switch(it->subtitling_type)
2219 case 0x01: // ebu teletext subtitles
2221 int page_number = it->teletext_page_number & 0xFF;
2222 int magazine_number = it->teletext_magazine_number & 7;
2223 int hash = magazine_number << 8 | page_number;
2224 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2226 ePyObject tuple = PyTuple_New(5);
2227 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2228 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2229 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2230 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2231 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2232 PyList_Append(l, tuple);
2234 added_ttx_pages.insert(hash);
2239 case 0x20 ... 0x23: // dvb subtitles
2241 ePyObject tuple = PyTuple_New(5);
2242 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2243 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2244 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2245 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2246 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2247 PyList_Insert(l, 0, tuple);
2255 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2256 it != subs.end(); ++it)
2258 int page_number = it->teletext_page_number & 0xFF;
2259 int magazine_number = it->teletext_magazine_number & 7;
2260 int hash = magazine_number << 8 | page_number;
2261 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2263 ePyObject tuple = PyTuple_New(5);
2264 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2265 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2266 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2267 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2268 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2269 PyList_Append(l, tuple);
2277 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2279 if (m_subtitle_widget)
2281 m_subtitle_pages.push_back(page);
2282 checkSubtitleTiming();
2286 void eDVBServicePlay::checkSubtitleTiming()
2288 // eDebug("checkSubtitleTiming");
2289 if (!m_subtitle_widget)
2293 enum { TELETEXT, DVB } type;
2294 eDVBTeletextSubtitlePage page;
2295 eDVBSubtitlePage dvb_page;
2297 if (!m_subtitle_pages.empty())
2299 page = m_subtitle_pages.front();
2301 show_time = page.m_pts;
2303 else if (!m_dvb_subtitle_pages.empty())
2305 dvb_page = m_dvb_subtitle_pages.front();
2307 show_time = dvb_page.m_show_time;
2315 m_decoder->getPTS(0, pos);
2317 // eDebug("%lld %lld", pos, show_time);
2318 int diff = show_time - pos;
2321 eDebug("[late (%d ms)]", -diff / 90);
2326 eDebug("[invalid]");
2332 if (type == TELETEXT)
2334 eDebug("display teletext subtitle page");
2335 m_subtitle_widget->setPage(page);
2336 m_subtitle_pages.pop_front();
2340 eDebug("display dvb subtitle Page");
2341 m_subtitle_widget->setPage(dvb_page);
2342 m_dvb_subtitle_pages.pop_front();
2346 // eDebug("start subtitle delay %d", diff / 90);
2347 m_subtitle_sync_timer.start(diff / 90, 1);
2353 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2355 if (m_subtitle_widget)
2357 m_dvb_subtitle_pages.push_back(p);
2358 checkSubtitleTiming();
2362 int eDVBServicePlay::getAC3Delay()
2365 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2367 return m_decoder->getAC3Delay();
2372 int eDVBServicePlay::getPCMDelay()
2375 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2377 return m_decoder->getPCMDelay();
2382 void eDVBServicePlay::setAC3Delay(int delay)
2385 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2387 m_decoder->setAC3Delay(delay);
2390 void eDVBServicePlay::setPCMDelay(int delay)
2393 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2395 m_decoder->setPCMDelay(delay);
2398 DEFINE_REF(eDVBServicePlay)
2400 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");