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);
109 DEFINE_REF(eStaticServiceDVBBouquetInformation);
111 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
113 ePtr<iDVBChannelList> db;
114 ePtr<eDVBResourceManager> res;
117 if ((err = eDVBResourceManager::getInstance(res)) != 0)
119 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
122 if ((err = res->getChannelList(db)) != 0)
124 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
129 if ((err = db->getBouquet(ref, bouquet)) != 0)
131 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
135 if ( bouquet && bouquet->m_bouquet_name.length() )
137 name = bouquet->m_bouquet_name;
144 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
146 if (ref.flags & eServiceReference::isGroup)
148 ePtr<iDVBChannelList> db;
149 ePtr<eDVBResourceManager> res;
151 if (eDVBResourceManager::getInstance(res))
153 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
157 if (res->getChannelList(db))
159 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
164 if (db->getBouquet(ref, bouquet))
166 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
171 eDVBChannelID chid, chid_ignore;
172 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
173 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
175 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
176 int tmp=res->canAllocateChannel(chid, chid_ignore);
179 m_playable_service = *it;
186 m_playable_service = eServiceReference();
190 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
195 #include <lib/dvb/epgcache.h>
197 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
199 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
202 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
204 DECLARE_REF(eStaticServiceDVBPVRInformation);
205 eServiceReference m_ref;
206 eDVBMetaParser m_parser;
208 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
209 RESULT getName(const eServiceReference &ref, std::string &name);
210 int getLength(const eServiceReference &ref);
211 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
212 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
213 int getInfo(const eServiceReference &ref, int w);
214 std::string getInfoString(const eServiceReference &ref,int w);
217 DEFINE_REF(eStaticServiceDVBPVRInformation);
219 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
222 m_parser.parseFile(ref.path);
225 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
227 ASSERT(ref == m_ref);
228 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
232 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
234 ASSERT(ref == m_ref);
238 if (tstools.openFile(ref.path.c_str()))
242 if (tstools.calcLen(len))
248 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
252 case iServiceInformation::sDescription:
253 return iServiceInformation::resIsString;
254 case iServiceInformation::sServiceref:
255 return iServiceInformation::resIsString;
256 case iServiceInformation::sTimeCreate:
257 if (m_parser.m_time_create)
258 return m_parser.m_time_create;
260 return iServiceInformation::resNA;
262 return iServiceInformation::resNA;
266 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
270 case iServiceInformation::sDescription:
271 return m_parser.m_description;
272 case iServiceInformation::sServiceref:
273 return m_parser.m_ref.toString();
274 case iServiceInformation::sTags:
275 return m_parser.m_tags;
281 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
283 if (!ref.path.empty())
285 ePtr<eServiceEvent> event = new eServiceEvent;
286 std::string filename = ref.path;
287 filename.erase(filename.length()-2, 2);
289 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
299 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
301 DECLARE_REF(eDVBPVRServiceOfflineOperations);
302 eServiceReferenceDVB m_ref;
304 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
306 RESULT deleteFromDisk(int simulate);
307 RESULT getListOfFilenames(std::list<std::string> &);
310 DEFINE_REF(eDVBPVRServiceOfflineOperations);
312 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
316 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
322 std::list<std::string> res;
323 if (getListOfFilenames(res))
326 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
328 eDebug("FATAL !! can't get background file eraser");
330 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
332 eDebug("Removing %s...", i->c_str());
334 eraser->erase(i->c_str());
336 ::unlink(i->c_str());
343 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
346 res.push_back(m_ref.path);
348 // handling for old splitted recordings (enigma 1)
353 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
355 if (stat(buf, &s) < 0)
360 res.push_back(m_ref.path + ".meta");
361 res.push_back(m_ref.path + ".ap");
362 res.push_back(m_ref.path + ".cuts");
363 std::string tmp = m_ref.path;
364 tmp.erase(m_ref.path.length()-3);
365 res.push_back(tmp + ".eit");
369 DEFINE_REF(eServiceFactoryDVB)
371 eServiceFactoryDVB::eServiceFactoryDVB()
373 ePtr<eServiceCenter> sc;
375 eServiceCenter::getPrivInstance(sc);
377 sc->addServiceFactory(eServiceFactoryDVB::id, this);
379 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
380 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
383 eServiceFactoryDVB::~eServiceFactoryDVB()
385 ePtr<eServiceCenter> sc;
387 eServiceCenter::getPrivInstance(sc);
389 sc->removeServiceFactory(eServiceFactoryDVB::id);
392 DEFINE_REF(eDVBServiceList);
394 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
398 eDVBServiceList::~eDVBServiceList()
402 RESULT eDVBServiceList::startQuery()
404 ePtr<iDVBChannelList> db;
405 ePtr<eDVBResourceManager> res;
408 if ((err = eDVBResourceManager::getInstance(res)) != 0)
410 eDebug("no resource manager");
413 if ((err = res->getChannelList(db)) != 0)
415 eDebug("no channel list");
419 ePtr<eDVBChannelQuery> q;
421 if (!m_parent.path.empty())
423 eDVBChannelQuery::compile(q, m_parent.path);
426 eDebug("compile query failed");
431 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
433 eDebug("startQuery failed");
440 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
442 eServiceReferenceDVB ref;
447 while (!m_query->getNextResult(ref))
451 list.sort(iListableServiceCompare(this));
456 // The first argument of this function is a format string to specify the order and
457 // the content of the returned list
458 // useable format options are
459 // R = Service Reference (as swig object .. this is very slow)
460 // S = Service Reference (as python string object .. same as ref.toString())
461 // C = Service Reference (as python string object .. same as ref.toCompareString())
462 // N = Service Name (as python string object)
463 // when exactly one return value per service is selected in the format string,
464 // then each value is directly a list entry
465 // when more than one value is returned per service, then the list is a list of
467 // unknown format string chars are returned as python None values !
468 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
471 std::list<eServiceReference> tmplist;
474 if (!format || !(retcount=strlen(format)))
475 format = "R"; // just return service reference swig object ...
477 if (!getContent(tmplist, sorted))
479 int services=tmplist.size();
480 ePtr<iStaticServiceInformation> sptr;
481 eServiceCenterPtr service_center;
483 if (strchr(format, 'N'))
484 eServiceCenter::getPrivInstance(service_center);
486 ret = PyList_New(services);
487 std::list<eServiceReference>::iterator it(tmplist.begin());
489 for (int cnt=0; cnt < services; ++cnt)
491 eServiceReference &ref=*it++;
492 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
493 for (int i=0; i < retcount; ++i)
498 case 'R': // service reference (swig)object
499 tmp = NEW_eServiceReference(ref);
501 case 'C': // service reference compare string
502 tmp = PyString_FromString(ref.toCompareString().c_str());
504 case 'S': // service reference string
505 tmp = PyString_FromString(ref.toString().c_str());
507 case 'N': // service name
510 service_center->info(ref, sptr);
514 sptr->getName(ref, name);
516 tmp = PyString_FromString(name.c_str());
520 tmp = PyString_FromString("<n/a>");
533 PyTuple_SET_ITEM(tuple, i, tmp);
535 PyList_SET_ITEM(ret, cnt, tmp);
539 PyList_SET_ITEM(ret, cnt, tuple);
542 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
545 RESULT eDVBServiceList::getNext(eServiceReference &ref)
550 return m_query->getNextResult((eServiceReferenceDVB&)ref);
553 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
555 if (m_parent.flags & eServiceReference::canDescent) // bouquet
557 ePtr<iDVBChannelList> db;
558 ePtr<eDVBResourceManager> resm;
560 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
563 if (db->getBouquet(m_parent, m_bouquet) != 0)
574 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
578 return m_bouquet->addService(ref, before);
581 RESULT eDVBServiceList::removeService(eServiceReference &ref)
585 return m_bouquet->removeService(ref);
588 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
592 return m_bouquet->moveService(ref, pos);
595 RESULT eDVBServiceList::flushChanges()
599 return m_bouquet->flushChanges();
602 RESULT eDVBServiceList::setListName(const std::string &name)
606 return m_bouquet->setListName(name);
609 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
611 ePtr<eDVBService> service;
612 int r = lookupService(service, ref);
615 // check resources...
616 ptr = new eDVBServicePlay(ref, service);
620 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
622 if (ref.path.empty())
624 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
633 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
635 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
636 if (list->startQuery())
646 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
648 /* is a listable service? */
649 if (ref.flags & eServiceReference::canDescent) // bouquet
651 if ( !ref.name.empty() ) // satellites or providers list
652 ptr = m_StaticServiceDVBInfo;
653 else // a dvb bouquet
654 ptr = m_StaticServiceDVBBouquetInfo;
656 else if (!ref.path.empty()) /* do we have a PVR service? */
657 ptr = new eStaticServiceDVBPVRInformation(ref);
658 else // normal dvb service
660 ePtr<eDVBService> service;
661 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
662 ptr = m_StaticServiceDVBInfo;
664 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
670 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
672 if (ref.path.empty())
678 ptr = new eDVBPVRServiceOfflineOperations(ref);
683 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
685 // TODO: handle the listing itself
686 // if (ref.... == -1) .. return "... bouquets ...";
687 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
689 ePtr<iDVBChannelList> db;
690 ePtr<eDVBResourceManager> res;
693 if ((err = eDVBResourceManager::getInstance(res)) != 0)
695 eDebug("no resource manager");
698 if ((err = res->getChannelList(db)) != 0)
700 eDebug("no channel list");
704 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
705 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
707 eDebug("getService failed!");
714 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
715 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
717 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
719 m_is_pvr = !m_reference.path.empty();
721 m_timeshift_enabled = m_timeshift_active = 0;
724 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
725 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
726 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
728 m_cuesheet_changed = 0;
729 m_cutlist_enabled = 1;
731 m_subtitle_widget = 0;
735 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
738 eDVBServicePlay::~eDVBServicePlay()
740 delete m_subtitle_widget;
743 void eDVBServicePlay::gotNewEvent()
747 ePtr<eServiceEvent> m_event_now, m_event_next;
748 getEvent(m_event_now, 0);
749 getEvent(m_event_next, 1);
752 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
754 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
756 m_event((iPlayableService*)this, evUpdatedEventInfo);
759 void eDVBServicePlay::serviceEvent(int event)
761 m_tune_state = event;
765 case eDVBServicePMTHandler::eventTuned:
767 ePtr<iDVBDemux> m_demux;
768 if (!m_service_handler.getDataDemux(m_demux))
770 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
771 int sid = ref.getParentServiceID().get();
773 sid = ref.getServiceID().get();
774 if ( ref.getParentTransportStreamID().get() &&
775 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
776 m_event_handler.startOther(m_demux, sid);
778 m_event_handler.start(m_demux, sid);
782 case eDVBServicePMTHandler::eventNoPAT:
783 case eDVBServicePMTHandler::eventNoPATEntry:
784 case eDVBServicePMTHandler::eventNoPMT:
785 case eDVBServicePMTHandler::eventTuneFailed:
787 eDebug("DVB service failed to tune - error %d", event);
788 m_event((iPlayableService*)this, evTuneFailed);
791 case eDVBServicePMTHandler::eventNewProgramInfo:
793 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
794 if (m_timeshift_enabled)
795 updateTimeshiftPids();
796 if (!m_timeshift_active)
798 if (m_first_program_info && m_is_pvr)
800 m_first_program_info = 0;
803 m_event((iPlayableService*)this, evUpdatedInfo);
806 case eDVBServicePMTHandler::eventEOF:
807 m_event((iPlayableService*)this, evEOF);
809 case eDVBServicePMTHandler::eventSOF:
810 m_event((iPlayableService*)this, evSOF);
815 void eDVBServicePlay::serviceEventTimeshift(int event)
819 case eDVBServicePMTHandler::eventNewProgramInfo:
820 if (m_timeshift_active)
823 case eDVBServicePMTHandler::eventSOF:
824 m_event((iPlayableService*)this, evSOF);
826 case eDVBServicePMTHandler::eventEOF:
832 RESULT eDVBServicePlay::start()
835 /* in pvr mode, we only want to use one demux. in tv mode, we're using
836 two (one for decoding, one for data source), as we must be prepared
837 to start recording from the data demux. */
839 m_cue = new eCueSheet();
841 m_first_program_info = 1;
842 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
843 r = m_service_handler.tune(service, m_is_pvr, m_cue);
845 /* inject EIT if there is a stored one */
848 std::string filename = service.path;
849 filename.erase(filename.length()-2, 2);
851 ePtr<eServiceEvent> event = new eServiceEvent;
852 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
854 ePtr<eServiceEvent> empty;
855 m_event_handler.inject(event, 0);
856 m_event_handler.inject(empty, 1);
863 m_event(this, evStart);
864 m_event((iPlayableService*)this, evSeekableStatusChanged);
868 RESULT eDVBServicePlay::stop()
870 /* add bookmark for last play position */
874 if (!getPlayPosition(play_position))
876 /* remove last position */
877 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
879 if (i->what == 3) /* current play position */
881 m_cue_entries.erase(i);
882 i = m_cue_entries.begin();
888 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
889 m_cuesheet_changed = 1;
893 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
895 m_service_handler_timeshift.free();
896 m_service_handler.free();
898 if (m_is_pvr && m_cuesheet_changed)
901 /* save cuesheet only when main file is accessible. */
902 if (!::stat(m_reference.path.c_str(), &s))
909 RESULT eDVBServicePlay::setTarget(int target)
911 m_is_primary = !target;
915 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
917 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
921 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
923 /* note: we check for timeshift to be enabled,
924 not neccessary active. if you pause when timeshift
925 is not active, you should activate it when unpausing */
926 if ((!m_is_pvr) && (!m_timeshift_enabled))
936 RESULT eDVBServicePlay::setSlowMotion(int ratio)
939 return m_decoder->setSlowMotion(ratio);
944 RESULT eDVBServicePlay::setFastForward(int ratio)
946 int skipmode, ffratio;
952 } else if (ratio > 0)
960 } else // if (ratio < 0)
966 if (m_skipmode != skipmode)
968 eDebug("setting cue skipmode to %d", skipmode);
970 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
973 m_skipmode = skipmode;
978 return m_decoder->setFastForward(ffratio);
981 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
983 if (m_is_pvr || m_timeshift_enabled)
993 /* TODO: when timeshift is enabled but not active, this doesn't work. */
994 RESULT eDVBServicePlay::getLength(pts_t &len)
996 ePtr<iDVBPVRChannel> pvr_channel;
998 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1001 return pvr_channel->getLength(len);
1004 RESULT eDVBServicePlay::pause()
1006 if (!m_is_paused && m_decoder)
1009 return m_decoder->freeze(0);
1014 RESULT eDVBServicePlay::unpause()
1016 if (m_is_paused && m_decoder)
1019 return m_decoder->unfreeze();
1024 RESULT eDVBServicePlay::seekTo(pts_t to)
1026 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1028 if (!m_decode_demux)
1031 ePtr<iDVBPVRChannel> pvr_channel;
1033 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1039 m_cue->seekTo(0, to);
1043 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1045 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1047 if (!m_decode_demux)
1050 ePtr<iDVBPVRChannel> pvr_channel;
1052 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1057 /* HACK until we have skip-AP api */
1058 if ((to > 0) && (to < 100))
1066 m_cue->seekTo(mode, to);
1070 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1072 ePtr<iDVBPVRChannel> pvr_channel;
1074 if (!m_decode_demux)
1077 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1082 /* if there is a decoder, use audio or video PTS */
1085 r = m_decoder->getPTS(0, pos);
1091 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1094 RESULT eDVBServicePlay::setTrickmode(int trick)
1097 m_decoder->setTrickmode(trick);
1101 RESULT eDVBServicePlay::isCurrentlySeekable()
1103 return m_is_pvr || m_timeshift_active;
1106 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1112 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1118 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1124 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1130 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1136 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1139 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1140 (m_timeshift_enabled || !m_is_pvr))
1142 if (!m_timeshift_enabled)
1144 /* we need enough diskspace */
1146 if (statfs(TSPATH "/.", &fs) < 0)
1148 eDebug("statfs failed!");
1152 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1154 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1164 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1175 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1181 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1187 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1193 RESULT eDVBServicePlay::getName(std::string &name)
1197 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1198 return i->getName(m_reference, name);
1202 m_dvb_service->getName(m_reference, name);
1206 else if (!m_reference.name.empty())
1207 eStaticServiceDVBInformation().getName(m_reference, name);
1209 name = "DVB service";
1213 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1215 return m_event_handler.getEvent(evt, nownext);
1218 int eDVBServicePlay::getInfo(int w)
1220 eDVBServicePMTHandler::program program;
1223 return resIsPyObject;
1225 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1227 int no_program_info = 0;
1229 if (h.getProgramInfo(program))
1230 no_program_info = 1;
1234 #if HAVE_DVB_API_VERSION >= 3
1236 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1237 return m_videoEventData.height;
1240 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1241 return m_videoEventData.width;
1244 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1247 #if HAVE_DVB_API_VERSION >= 3
1248 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1249 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1252 #warning "FIXMEE implement sAspect for old DVB API"
1254 if (no_program_info)
1256 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1258 ePtr<eServiceEvent> evt;
1259 if (!m_event_handler.getEvent(evt, 0))
1261 ePtr<eComponentData> data;
1262 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1264 if ( data->getStreamContent() == 1 )
1266 switch(data->getComponentType())
1269 case 1: // 4:3 SD PAL
1271 case 3: // 16:9 SD PAL
1272 case 4: // > 16:9 PAL
1273 case 5: // 4:3 SD NTSC
1275 case 7: // 16:9 SD NTSC
1276 case 8: // > 16:9 NTSC
1279 case 9: // 4:3 HD PAL
1281 case 0xB: // 16:9 HD PAL
1282 case 0xC: // > 16:9 HD PAL
1283 case 0xD: // 4:3 HD NTSC
1285 case 0xF: // 16:9 HD NTSC
1286 case 0x10: // > 16:9 HD PAL
1287 return data->getComponentType();
1294 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1295 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1296 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1297 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1298 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1299 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1300 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1301 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1302 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1303 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1304 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1305 case sProvider: if (!m_dvb_service) return -1; return -2;
1306 case sServiceref: return resIsString;
1307 case sDVBState: return m_tune_state;
1313 std::string eDVBServicePlay::getInfoString(int w)
1318 if (!m_dvb_service) return "";
1319 return m_dvb_service->m_provider_name;
1321 return m_reference.toString();
1325 return iServiceInformation::getInfoString(w);
1328 PyObject *eDVBServicePlay::getInfoObject(int w)
1333 return m_service_handler.getCaIds();
1337 return iServiceInformation::getInfoObject(w);
1340 int eDVBServicePlay::getNumberOfTracks()
1342 eDVBServicePMTHandler::program program;
1343 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1344 if (h.getProgramInfo(program))
1346 return program.audioStreams.size();
1349 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1351 int ret = selectAudioStream(i);
1353 if (m_decoder->start())
1359 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1361 eDVBServicePMTHandler::program program;
1362 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1364 if (h.getProgramInfo(program))
1367 if (i >= program.audioStreams.size())
1370 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1371 info.m_description = "MPEG";
1372 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1373 info.m_description = "AC3";
1374 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1375 info.m_description = "AAC";
1376 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1377 info.m_description = "DTS";
1379 info.m_description = "???";
1381 if (program.audioStreams[i].component_tag != -1)
1383 ePtr<eServiceEvent> evt;
1384 if (!m_event_handler.getEvent(evt, 0))
1386 ePtr<eComponentData> data;
1387 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1388 info.m_language = data->getText();
1392 if (info.m_language.empty())
1393 info.m_language = program.audioStreams[i].language_code;
1398 int eDVBServicePlay::selectAudioStream(int i)
1400 eDVBServicePMTHandler::program program;
1401 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1403 if (h.getProgramInfo(program))
1406 if ((unsigned int)i >= program.audioStreams.size())
1412 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1415 if (m_radiotext_parser)
1416 m_radiotext_parser->start(program.audioStreams[i].pid);
1418 if (m_dvb_service && !m_is_pvr)
1420 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1422 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1423 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1427 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1428 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1432 h.resetCachedProgram();
1437 int eDVBServicePlay::getCurrentChannel()
1439 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1442 RESULT eDVBServicePlay::selectChannel(int i)
1444 if (i < LEFT || i > RIGHT || i == STEREO)
1447 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1449 m_decoder->setAudioChannel(i);
1453 std::string eDVBServicePlay::getRadioText(int x)
1455 if (m_radiotext_parser)
1459 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1464 void eDVBServicePlay::radioTextUpdated()
1466 m_event((iPlayableService*)this, evUpdatedRadioText);
1469 int eDVBServiceBase::getFrontendInfo(int w)
1471 eUsePtr<iDVBChannel> channel;
1472 if(m_service_handler.getChannel(channel))
1474 ePtr<iDVBFrontend> fe;
1475 if(channel->getFrontend(fe))
1477 return fe->readFrontendData(w);
1480 PyObject *eDVBServiceBase::getFrontendData(bool original)
1484 eUsePtr<iDVBChannel> channel;
1485 if(!m_service_handler.getChannel(channel))
1487 ePtr<iDVBFrontend> fe;
1488 if(!channel->getFrontend(fe))
1490 ret = fe->readTransponderData(original);
1493 ePtr<iDVBFrontendParameters> feparm;
1494 channel->getCurrentFrontendParameters(feparm);
1497 eDVBFrontendParametersSatellite osat;
1498 if (!feparm->getDVBS(osat))
1500 void PutToDict(ePyObject &, const char*, long);
1501 void PutToDict(ePyObject &, const char*, const char*);
1502 PutToDict(ret, "orbital_position", osat.orbital_position);
1503 const char *tmp = "UNKNOWN";
1504 switch(osat.polarisation)
1506 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1507 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1508 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1509 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1512 PutToDict(ret, "polarization", tmp);
1526 int eDVBServicePlay::getNumberOfSubservices()
1528 ePtr<eServiceEvent> evt;
1529 if (!m_event_handler.getEvent(evt, 0))
1530 return evt->getNumOfLinkageServices();
1534 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1536 ePtr<eServiceEvent> evt;
1537 if (!m_event_handler.getEvent(evt, 0))
1539 if (!evt->getLinkageService(sub, m_reference, n))
1542 sub.type=eServiceReference::idInvalid;
1546 RESULT eDVBServicePlay::startTimeshift()
1548 ePtr<iDVBDemux> demux;
1550 eDebug("Start timeshift!");
1552 if (m_timeshift_enabled)
1555 /* start recording with the data demux. */
1556 if (m_service_handler.getDataDemux(demux))
1559 demux->createTSRecorder(m_record);
1563 char templ[]=TSPATH "/timeshift.XXXXXX";
1564 m_timeshift_fd = mkstemp(templ);
1565 m_timeshift_file = templ;
1567 eDebug("recording to %s", templ);
1569 if (m_timeshift_fd < 0)
1575 m_record->setTargetFD(m_timeshift_fd);
1577 m_timeshift_enabled = 1;
1579 updateTimeshiftPids();
1585 RESULT eDVBServicePlay::stopTimeshift()
1587 if (!m_timeshift_enabled)
1592 m_timeshift_enabled = 0;
1597 close(m_timeshift_fd);
1598 eDebug("remove timeshift file");
1599 remove(m_timeshift_file.c_str());
1604 int eDVBServicePlay::isTimeshiftActive()
1606 return m_timeshift_enabled && m_timeshift_active;
1609 RESULT eDVBServicePlay::activateTimeshift()
1611 if (!m_timeshift_enabled)
1614 if (!m_timeshift_active)
1616 switchToTimeshift();
1623 PyObject *eDVBServicePlay::getCutList()
1625 ePyObject list = PyList_New(0);
1627 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1629 ePyObject tuple = PyTuple_New(2);
1630 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1631 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1632 PyList_Append(list, tuple);
1639 void eDVBServicePlay::setCutList(ePyObject list)
1641 if (!PyList_Check(list))
1643 int size = PyList_Size(list);
1646 m_cue_entries.clear();
1648 for (i=0; i<size; ++i)
1650 ePyObject tuple = PyList_GET_ITEM(list, i);
1651 if (!PyTuple_Check(tuple))
1653 eDebug("non-tuple in cutlist");
1656 if (PyTuple_Size(tuple) != 2)
1658 eDebug("cutlist entries need to be a 2-tuple");
1661 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1662 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1664 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1667 pts_t pts = PyLong_AsLongLong(ppts);
1668 int type = PyInt_AsLong(ptype);
1669 m_cue_entries.insert(cueEntry(pts, type));
1670 eDebug("adding %08llx, %d", pts, type);
1672 m_cuesheet_changed = 1;
1674 cutlistToCuesheet();
1675 m_event((iPlayableService*)this, evCuesheetChanged);
1678 void eDVBServicePlay::setCutListEnable(int enable)
1680 m_cutlist_enabled = enable;
1681 cutlistToCuesheet();
1684 void eDVBServicePlay::updateTimeshiftPids()
1689 eDVBServicePMTHandler::program program;
1690 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1692 if (h.getProgramInfo(program))
1696 std::set<int> pids_to_record;
1697 pids_to_record.insert(0); // PAT
1698 if (program.pmtPid != -1)
1699 pids_to_record.insert(program.pmtPid); // PMT
1701 if (program.textPid != -1)
1702 pids_to_record.insert(program.textPid); // Videotext
1704 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1705 i(program.videoStreams.begin());
1706 i != program.videoStreams.end(); ++i)
1707 pids_to_record.insert(i->pid);
1709 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1710 i(program.audioStreams.begin());
1711 i != program.audioStreams.end(); ++i)
1712 pids_to_record.insert(i->pid);
1714 std::set<int> new_pids, obsolete_pids;
1716 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1717 m_pids_active.begin(), m_pids_active.end(),
1718 std::inserter(new_pids, new_pids.begin()));
1720 std::set_difference(
1721 m_pids_active.begin(), m_pids_active.end(),
1722 pids_to_record.begin(), pids_to_record.end(),
1723 std::inserter(new_pids, new_pids.begin())
1726 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1727 m_record->addPID(*i);
1729 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1730 m_record->removePID(*i);
1734 void eDVBServicePlay::switchToLive()
1736 if (!m_timeshift_active)
1742 m_teletext_parser = 0;
1743 m_radiotext_parser = 0;
1744 m_subtitle_parser = 0;
1745 m_new_dvb_subtitle_page_connection = 0;
1746 m_new_subtitle_page_connection = 0;
1747 m_radiotext_updated_connection = 0;
1749 /* free the timeshift service handler, we need the resources */
1750 m_service_handler_timeshift.free();
1751 m_timeshift_active = 0;
1753 m_event((iPlayableService*)this, evSeekableStatusChanged);
1758 void eDVBServicePlay::switchToTimeshift()
1760 if (m_timeshift_active)
1765 m_teletext_parser = 0;
1766 m_radiotext_parser = 0;
1767 m_subtitle_parser = 0;
1768 m_new_subtitle_page_connection = 0;
1769 m_new_dvb_subtitle_page_connection = 0;
1770 m_radiotext_updated_connection = 0;
1772 m_timeshift_active = 1;
1774 m_event((iPlayableService*)this, evSeekableStatusChanged);
1776 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1777 r.path = m_timeshift_file;
1779 m_cue = new eCueSheet();
1780 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1781 updateDecoder(); /* mainly to switch off PCR */
1784 void eDVBServicePlay::updateDecoder()
1786 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1788 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1790 bool defaultac3=false;
1791 std::string default_ac3;
1793 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1794 defaultac3 = default_ac3 == "True";
1796 eDVBServicePMTHandler::program program;
1797 if (h.getProgramInfo(program))
1798 eDebug("getting program info failed.");
1801 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1802 if (!program.videoStreams.empty())
1804 eDebugNoNewLine(" (");
1805 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1806 i(program.videoStreams.begin());
1807 i != program.videoStreams.end(); ++i)
1814 if (i != program.videoStreams.begin())
1815 eDebugNoNewLine(", ");
1816 eDebugNoNewLine("%04x", i->pid);
1818 eDebugNoNewLine(")");
1820 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1821 if (!program.audioStreams.empty())
1823 eDebugNoNewLine(" (");
1824 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1825 i(program.audioStreams.begin());
1826 i != program.audioStreams.end(); ++i)
1828 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1830 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1836 if (i != program.audioStreams.begin())
1837 eDebugNoNewLine(", ");
1838 eDebugNoNewLine("%04x", i->pid);
1840 eDebugNoNewLine(")");
1842 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1843 pcrpid = program.pcrPid;
1844 eDebug(", and the text pid is %04x", program.textPid);
1845 tpid = program.textPid;
1850 h.getDecodeDemux(m_decode_demux);
1853 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1855 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
1858 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1859 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1860 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1861 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1862 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
1869 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1870 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1871 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1873 else // subservice or recording
1875 eServiceReferenceDVB ref;
1876 m_service_handler.getServiceReference(ref);
1877 eServiceReferenceDVB parent = ref.getParentServiceReference();
1882 ePtr<eDVBResourceManager> res_mgr;
1883 if (!eDVBResourceManager::getInstance(res_mgr))
1885 ePtr<iDVBChannelList> db;
1886 if (!res_mgr->getChannelList(db))
1888 ePtr<eDVBService> origService;
1889 if (!db->getService(parent, origService))
1891 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1892 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1898 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1899 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1901 m_decoder->setVideoPID(vpid, vpidtype);
1902 m_decoder->setAudioPID(apid, apidtype);
1903 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1905 m_decoder->setSyncPCR(pcrpid);
1908 ePtr<iDVBDemux> data_demux;
1909 if (!h.getDataDemux(data_demux))
1911 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1912 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1913 m_radiotext_parser->start(apid);
1918 m_decoder->setSyncPCR(-1);
1920 m_decoder->setTextPID(tpid);
1922 m_teletext_parser->start(program.textPid);
1925 m_decoder->setTrickmode(1);
1929 if (vpid > 0 && vpid < 0x2000)
1933 std::string radio_pic;
1934 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1935 m_decoder->setRadioPic(radio_pic);
1938 m_decoder->setAudioChannel(achannel);
1940 // how we can do this better?
1941 // update cache pid when the user changed the audio track or video track
1942 // TODO handling of difference audio types.. default audio types..
1944 /* don't worry about non-existing services, nor pvr services */
1945 if (m_dvb_service && !m_is_pvr)
1947 if (apidtype == eDVBAudio::aMPEG)
1949 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1950 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1954 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1955 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1957 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1958 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1959 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1960 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1963 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1966 void eDVBServicePlay::loadCuesheet()
1968 std::string filename = m_reference.path + ".cuts";
1970 m_cue_entries.clear();
1972 FILE *f = fopen(filename.c_str(), "rb");
1976 eDebug("loading cuts..");
1979 unsigned long long where;
1982 if (!fread(&where, sizeof(where), 1, f))
1984 if (!fread(&what, sizeof(what), 1, f))
1987 #if BYTE_ORDER == LITTLE_ENDIAN
1988 where = bswap_64(where);
1995 m_cue_entries.insert(cueEntry(where, what));
1998 eDebug("%d entries", m_cue_entries.size());
2000 eDebug("cutfile not found!");
2002 m_cuesheet_changed = 0;
2003 cutlistToCuesheet();
2004 m_event((iPlayableService*)this, evCuesheetChanged);
2007 void eDVBServicePlay::saveCuesheet()
2009 std::string filename = m_reference.path + ".cuts";
2011 FILE *f = fopen(filename.c_str(), "wb");
2015 unsigned long long where;
2018 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2020 #if BYTE_ORDER == BIG_ENDIAN
2023 where = bswap_64(i->where);
2025 what = htonl(i->what);
2026 fwrite(&where, sizeof(where), 1, f);
2027 fwrite(&what, sizeof(what), 1, f);
2033 m_cuesheet_changed = 0;
2036 void eDVBServicePlay::cutlistToCuesheet()
2040 eDebug("no cue sheet");
2045 if (!m_cutlist_enabled)
2047 m_cue->commitSpans();
2048 eDebug("cutlists were disabled");
2052 pts_t in = 0, out = 0, length = 0;
2056 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2060 if (i == m_cue_entries.end())
2063 if (i->what == 0) /* in */
2067 } else if (i->what == 1) /* out */
2069 else /* mark (2) or last play position (3) */
2077 m_cue->addSourceSpan(in, out);
2081 if (i == m_cue_entries.end())
2084 m_cue->commitSpans();
2087 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2089 if (m_subtitle_widget)
2090 disableSubtitles(parent);
2093 int tuplesize = PyTuple_Size(tuple);
2096 if (!PyTuple_Check(tuple))
2102 entry = PyTuple_GET_ITEM(tuple, 0);
2104 if (!PyInt_Check(entry))
2107 type = PyInt_AsLong(entry);
2109 if (type == 1) // teletext subtitles
2111 int page, magazine, pid;
2115 if (!m_teletext_parser)
2117 eDebug("enable teletext subtitles.. no parser !!!");
2121 entry = PyTuple_GET_ITEM(tuple, 1);
2122 if (!PyInt_Check(entry))
2124 pid = PyInt_AsLong(entry);
2126 entry = PyTuple_GET_ITEM(tuple, 2);
2127 if (!PyInt_Check(entry))
2129 page = PyInt_AsLong(entry);
2131 entry = PyTuple_GET_ITEM(tuple, 3);
2132 if (!PyInt_Check(entry))
2134 magazine = PyInt_AsLong(entry);
2136 m_subtitle_widget = new eSubtitleWidget(parent);
2137 m_subtitle_widget->resize(parent->size()); /* full size */
2138 m_teletext_parser->setPageAndMagazine(page, magazine);
2140 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2144 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2145 if (!m_subtitle_parser)
2147 eDebug("enable dvb subtitles.. no parser !!!");
2153 entry = PyTuple_GET_ITEM(tuple, 1);
2154 if (!PyInt_Check(entry))
2156 pid = PyInt_AsLong(entry);
2158 entry = PyTuple_GET_ITEM(tuple, 2);
2159 if (!PyInt_Check(entry))
2161 composition_page_id = PyInt_AsLong(entry);
2163 entry = PyTuple_GET_ITEM(tuple, 3);
2164 if (!PyInt_Check(entry))
2166 ancillary_page_id = PyInt_AsLong(entry);
2168 m_subtitle_widget = new eSubtitleWidget(parent);
2169 m_subtitle_widget->resize(parent->size()); /* full size */
2170 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2172 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2178 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2179 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2180 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2184 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2186 delete m_subtitle_widget;
2187 m_subtitle_widget = 0;
2188 if (m_subtitle_parser)
2190 m_subtitle_parser->stop();
2191 m_dvb_subtitle_pages.clear();
2193 if (m_teletext_parser)
2195 m_teletext_parser->setPageAndMagazine(-1, -1);
2196 m_subtitle_pages.clear();
2199 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2203 PyObject *eDVBServicePlay::getCachedSubtitle()
2207 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2210 unsigned int data = (unsigned int)tmp;
2211 int pid = (data&0xFFFF0000)>>16;
2212 ePyObject tuple = PyTuple_New(4);
2213 eDVBServicePMTHandler::program program;
2214 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2215 if (!h.getProgramInfo(program))
2217 if (program.textPid==pid) // teletext
2218 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2220 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2221 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2222 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2223 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2232 PyObject *eDVBServicePlay::getSubtitleList()
2234 if (!m_teletext_parser)
2240 ePyObject l = PyList_New(0);
2241 std::set<int> added_ttx_pages;
2243 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2244 m_teletext_parser->m_found_subtitle_pages;
2246 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2247 eDVBServicePMTHandler::program program;
2248 if (h.getProgramInfo(program))
2249 eDebug("getting program info failed.");
2252 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2253 it != program.subtitleStreams.end(); ++it)
2255 switch(it->subtitling_type)
2257 case 0x01: // ebu teletext subtitles
2259 int page_number = it->teletext_page_number & 0xFF;
2260 int magazine_number = it->teletext_magazine_number & 7;
2261 int hash = magazine_number << 8 | page_number;
2262 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2264 ePyObject tuple = PyTuple_New(5);
2265 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2266 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2267 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2268 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2269 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2270 PyList_Append(l, tuple);
2272 added_ttx_pages.insert(hash);
2277 case 0x20 ... 0x23: // dvb subtitles
2279 ePyObject tuple = PyTuple_New(5);
2280 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2281 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2282 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2283 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2284 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2285 PyList_Insert(l, 0, tuple);
2293 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2294 it != subs.end(); ++it)
2296 int page_number = it->teletext_page_number & 0xFF;
2297 int magazine_number = it->teletext_magazine_number & 7;
2298 int hash = magazine_number << 8 | page_number;
2299 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2301 ePyObject tuple = PyTuple_New(5);
2302 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2303 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2304 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2305 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2306 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2307 PyList_Append(l, tuple);
2315 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2317 if (m_subtitle_widget)
2319 m_subtitle_pages.push_back(page);
2320 checkSubtitleTiming();
2324 void eDVBServicePlay::checkSubtitleTiming()
2326 // eDebug("checkSubtitleTiming");
2327 if (!m_subtitle_widget)
2331 enum { TELETEXT, DVB } type;
2332 eDVBTeletextSubtitlePage page;
2333 eDVBSubtitlePage dvb_page;
2335 if (!m_subtitle_pages.empty())
2337 page = m_subtitle_pages.front();
2339 show_time = page.m_pts;
2341 else if (!m_dvb_subtitle_pages.empty())
2343 dvb_page = m_dvb_subtitle_pages.front();
2345 show_time = dvb_page.m_show_time;
2353 m_decoder->getPTS(0, pos);
2355 // eDebug("%lld %lld", pos, show_time);
2356 int diff = show_time - pos;
2359 eDebug("[late (%d ms)]", -diff / 90);
2364 eDebug("[invalid]");
2370 if (type == TELETEXT)
2372 eDebug("display teletext subtitle page");
2373 m_subtitle_widget->setPage(page);
2374 m_subtitle_pages.pop_front();
2378 eDebug("display dvb subtitle Page");
2379 m_subtitle_widget->setPage(dvb_page);
2380 m_dvb_subtitle_pages.pop_front();
2384 // eDebug("start subtitle delay %d", diff / 90);
2385 m_subtitle_sync_timer.start(diff / 90, 1);
2391 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2393 if (m_subtitle_widget)
2395 m_dvb_subtitle_pages.push_back(p);
2396 checkSubtitleTiming();
2400 int eDVBServicePlay::getAC3Delay()
2403 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2405 return m_decoder->getAC3Delay();
2410 int eDVBServicePlay::getPCMDelay()
2413 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2415 return m_decoder->getPCMDelay();
2420 void eDVBServicePlay::setAC3Delay(int delay)
2423 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2425 m_decoder->setAC3Delay(delay);
2428 void eDVBServicePlay::setPCMDelay(int delay)
2431 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2433 m_decoder->setPCMDelay(delay);
2436 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2438 eDebug("!!!!!!!!!! Video Event type %d, aspect %d, %dx%d", event.type, event.aspect, event.width, event.height);
2439 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2440 m_event((iPlayableService*)this, evVideoSizeChanged);
2443 DEFINE_REF(eDVBServicePlay)
2445 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");