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 int tmp=res->canAllocateChannel(chid, chid_ignore);
176 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
179 m_playable_service = *it;
186 m_playable_service = eServiceReference();
190 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
195 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
197 DECLARE_REF(eStaticServiceDVBPVRInformation);
198 eServiceReference m_ref;
199 eDVBMetaParser m_parser;
201 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
202 RESULT getName(const eServiceReference &ref, std::string &name);
203 int getLength(const eServiceReference &ref);
204 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
205 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
206 int getInfo(const eServiceReference &ref, int w);
207 std::string getInfoString(const eServiceReference &ref,int w);
210 DEFINE_REF(eStaticServiceDVBPVRInformation);
212 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
215 m_parser.parseFile(ref.path);
218 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
220 ASSERT(ref == m_ref);
221 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
225 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
227 ASSERT(ref == m_ref);
231 if (tstools.openFile(ref.path.c_str()))
235 if (tstools.calcLen(len))
241 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
245 case iServiceInformation::sDescription:
246 return iServiceInformation::resIsString;
247 case iServiceInformation::sServiceref:
248 return iServiceInformation::resIsString;
249 case iServiceInformation::sTimeCreate:
250 if (m_parser.m_time_create)
251 return m_parser.m_time_create;
253 return iServiceInformation::resNA;
255 return iServiceInformation::resNA;
259 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
263 case iServiceInformation::sDescription:
264 return m_parser.m_description;
265 case iServiceInformation::sServiceref:
266 return m_parser.m_ref.toString();
267 case iServiceInformation::sTags:
268 return m_parser.m_tags;
274 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
276 if (!ref.path.empty())
278 ePtr<eServiceEvent> event = new eServiceEvent;
279 std::string filename = ref.path;
280 filename.erase(filename.length()-2, 2);
282 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
292 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
294 DECLARE_REF(eDVBPVRServiceOfflineOperations);
295 eServiceReferenceDVB m_ref;
297 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
299 RESULT deleteFromDisk(int simulate);
300 RESULT getListOfFilenames(std::list<std::string> &);
303 DEFINE_REF(eDVBPVRServiceOfflineOperations);
305 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
309 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
315 std::list<std::string> res;
316 if (getListOfFilenames(res))
319 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
321 eDebug("FATAL !! can't get background file eraser");
323 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
325 eDebug("Removing %s...", i->c_str());
327 eraser->erase(i->c_str());
329 ::unlink(i->c_str());
336 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
339 res.push_back(m_ref.path);
341 // handling for old splitted recordings (enigma 1)
346 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
348 if (stat(buf, &s) < 0)
353 res.push_back(m_ref.path + ".meta");
354 res.push_back(m_ref.path + ".ap");
355 res.push_back(m_ref.path + ".cuts");
356 std::string tmp = m_ref.path;
357 tmp.erase(m_ref.path.length()-3);
358 res.push_back(tmp + ".eit");
362 DEFINE_REF(eServiceFactoryDVB)
364 eServiceFactoryDVB::eServiceFactoryDVB()
366 ePtr<eServiceCenter> sc;
368 eServiceCenter::getPrivInstance(sc);
370 sc->addServiceFactory(eServiceFactoryDVB::id, this);
372 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
373 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
376 eServiceFactoryDVB::~eServiceFactoryDVB()
378 ePtr<eServiceCenter> sc;
380 eServiceCenter::getPrivInstance(sc);
382 sc->removeServiceFactory(eServiceFactoryDVB::id);
385 DEFINE_REF(eDVBServiceList);
387 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
391 eDVBServiceList::~eDVBServiceList()
395 RESULT eDVBServiceList::startQuery()
397 ePtr<iDVBChannelList> db;
398 ePtr<eDVBResourceManager> res;
401 if ((err = eDVBResourceManager::getInstance(res)) != 0)
403 eDebug("no resource manager");
406 if ((err = res->getChannelList(db)) != 0)
408 eDebug("no channel list");
412 ePtr<eDVBChannelQuery> q;
414 if (!m_parent.path.empty())
416 eDVBChannelQuery::compile(q, m_parent.path);
419 eDebug("compile query failed");
424 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
426 eDebug("startQuery failed");
433 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
435 eServiceReferenceDVB ref;
440 while (!m_query->getNextResult(ref))
444 list.sort(iListableServiceCompare(this));
449 // The first argument of this function is a format string to specify the order and
450 // the content of the returned list
451 // useable format options are
452 // R = Service Reference (as swig object .. this is very slow)
453 // S = Service Reference (as python string object .. same as ref.toString())
454 // C = Service Reference (as python string object .. same as ref.toCompareString())
455 // N = Service Name (as python string object)
456 // when exactly one return value per service is selected in the format string,
457 // then each value is directly a list entry
458 // when more than one value is returned per service, then the list is a list of
460 // unknown format string chars are returned as python None values !
461 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
464 std::list<eServiceReference> tmplist;
467 if (!format || !(retcount=strlen(format)))
468 format = "R"; // just return service reference swig object ...
470 if (!getContent(tmplist, sorted))
472 int services=tmplist.size();
473 ePtr<iStaticServiceInformation> sptr;
474 eServiceCenterPtr service_center;
476 if (strchr(format, 'N'))
477 eServiceCenter::getPrivInstance(service_center);
479 ret = PyList_New(services);
480 std::list<eServiceReference>::iterator it(tmplist.begin());
482 for (int cnt=0; cnt < services; ++cnt)
484 eServiceReference &ref=*it++;
485 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
486 for (int i=0; i < retcount; ++i)
491 case 'R': // service reference (swig)object
492 tmp = NEW_eServiceReference(ref);
494 case 'C': // service reference compare string
495 tmp = PyString_FromString(ref.toCompareString().c_str());
497 case 'S': // service reference string
498 tmp = PyString_FromString(ref.toString().c_str());
500 case 'N': // service name
503 service_center->info(ref, sptr);
507 sptr->getName(ref, name);
509 tmp = PyString_FromString(name.c_str());
513 tmp = PyString_FromString("<n/a>");
526 PyTuple_SET_ITEM(tuple, i, tmp);
528 PyList_SET_ITEM(ret, cnt, tmp);
532 PyList_SET_ITEM(ret, cnt, tuple);
535 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
538 RESULT eDVBServiceList::getNext(eServiceReference &ref)
543 return m_query->getNextResult((eServiceReferenceDVB&)ref);
546 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
548 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
550 ePtr<iDVBChannelList> db;
551 ePtr<eDVBResourceManager> resm;
553 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
556 if (db->getBouquet(m_parent, m_bouquet) != 0)
567 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
571 return m_bouquet->addService(ref, before);
574 RESULT eDVBServiceList::removeService(eServiceReference &ref)
578 return m_bouquet->removeService(ref);
581 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
585 return m_bouquet->moveService(ref, pos);
588 RESULT eDVBServiceList::flushChanges()
592 return m_bouquet->flushChanges();
595 RESULT eDVBServiceList::setListName(const std::string &name)
599 return m_bouquet->setListName(name);
602 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
604 ePtr<eDVBService> service;
605 int r = lookupService(service, ref);
608 // check resources...
609 ptr = new eDVBServicePlay(ref, service);
613 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
615 if (ref.path.empty())
617 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
626 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
628 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
629 if (list->startQuery())
639 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
641 /* is a listable service? */
642 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
644 if ( !ref.name.empty() ) // satellites or providers list
645 ptr = m_StaticServiceDVBInfo;
646 else // a dvb bouquet
647 ptr = m_StaticServiceDVBBouquetInfo;
649 else if (!ref.path.empty()) /* do we have a PVR service? */
650 ptr = new eStaticServiceDVBPVRInformation(ref);
651 else // normal dvb service
653 ePtr<eDVBService> service;
654 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
655 ptr = m_StaticServiceDVBInfo;
657 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
663 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
665 if (ref.path.empty())
671 ptr = new eDVBPVRServiceOfflineOperations(ref);
676 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
678 // TODO: handle the listing itself
679 // if (ref.... == -1) .. return "... bouquets ...";
680 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
682 ePtr<iDVBChannelList> db;
683 ePtr<eDVBResourceManager> res;
686 if ((err = eDVBResourceManager::getInstance(res)) != 0)
688 eDebug("no resource manager");
691 if ((err = res->getChannelList(db)) != 0)
693 eDebug("no channel list");
697 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
698 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
700 eDebug("getService failed!");
707 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
708 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
711 m_is_pvr = !m_reference.path.empty();
713 m_timeshift_enabled = m_timeshift_active = 0;
716 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
717 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
718 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
720 m_cuesheet_changed = 0;
721 m_cutlist_enabled = 1;
723 m_subtitle_widget = 0;
725 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
728 eDVBServicePlay::~eDVBServicePlay()
730 delete m_subtitle_widget;
733 void eDVBServicePlay::gotNewEvent()
737 ePtr<eServiceEvent> m_event_now, m_event_next;
738 getEvent(m_event_now, 0);
739 getEvent(m_event_next, 1);
742 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
744 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
746 m_event((iPlayableService*)this, evUpdatedEventInfo);
749 void eDVBServicePlay::serviceEvent(int event)
753 case eDVBServicePMTHandler::eventTuned:
755 ePtr<iDVBDemux> m_demux;
756 if (!m_service_handler.getDataDemux(m_demux))
758 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
759 int sid = ref.getParentServiceID().get();
761 sid = ref.getServiceID().get();
762 if ( ref.getParentTransportStreamID().get() &&
763 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
764 m_event_handler.startOther(m_demux, sid);
766 m_event_handler.start(m_demux, sid);
770 case eDVBServicePMTHandler::eventTuneFailed:
772 eDebug("DVB service failed to tune");
773 m_event((iPlayableService*)this, evTuneFailed);
776 case eDVBServicePMTHandler::eventNewProgramInfo:
778 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
779 if (m_timeshift_enabled)
780 updateTimeshiftPids();
781 if (!m_timeshift_active)
783 if (m_first_program_info && m_is_pvr)
785 m_first_program_info = 0;
788 m_event((iPlayableService*)this, evUpdatedInfo);
791 case eDVBServicePMTHandler::eventEOF:
792 m_event((iPlayableService*)this, evEOF);
794 case eDVBServicePMTHandler::eventSOF:
795 m_event((iPlayableService*)this, evSOF);
800 void eDVBServicePlay::serviceEventTimeshift(int event)
804 case eDVBServicePMTHandler::eventNewProgramInfo:
805 if (m_timeshift_active)
808 case eDVBServicePMTHandler::eventSOF:
809 m_event((iPlayableService*)this, evSOF);
811 case eDVBServicePMTHandler::eventEOF:
817 RESULT eDVBServicePlay::start()
820 /* in pvr mode, we only want to use one demux. in tv mode, we're using
821 two (one for decoding, one for data source), as we must be prepared
822 to start recording from the data demux. */
824 m_cue = new eCueSheet();
826 m_first_program_info = 1;
827 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
828 r = m_service_handler.tune(service, m_is_pvr, m_cue);
830 /* inject EIT if there is a stored one */
833 std::string filename = service.path;
834 filename.erase(filename.length()-2, 2);
836 ePtr<eServiceEvent> event = new eServiceEvent;
837 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
839 ePtr<eServiceEvent> empty;
840 m_event_handler.inject(event, 0);
841 m_event_handler.inject(empty, 1);
848 m_event(this, evStart);
849 m_event((iPlayableService*)this, evSeekableStatusChanged);
853 RESULT eDVBServicePlay::stop()
855 /* add bookmark for last play position */
859 if (!getPlayPosition(play_position))
861 /* remove last position */
862 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
864 if (i->what == 3) /* current play position */
866 m_cue_entries.erase(i);
867 i = m_cue_entries.begin();
873 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
874 m_cuesheet_changed = 1;
878 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
880 m_service_handler_timeshift.free();
881 m_service_handler.free();
883 if (m_is_pvr && m_cuesheet_changed)
886 /* save cuesheet only when main file is accessible. */
887 if (!::stat(m_reference.path.c_str(), &s))
894 RESULT eDVBServicePlay::setTarget(int target)
896 m_is_primary = !target;
900 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
902 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
906 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
908 /* note: we check for timeshift to be enabled,
909 not neccessary active. if you pause when timeshift
910 is not active, you should activate it when unpausing */
911 if ((!m_is_pvr) && (!m_timeshift_enabled))
921 RESULT eDVBServicePlay::setSlowMotion(int ratio)
924 return m_decoder->setSlowMotion(ratio);
929 RESULT eDVBServicePlay::setFastForward(int ratio)
931 int skipmode, ffratio;
937 } else if (ratio > 0)
945 } else // if (ratio < 0)
951 if (m_skipmode != skipmode)
953 eDebug("setting cue skipmode to %d", skipmode);
955 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
958 m_skipmode = skipmode;
963 return m_decoder->setFastForward(ffratio);
966 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
968 if (m_is_pvr || m_timeshift_enabled)
978 /* TODO: when timeshift is enabled but not active, this doesn't work. */
979 RESULT eDVBServicePlay::getLength(pts_t &len)
981 ePtr<iDVBPVRChannel> pvr_channel;
983 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
986 return pvr_channel->getLength(len);
989 RESULT eDVBServicePlay::pause()
991 if (!m_is_paused && m_decoder)
994 return m_decoder->freeze(0);
999 RESULT eDVBServicePlay::unpause()
1001 if (m_is_paused && m_decoder)
1004 return m_decoder->unfreeze();
1009 RESULT eDVBServicePlay::seekTo(pts_t to)
1011 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1013 if (!m_decode_demux)
1016 ePtr<iDVBPVRChannel> pvr_channel;
1018 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1024 m_cue->seekTo(0, to);
1028 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1030 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1032 if (!m_decode_demux)
1035 ePtr<iDVBPVRChannel> pvr_channel;
1037 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1042 /* HACK until we have skip-AP api */
1043 if ((to > 0) && (to < 100))
1051 m_cue->seekTo(mode, to);
1055 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1057 ePtr<iDVBPVRChannel> pvr_channel;
1059 if (!m_decode_demux)
1062 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1067 /* if there is a decoder, use audio or video PTS */
1070 r = m_decoder->getPTS(0, pos);
1076 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1079 RESULT eDVBServicePlay::setTrickmode(int trick)
1082 m_decoder->setTrickmode(trick);
1086 RESULT eDVBServicePlay::isCurrentlySeekable()
1088 return m_is_pvr || m_timeshift_active;
1091 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1097 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1103 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1109 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1115 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1121 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1124 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1125 (m_timeshift_enabled || !m_is_pvr))
1127 if (!m_timeshift_enabled)
1129 /* we need enough diskspace */
1131 if (statfs(TSPATH "/.", &fs) < 0)
1133 eDebug("statfs failed!");
1137 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1139 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1149 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1160 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1166 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1172 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1178 RESULT eDVBServicePlay::getName(std::string &name)
1182 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1183 return i->getName(m_reference, name);
1187 m_dvb_service->getName(m_reference, name);
1191 else if (!m_reference.name.empty())
1192 eStaticServiceDVBInformation().getName(m_reference, name);
1194 name = "DVB service";
1198 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1200 return m_event_handler.getEvent(evt, nownext);
1203 int eDVBServicePlay::getInfo(int w)
1205 eDVBServicePMTHandler::program program;
1208 return resIsPyObject;
1210 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1212 if (h.getProgramInfo(program))
1218 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1220 ePtr<eServiceEvent> evt;
1221 if (!m_event_handler.getEvent(evt, 0))
1223 ePtr<eComponentData> data;
1224 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1226 if ( data->getStreamContent() == 1 )
1228 switch(data->getComponentType())
1231 case 1: // 4:3 SD PAL
1233 case 3: // 16:9 SD PAL
1234 case 4: // > 16:9 PAL
1235 case 5: // 4:3 SD NTSC
1237 case 7: // 16:9 SD NTSC
1238 case 8: // > 16:9 NTSC
1241 case 9: // 4:3 HD PAL
1243 case 0xB: // 16:9 HD PAL
1244 case 0xC: // > 16:9 HD PAL
1245 case 0xD: // 4:3 HD NTSC
1247 case 0xF: // 16:9 HD NTSC
1248 case 0x10: // > 16:9 HD PAL
1249 return data->getComponentType();
1256 case sIsCrypted: return program.isCrypted();
1257 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1258 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1259 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1260 case sPCRPID: return program.pcrPid;
1261 case sPMTPID: return program.pmtPid;
1262 case sTXTPID: return program.textPid;
1263 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1264 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1265 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1266 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1267 case sProvider: if (!m_dvb_service) return -1; return -2;
1268 case sServiceref: return resIsString;
1274 std::string eDVBServicePlay::getInfoString(int w)
1279 if (!m_dvb_service) return "";
1280 return m_dvb_service->m_provider_name;
1282 return m_reference.toString();
1286 return iServiceInformation::getInfoString(w);
1289 PyObject *eDVBServicePlay::getInfoObject(int w)
1294 return m_service_handler.getCaIds();
1298 return iServiceInformation::getInfoObject(w);
1301 int eDVBServicePlay::getNumberOfTracks()
1303 eDVBServicePMTHandler::program program;
1304 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1305 if (h.getProgramInfo(program))
1307 return program.audioStreams.size();
1310 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1312 int ret = selectAudioStream(i);
1314 if (m_decoder->start())
1320 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1322 eDVBServicePMTHandler::program program;
1323 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1325 if (h.getProgramInfo(program))
1328 if (i >= program.audioStreams.size())
1331 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1332 info.m_description = "MPEG";
1333 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1334 info.m_description = "AC3";
1335 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1336 info.m_description = "AAC";
1337 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1338 info.m_description = "DTS";
1340 info.m_description = "???";
1342 if (program.audioStreams[i].component_tag != -1)
1344 ePtr<eServiceEvent> evt;
1345 if (!m_event_handler.getEvent(evt, 0))
1347 ePtr<eComponentData> data;
1348 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1349 info.m_language = data->getText();
1353 if (info.m_language.empty())
1354 info.m_language = program.audioStreams[i].language_code;
1359 int eDVBServicePlay::selectAudioStream(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 ((unsigned int)i >= program.audioStreams.size())
1373 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1376 if (m_radiotext_parser)
1377 m_radiotext_parser->start(program.audioStreams[i].pid);
1379 if (m_dvb_service && !m_is_pvr)
1381 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1383 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1384 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1388 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1389 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1393 h.resetCachedProgram();
1398 int eDVBServicePlay::getCurrentChannel()
1400 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1403 RESULT eDVBServicePlay::selectChannel(int i)
1405 if (i < LEFT || i > RIGHT || i == STEREO)
1408 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1410 m_decoder->setAudioChannel(i);
1414 std::string eDVBServicePlay::getRadioText(int x)
1416 if (m_radiotext_parser)
1420 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1425 void eDVBServicePlay::radioTextUpdated()
1427 m_event((iPlayableService*)this, evUpdatedRadioText);
1430 int eDVBServiceBase::getFrontendInfo(int w)
1432 eUsePtr<iDVBChannel> channel;
1433 if(m_service_handler.getChannel(channel))
1435 ePtr<iDVBFrontend> fe;
1436 if(channel->getFrontend(fe))
1438 return fe->readFrontendData(w);
1441 PyObject *eDVBServiceBase::getFrontendData(bool original)
1445 eUsePtr<iDVBChannel> channel;
1446 if(!m_service_handler.getChannel(channel))
1448 ePtr<iDVBFrontend> fe;
1449 if(!channel->getFrontend(fe))
1451 ret = fe->readTransponderData(original);
1454 ePtr<iDVBFrontendParameters> feparm;
1455 channel->getCurrentFrontendParameters(feparm);
1458 eDVBFrontendParametersSatellite osat;
1459 if (!feparm->getDVBS(osat))
1461 void PutToDict(ePyObject &, const char*, long);
1462 void PutToDict(ePyObject &, const char*, const char*);
1463 PutToDict(ret, "orbital_position", osat.orbital_position);
1464 const char *tmp = "UNKNOWN";
1465 switch(osat.polarisation)
1467 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1468 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1469 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1470 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1473 PutToDict(ret, "polarization", tmp);
1487 int eDVBServicePlay::getNumberOfSubservices()
1489 ePtr<eServiceEvent> evt;
1490 if (!m_event_handler.getEvent(evt, 0))
1491 return evt->getNumOfLinkageServices();
1495 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1497 ePtr<eServiceEvent> evt;
1498 if (!m_event_handler.getEvent(evt, 0))
1500 if (!evt->getLinkageService(sub, m_reference, n))
1503 sub.type=eServiceReference::idInvalid;
1507 RESULT eDVBServicePlay::startTimeshift()
1509 ePtr<iDVBDemux> demux;
1511 eDebug("Start timeshift!");
1513 if (m_timeshift_enabled)
1516 /* start recording with the data demux. */
1517 if (m_service_handler.getDataDemux(demux))
1520 demux->createTSRecorder(m_record);
1524 char templ[]=TSPATH "/timeshift.XXXXXX";
1525 m_timeshift_fd = mkstemp(templ);
1526 m_timeshift_file = templ;
1528 eDebug("recording to %s", templ);
1530 if (m_timeshift_fd < 0)
1536 m_record->setTargetFD(m_timeshift_fd);
1538 m_timeshift_enabled = 1;
1540 updateTimeshiftPids();
1546 RESULT eDVBServicePlay::stopTimeshift()
1548 if (!m_timeshift_enabled)
1553 m_timeshift_enabled = 0;
1558 close(m_timeshift_fd);
1559 eDebug("remove timeshift file");
1560 remove(m_timeshift_file.c_str());
1565 int eDVBServicePlay::isTimeshiftActive()
1567 return m_timeshift_enabled && m_timeshift_active;
1570 RESULT eDVBServicePlay::activateTimeshift()
1572 if (!m_timeshift_enabled)
1575 if (!m_timeshift_active)
1577 switchToTimeshift();
1584 PyObject *eDVBServicePlay::getCutList()
1586 ePyObject list = PyList_New(0);
1588 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1590 ePyObject tuple = PyTuple_New(2);
1591 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1592 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1593 PyList_Append(list, tuple);
1600 void eDVBServicePlay::setCutList(ePyObject list)
1602 if (!PyList_Check(list))
1604 int size = PyList_Size(list);
1607 m_cue_entries.clear();
1609 for (i=0; i<size; ++i)
1611 ePyObject tuple = PyList_GET_ITEM(list, i);
1612 if (!PyTuple_Check(tuple))
1614 eDebug("non-tuple in cutlist");
1617 if (PyTuple_Size(tuple) != 2)
1619 eDebug("cutlist entries need to be a 2-tuple");
1622 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1623 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1625 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1628 pts_t pts = PyLong_AsLongLong(ppts);
1629 int type = PyInt_AsLong(ptype);
1630 m_cue_entries.insert(cueEntry(pts, type));
1631 eDebug("adding %08llx, %d", pts, type);
1633 m_cuesheet_changed = 1;
1635 cutlistToCuesheet();
1636 m_event((iPlayableService*)this, evCuesheetChanged);
1639 void eDVBServicePlay::setCutListEnable(int enable)
1641 m_cutlist_enabled = enable;
1642 cutlistToCuesheet();
1645 void eDVBServicePlay::updateTimeshiftPids()
1650 eDVBServicePMTHandler::program program;
1651 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1653 if (h.getProgramInfo(program))
1657 std::set<int> pids_to_record;
1658 pids_to_record.insert(0); // PAT
1659 if (program.pmtPid != -1)
1660 pids_to_record.insert(program.pmtPid); // PMT
1662 if (program.textPid != -1)
1663 pids_to_record.insert(program.textPid); // Videotext
1665 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1666 i(program.videoStreams.begin());
1667 i != program.videoStreams.end(); ++i)
1668 pids_to_record.insert(i->pid);
1670 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1671 i(program.audioStreams.begin());
1672 i != program.audioStreams.end(); ++i)
1673 pids_to_record.insert(i->pid);
1675 std::set<int> new_pids, obsolete_pids;
1677 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1678 m_pids_active.begin(), m_pids_active.end(),
1679 std::inserter(new_pids, new_pids.begin()));
1681 std::set_difference(
1682 m_pids_active.begin(), m_pids_active.end(),
1683 pids_to_record.begin(), pids_to_record.end(),
1684 std::inserter(new_pids, new_pids.begin())
1687 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1688 m_record->addPID(*i);
1690 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1691 m_record->removePID(*i);
1695 void eDVBServicePlay::switchToLive()
1697 if (!m_timeshift_active)
1703 m_teletext_parser = 0;
1704 m_radiotext_parser = 0;
1705 m_subtitle_parser = 0;
1706 m_new_dvb_subtitle_page_connection = 0;
1707 m_new_subtitle_page_connection = 0;
1708 m_radiotext_updated_connection = 0;
1710 /* free the timeshift service handler, we need the resources */
1711 m_service_handler_timeshift.free();
1712 m_timeshift_active = 0;
1714 m_event((iPlayableService*)this, evSeekableStatusChanged);
1719 void eDVBServicePlay::switchToTimeshift()
1721 if (m_timeshift_active)
1726 m_teletext_parser = 0;
1727 m_radiotext_parser = 0;
1728 m_subtitle_parser = 0;
1729 m_new_subtitle_page_connection = 0;
1730 m_new_dvb_subtitle_page_connection = 0;
1731 m_radiotext_updated_connection = 0;
1733 m_timeshift_active = 1;
1735 m_event((iPlayableService*)this, evSeekableStatusChanged);
1737 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1738 r.path = m_timeshift_file;
1740 m_cue = new eCueSheet();
1741 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1742 updateDecoder(); /* mainly to switch off PCR */
1745 void eDVBServicePlay::updateDecoder()
1747 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1749 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1751 bool defaultac3=false;
1752 std::string default_ac3;
1754 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1755 defaultac3 = default_ac3 == "True";
1757 eDVBServicePMTHandler::program program;
1758 if (h.getProgramInfo(program))
1759 eDebug("getting program info failed.");
1762 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1763 if (!program.videoStreams.empty())
1765 eDebugNoNewLine(" (");
1766 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1767 i(program.videoStreams.begin());
1768 i != program.videoStreams.end(); ++i)
1775 if (i != program.videoStreams.begin())
1776 eDebugNoNewLine(", ");
1777 eDebugNoNewLine("%04x", i->pid);
1779 eDebugNoNewLine(")");
1781 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1782 if (!program.audioStreams.empty())
1784 eDebugNoNewLine(" (");
1785 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1786 i(program.audioStreams.begin());
1787 i != program.audioStreams.end(); ++i)
1789 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1791 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1797 if (i != program.audioStreams.begin())
1798 eDebugNoNewLine(", ");
1799 eDebugNoNewLine("%04x", i->pid);
1801 eDebugNoNewLine(")");
1803 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1804 pcrpid = program.pcrPid;
1805 eDebug(", and the text pid is %04x", program.textPid);
1806 tpid = program.textPid;
1811 h.getDecodeDemux(m_decode_demux);
1813 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1815 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1816 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1817 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1818 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1819 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
1826 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1827 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1828 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1830 else // subservice or recording
1832 eServiceReferenceDVB ref;
1833 m_service_handler.getServiceReference(ref);
1834 eServiceReferenceDVB parent = ref.getParentServiceReference();
1839 ePtr<eDVBResourceManager> res_mgr;
1840 if (!eDVBResourceManager::getInstance(res_mgr))
1842 ePtr<iDVBChannelList> db;
1843 if (!res_mgr->getChannelList(db))
1845 ePtr<eDVBService> origService;
1846 if (!db->getService(parent, origService))
1848 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1849 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1855 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1856 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1858 m_decoder->setVideoPID(vpid, vpidtype);
1859 m_decoder->setAudioPID(apid, apidtype);
1860 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1862 m_decoder->setSyncPCR(pcrpid);
1865 ePtr<iDVBDemux> data_demux;
1866 if (!h.getDataDemux(data_demux))
1868 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1869 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1870 m_radiotext_parser->start(apid);
1875 m_decoder->setSyncPCR(-1);
1877 m_decoder->setTextPID(tpid);
1879 m_teletext_parser->start(program.textPid);
1882 m_decoder->setTrickmode(1);
1886 if (vpid > 0 && vpid < 0x2000)
1890 std::string radio_pic;
1891 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1892 m_decoder->setRadioPic(radio_pic);
1895 m_decoder->setAudioChannel(achannel);
1897 // how we can do this better?
1898 // update cache pid when the user changed the audio track or video track
1899 // TODO handling of difference audio types.. default audio types..
1901 /* don't worry about non-existing services, nor pvr services */
1902 if (m_dvb_service && !m_is_pvr)
1904 if (apidtype == eDVBAudio::aMPEG)
1906 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1907 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1911 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1912 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1914 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1915 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1916 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1917 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1920 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1923 void eDVBServicePlay::loadCuesheet()
1925 std::string filename = m_reference.path + ".cuts";
1927 m_cue_entries.clear();
1929 FILE *f = fopen(filename.c_str(), "rb");
1933 eDebug("loading cuts..");
1936 unsigned long long where;
1939 if (!fread(&where, sizeof(where), 1, f))
1941 if (!fread(&what, sizeof(what), 1, f))
1944 #if BYTE_ORDER == LITTLE_ENDIAN
1945 where = bswap_64(where);
1952 m_cue_entries.insert(cueEntry(where, what));
1955 eDebug("%d entries", m_cue_entries.size());
1957 eDebug("cutfile not found!");
1959 m_cuesheet_changed = 0;
1960 cutlistToCuesheet();
1961 m_event((iPlayableService*)this, evCuesheetChanged);
1964 void eDVBServicePlay::saveCuesheet()
1966 std::string filename = m_reference.path + ".cuts";
1968 FILE *f = fopen(filename.c_str(), "wb");
1972 unsigned long long where;
1975 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1977 #if BYTE_ORDER == BIG_ENDIAN
1980 where = bswap_64(i->where);
1982 what = htonl(i->what);
1983 fwrite(&where, sizeof(where), 1, f);
1984 fwrite(&what, sizeof(what), 1, f);
1990 m_cuesheet_changed = 0;
1993 void eDVBServicePlay::cutlistToCuesheet()
1997 eDebug("no cue sheet");
2002 if (!m_cutlist_enabled)
2004 m_cue->commitSpans();
2005 eDebug("cutlists were disabled");
2009 pts_t in = 0, out = 0, length = 0;
2013 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2017 if (i == m_cue_entries.end())
2020 if (i->what == 0) /* in */
2024 } else if (i->what == 1) /* out */
2026 else /* mark (2) or last play position (3) */
2034 m_cue->addSourceSpan(in, out);
2038 if (i == m_cue_entries.end())
2041 m_cue->commitSpans();
2044 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2046 if (m_subtitle_widget)
2047 disableSubtitles(parent);
2050 int tuplesize = PyTuple_Size(tuple);
2053 if (!PyTuple_Check(tuple))
2059 entry = PyTuple_GET_ITEM(tuple, 0);
2061 if (!PyInt_Check(entry))
2064 type = PyInt_AsLong(entry);
2066 if (type == 1) // teletext subtitles
2068 int page, magazine, pid;
2072 if (!m_teletext_parser)
2074 eDebug("enable teletext subtitles.. no parser !!!");
2078 entry = PyTuple_GET_ITEM(tuple, 1);
2079 if (!PyInt_Check(entry))
2081 pid = PyInt_AsLong(entry);
2083 entry = PyTuple_GET_ITEM(tuple, 2);
2084 if (!PyInt_Check(entry))
2086 page = PyInt_AsLong(entry);
2088 entry = PyTuple_GET_ITEM(tuple, 3);
2089 if (!PyInt_Check(entry))
2091 magazine = PyInt_AsLong(entry);
2093 m_subtitle_widget = new eSubtitleWidget(parent);
2094 m_subtitle_widget->resize(parent->size()); /* full size */
2095 m_teletext_parser->setPageAndMagazine(page, magazine);
2097 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2101 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2102 if (!m_subtitle_parser)
2104 eDebug("enable dvb subtitles.. no parser !!!");
2110 entry = PyTuple_GET_ITEM(tuple, 1);
2111 if (!PyInt_Check(entry))
2113 pid = PyInt_AsLong(entry);
2115 entry = PyTuple_GET_ITEM(tuple, 2);
2116 if (!PyInt_Check(entry))
2118 composition_page_id = PyInt_AsLong(entry);
2120 entry = PyTuple_GET_ITEM(tuple, 3);
2121 if (!PyInt_Check(entry))
2123 ancillary_page_id = PyInt_AsLong(entry);
2125 m_subtitle_widget = new eSubtitleWidget(parent);
2126 m_subtitle_widget->resize(parent->size()); /* full size */
2127 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2129 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2135 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2136 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2137 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2141 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2143 delete m_subtitle_widget;
2144 m_subtitle_widget = 0;
2145 if (m_subtitle_parser)
2147 m_subtitle_parser->stop();
2148 m_dvb_subtitle_pages.clear();
2150 if (m_teletext_parser)
2152 m_teletext_parser->setPageAndMagazine(-1, -1);
2153 m_subtitle_pages.clear();
2156 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2160 PyObject *eDVBServicePlay::getCachedSubtitle()
2164 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2167 unsigned int data = (unsigned int)tmp;
2168 int pid = (data&0xFFFF0000)>>16;
2169 ePyObject tuple = PyTuple_New(4);
2170 eDVBServicePMTHandler::program program;
2171 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2172 if (!h.getProgramInfo(program))
2174 if (program.textPid==pid) // teletext
2175 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2177 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2178 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2179 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2180 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2189 PyObject *eDVBServicePlay::getSubtitleList()
2191 if (!m_teletext_parser)
2197 ePyObject l = PyList_New(0);
2198 std::set<int> added_ttx_pages;
2200 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2201 m_teletext_parser->m_found_subtitle_pages;
2203 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2204 eDVBServicePMTHandler::program program;
2205 if (h.getProgramInfo(program))
2206 eDebug("getting program info failed.");
2209 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2210 it != program.subtitleStreams.end(); ++it)
2212 switch(it->subtitling_type)
2214 case 0x01: // ebu teletext subtitles
2216 int page_number = it->teletext_page_number & 0xFF;
2217 int magazine_number = it->teletext_magazine_number & 7;
2218 int hash = magazine_number << 8 | page_number;
2219 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2221 ePyObject tuple = PyTuple_New(5);
2222 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2223 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2224 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2225 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2226 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2227 PyList_Append(l, tuple);
2229 added_ttx_pages.insert(hash);
2234 case 0x20 ... 0x23: // dvb subtitles
2236 ePyObject tuple = PyTuple_New(5);
2237 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2238 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2239 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2240 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2241 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2242 PyList_Insert(l, 0, tuple);
2250 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2251 it != subs.end(); ++it)
2253 int page_number = it->teletext_page_number & 0xFF;
2254 int magazine_number = it->teletext_magazine_number & 7;
2255 int hash = magazine_number << 8 | page_number;
2256 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2258 ePyObject tuple = PyTuple_New(5);
2259 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2260 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2261 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2262 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2263 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2264 PyList_Append(l, tuple);
2272 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2274 if (m_subtitle_widget)
2276 m_subtitle_pages.push_back(page);
2277 checkSubtitleTiming();
2281 void eDVBServicePlay::checkSubtitleTiming()
2283 // eDebug("checkSubtitleTiming");
2284 if (!m_subtitle_widget)
2288 enum { TELETEXT, DVB } type;
2289 eDVBTeletextSubtitlePage page;
2290 eDVBSubtitlePage dvb_page;
2292 if (!m_subtitle_pages.empty())
2294 page = m_subtitle_pages.front();
2296 show_time = page.m_pts;
2298 else if (!m_dvb_subtitle_pages.empty())
2300 dvb_page = m_dvb_subtitle_pages.front();
2302 show_time = dvb_page.m_show_time;
2310 m_decoder->getPTS(0, pos);
2312 // eDebug("%lld %lld", pos, show_time);
2313 int diff = show_time - pos;
2316 eDebug("[late (%d ms)]", -diff / 90);
2321 eDebug("[invalid]");
2327 if (type == TELETEXT)
2329 eDebug("display teletext subtitle page");
2330 m_subtitle_widget->setPage(page);
2331 m_subtitle_pages.pop_front();
2335 eDebug("display dvb subtitle Page");
2336 m_subtitle_widget->setPage(dvb_page);
2337 m_dvb_subtitle_pages.pop_front();
2341 // eDebug("start subtitle delay %d", diff / 90);
2342 m_subtitle_sync_timer.start(diff / 90, 1);
2348 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2350 if (m_subtitle_widget)
2352 m_dvb_subtitle_pages.push_back(p);
2353 checkSubtitleTiming();
2357 int eDVBServicePlay::getAC3Delay()
2360 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2362 return m_decoder->getAC3Delay();
2367 int eDVBServicePlay::getPCMDelay()
2370 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2372 return m_decoder->getPCMDelay();
2377 void eDVBServicePlay::setAC3Delay(int delay)
2380 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2382 m_decoder->setAC3Delay(delay);
2385 void eDVBServicePlay::setPCMDelay(int delay)
2388 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2390 m_decoder->setPCMDelay(delay);
2393 DEFINE_REF(eDVBServicePlay)
2395 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");