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)
718 m_is_pvr = !m_reference.path.empty();
720 m_timeshift_enabled = m_timeshift_active = 0;
723 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
724 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
725 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
727 m_cuesheet_changed = 0;
728 m_cutlist_enabled = 1;
730 m_subtitle_widget = 0;
732 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
735 eDVBServicePlay::~eDVBServicePlay()
737 delete m_subtitle_widget;
740 void eDVBServicePlay::gotNewEvent()
744 ePtr<eServiceEvent> m_event_now, m_event_next;
745 getEvent(m_event_now, 0);
746 getEvent(m_event_next, 1);
749 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
751 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
753 m_event((iPlayableService*)this, evUpdatedEventInfo);
756 void eDVBServicePlay::serviceEvent(int event)
760 case eDVBServicePMTHandler::eventTuned:
762 ePtr<iDVBDemux> m_demux;
763 if (!m_service_handler.getDataDemux(m_demux))
765 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
766 int sid = ref.getParentServiceID().get();
768 sid = ref.getServiceID().get();
769 if ( ref.getParentTransportStreamID().get() &&
770 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
771 m_event_handler.startOther(m_demux, sid);
773 m_event_handler.start(m_demux, sid);
777 case eDVBServicePMTHandler::eventTuneFailed:
779 eDebug("DVB service failed to tune");
780 m_event((iPlayableService*)this, evTuneFailed);
783 case eDVBServicePMTHandler::eventNewProgramInfo:
785 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
786 if (m_timeshift_enabled)
787 updateTimeshiftPids();
788 if (!m_timeshift_active)
790 if (m_first_program_info && m_is_pvr)
792 m_first_program_info = 0;
795 m_event((iPlayableService*)this, evUpdatedInfo);
798 case eDVBServicePMTHandler::eventEOF:
799 m_event((iPlayableService*)this, evEOF);
801 case eDVBServicePMTHandler::eventSOF:
802 m_event((iPlayableService*)this, evSOF);
807 void eDVBServicePlay::serviceEventTimeshift(int event)
811 case eDVBServicePMTHandler::eventNewProgramInfo:
812 if (m_timeshift_active)
815 case eDVBServicePMTHandler::eventSOF:
816 m_event((iPlayableService*)this, evSOF);
818 case eDVBServicePMTHandler::eventEOF:
824 RESULT eDVBServicePlay::start()
827 /* in pvr mode, we only want to use one demux. in tv mode, we're using
828 two (one for decoding, one for data source), as we must be prepared
829 to start recording from the data demux. */
831 m_cue = new eCueSheet();
833 m_first_program_info = 1;
834 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
835 r = m_service_handler.tune(service, m_is_pvr, m_cue);
837 /* inject EIT if there is a stored one */
840 std::string filename = service.path;
841 filename.erase(filename.length()-2, 2);
843 ePtr<eServiceEvent> event = new eServiceEvent;
844 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
846 ePtr<eServiceEvent> empty;
847 m_event_handler.inject(event, 0);
848 m_event_handler.inject(empty, 1);
855 m_event(this, evStart);
856 m_event((iPlayableService*)this, evSeekableStatusChanged);
860 RESULT eDVBServicePlay::stop()
862 /* add bookmark for last play position */
866 if (!getPlayPosition(play_position))
868 /* remove last position */
869 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
871 if (i->what == 3) /* current play position */
873 m_cue_entries.erase(i);
874 i = m_cue_entries.begin();
880 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
881 m_cuesheet_changed = 1;
885 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
887 m_service_handler_timeshift.free();
888 m_service_handler.free();
890 if (m_is_pvr && m_cuesheet_changed)
893 /* save cuesheet only when main file is accessible. */
894 if (!::stat(m_reference.path.c_str(), &s))
901 RESULT eDVBServicePlay::setTarget(int target)
903 m_is_primary = !target;
907 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
909 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
913 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
915 /* note: we check for timeshift to be enabled,
916 not neccessary active. if you pause when timeshift
917 is not active, you should activate it when unpausing */
918 if ((!m_is_pvr) && (!m_timeshift_enabled))
928 RESULT eDVBServicePlay::setSlowMotion(int ratio)
931 return m_decoder->setSlowMotion(ratio);
936 RESULT eDVBServicePlay::setFastForward(int ratio)
938 int skipmode, ffratio;
944 } else if (ratio > 0)
952 } else // if (ratio < 0)
958 if (m_skipmode != skipmode)
960 eDebug("setting cue skipmode to %d", skipmode);
962 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
965 m_skipmode = skipmode;
970 return m_decoder->setFastForward(ffratio);
973 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
975 if (m_is_pvr || m_timeshift_enabled)
985 /* TODO: when timeshift is enabled but not active, this doesn't work. */
986 RESULT eDVBServicePlay::getLength(pts_t &len)
988 ePtr<iDVBPVRChannel> pvr_channel;
990 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
993 return pvr_channel->getLength(len);
996 RESULT eDVBServicePlay::pause()
998 if (!m_is_paused && m_decoder)
1001 return m_decoder->freeze(0);
1006 RESULT eDVBServicePlay::unpause()
1008 if (m_is_paused && m_decoder)
1011 return m_decoder->unfreeze();
1016 RESULT eDVBServicePlay::seekTo(pts_t to)
1018 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1020 if (!m_decode_demux)
1023 ePtr<iDVBPVRChannel> pvr_channel;
1025 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1031 m_cue->seekTo(0, to);
1035 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1037 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1039 if (!m_decode_demux)
1042 ePtr<iDVBPVRChannel> pvr_channel;
1044 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1049 /* HACK until we have skip-AP api */
1050 if ((to > 0) && (to < 100))
1058 m_cue->seekTo(mode, to);
1062 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1064 ePtr<iDVBPVRChannel> pvr_channel;
1066 if (!m_decode_demux)
1069 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1074 /* if there is a decoder, use audio or video PTS */
1077 r = m_decoder->getPTS(0, pos);
1083 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1086 RESULT eDVBServicePlay::setTrickmode(int trick)
1089 m_decoder->setTrickmode(trick);
1093 RESULT eDVBServicePlay::isCurrentlySeekable()
1095 return m_is_pvr || m_timeshift_active;
1098 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1104 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1110 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1116 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1122 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1128 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1131 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1132 (m_timeshift_enabled || !m_is_pvr))
1134 if (!m_timeshift_enabled)
1136 /* we need enough diskspace */
1138 if (statfs(TSPATH "/.", &fs) < 0)
1140 eDebug("statfs failed!");
1144 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1146 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1156 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1167 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1173 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1179 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1185 RESULT eDVBServicePlay::getName(std::string &name)
1189 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1190 return i->getName(m_reference, name);
1194 m_dvb_service->getName(m_reference, name);
1198 else if (!m_reference.name.empty())
1199 eStaticServiceDVBInformation().getName(m_reference, name);
1201 name = "DVB service";
1205 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1207 return m_event_handler.getEvent(evt, nownext);
1210 int eDVBServicePlay::getInfo(int w)
1212 eDVBServicePMTHandler::program program;
1215 return resIsPyObject;
1217 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1219 if (h.getProgramInfo(program))
1225 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1227 ePtr<eServiceEvent> evt;
1228 if (!m_event_handler.getEvent(evt, 0))
1230 ePtr<eComponentData> data;
1231 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1233 if ( data->getStreamContent() == 1 )
1235 switch(data->getComponentType())
1238 case 1: // 4:3 SD PAL
1240 case 3: // 16:9 SD PAL
1241 case 4: // > 16:9 PAL
1242 case 5: // 4:3 SD NTSC
1244 case 7: // 16:9 SD NTSC
1245 case 8: // > 16:9 NTSC
1248 case 9: // 4:3 HD PAL
1250 case 0xB: // 16:9 HD PAL
1251 case 0xC: // > 16:9 HD PAL
1252 case 0xD: // 4:3 HD NTSC
1254 case 0xF: // 16:9 HD NTSC
1255 case 0x10: // > 16:9 HD PAL
1256 return data->getComponentType();
1263 case sIsCrypted: return program.isCrypted();
1264 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1265 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1266 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1267 case sPCRPID: return program.pcrPid;
1268 case sPMTPID: return program.pmtPid;
1269 case sTXTPID: return program.textPid;
1270 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1271 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1272 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1273 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1274 case sProvider: if (!m_dvb_service) return -1; return -2;
1275 case sServiceref: return resIsString;
1281 std::string eDVBServicePlay::getInfoString(int w)
1286 if (!m_dvb_service) return "";
1287 return m_dvb_service->m_provider_name;
1289 return m_reference.toString();
1293 return iServiceInformation::getInfoString(w);
1296 PyObject *eDVBServicePlay::getInfoObject(int w)
1301 return m_service_handler.getCaIds();
1305 return iServiceInformation::getInfoObject(w);
1308 int eDVBServicePlay::getNumberOfTracks()
1310 eDVBServicePMTHandler::program program;
1311 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1312 if (h.getProgramInfo(program))
1314 return program.audioStreams.size();
1317 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1319 int ret = selectAudioStream(i);
1321 if (m_decoder->start())
1327 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1329 eDVBServicePMTHandler::program program;
1330 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1332 if (h.getProgramInfo(program))
1335 if (i >= program.audioStreams.size())
1338 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1339 info.m_description = "MPEG";
1340 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1341 info.m_description = "AC3";
1342 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1343 info.m_description = "AAC";
1344 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1345 info.m_description = "DTS";
1347 info.m_description = "???";
1349 if (program.audioStreams[i].component_tag != -1)
1351 ePtr<eServiceEvent> evt;
1352 if (!m_event_handler.getEvent(evt, 0))
1354 ePtr<eComponentData> data;
1355 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1356 info.m_language = data->getText();
1360 if (info.m_language.empty())
1361 info.m_language = program.audioStreams[i].language_code;
1366 int eDVBServicePlay::selectAudioStream(int i)
1368 eDVBServicePMTHandler::program program;
1369 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1371 if (h.getProgramInfo(program))
1374 if ((unsigned int)i >= program.audioStreams.size())
1380 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1383 if (m_radiotext_parser)
1384 m_radiotext_parser->start(program.audioStreams[i].pid);
1386 if (m_dvb_service && !m_is_pvr)
1388 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1390 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1391 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1395 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1396 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1400 h.resetCachedProgram();
1405 int eDVBServicePlay::getCurrentChannel()
1407 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1410 RESULT eDVBServicePlay::selectChannel(int i)
1412 if (i < LEFT || i > RIGHT || i == STEREO)
1415 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1417 m_decoder->setAudioChannel(i);
1421 std::string eDVBServicePlay::getRadioText(int x)
1423 if (m_radiotext_parser)
1427 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1432 void eDVBServicePlay::radioTextUpdated()
1434 m_event((iPlayableService*)this, evUpdatedRadioText);
1437 int eDVBServiceBase::getFrontendInfo(int w)
1439 eUsePtr<iDVBChannel> channel;
1440 if(m_service_handler.getChannel(channel))
1442 ePtr<iDVBFrontend> fe;
1443 if(channel->getFrontend(fe))
1445 return fe->readFrontendData(w);
1448 PyObject *eDVBServiceBase::getFrontendData(bool original)
1452 eUsePtr<iDVBChannel> channel;
1453 if(!m_service_handler.getChannel(channel))
1455 ePtr<iDVBFrontend> fe;
1456 if(!channel->getFrontend(fe))
1458 ret = fe->readTransponderData(original);
1461 ePtr<iDVBFrontendParameters> feparm;
1462 channel->getCurrentFrontendParameters(feparm);
1465 eDVBFrontendParametersSatellite osat;
1466 if (!feparm->getDVBS(osat))
1468 void PutToDict(ePyObject &, const char*, long);
1469 void PutToDict(ePyObject &, const char*, const char*);
1470 PutToDict(ret, "orbital_position", osat.orbital_position);
1471 const char *tmp = "UNKNOWN";
1472 switch(osat.polarisation)
1474 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1475 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1476 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1477 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1480 PutToDict(ret, "polarization", tmp);
1494 int eDVBServicePlay::getNumberOfSubservices()
1496 ePtr<eServiceEvent> evt;
1497 if (!m_event_handler.getEvent(evt, 0))
1498 return evt->getNumOfLinkageServices();
1502 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1504 ePtr<eServiceEvent> evt;
1505 if (!m_event_handler.getEvent(evt, 0))
1507 if (!evt->getLinkageService(sub, m_reference, n))
1510 sub.type=eServiceReference::idInvalid;
1514 RESULT eDVBServicePlay::startTimeshift()
1516 ePtr<iDVBDemux> demux;
1518 eDebug("Start timeshift!");
1520 if (m_timeshift_enabled)
1523 /* start recording with the data demux. */
1524 if (m_service_handler.getDataDemux(demux))
1527 demux->createTSRecorder(m_record);
1531 char templ[]=TSPATH "/timeshift.XXXXXX";
1532 m_timeshift_fd = mkstemp(templ);
1533 m_timeshift_file = templ;
1535 eDebug("recording to %s", templ);
1537 if (m_timeshift_fd < 0)
1543 m_record->setTargetFD(m_timeshift_fd);
1545 m_timeshift_enabled = 1;
1547 updateTimeshiftPids();
1553 RESULT eDVBServicePlay::stopTimeshift()
1555 if (!m_timeshift_enabled)
1560 m_timeshift_enabled = 0;
1565 close(m_timeshift_fd);
1566 eDebug("remove timeshift file");
1567 remove(m_timeshift_file.c_str());
1572 int eDVBServicePlay::isTimeshiftActive()
1574 return m_timeshift_enabled && m_timeshift_active;
1577 RESULT eDVBServicePlay::activateTimeshift()
1579 if (!m_timeshift_enabled)
1582 if (!m_timeshift_active)
1584 switchToTimeshift();
1591 PyObject *eDVBServicePlay::getCutList()
1593 ePyObject list = PyList_New(0);
1595 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1597 ePyObject tuple = PyTuple_New(2);
1598 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1599 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1600 PyList_Append(list, tuple);
1607 void eDVBServicePlay::setCutList(ePyObject list)
1609 if (!PyList_Check(list))
1611 int size = PyList_Size(list);
1614 m_cue_entries.clear();
1616 for (i=0; i<size; ++i)
1618 ePyObject tuple = PyList_GET_ITEM(list, i);
1619 if (!PyTuple_Check(tuple))
1621 eDebug("non-tuple in cutlist");
1624 if (PyTuple_Size(tuple) != 2)
1626 eDebug("cutlist entries need to be a 2-tuple");
1629 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1630 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1632 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1635 pts_t pts = PyLong_AsLongLong(ppts);
1636 int type = PyInt_AsLong(ptype);
1637 m_cue_entries.insert(cueEntry(pts, type));
1638 eDebug("adding %08llx, %d", pts, type);
1640 m_cuesheet_changed = 1;
1642 cutlistToCuesheet();
1643 m_event((iPlayableService*)this, evCuesheetChanged);
1646 void eDVBServicePlay::setCutListEnable(int enable)
1648 m_cutlist_enabled = enable;
1649 cutlistToCuesheet();
1652 void eDVBServicePlay::updateTimeshiftPids()
1657 eDVBServicePMTHandler::program program;
1658 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1660 if (h.getProgramInfo(program))
1664 std::set<int> pids_to_record;
1665 pids_to_record.insert(0); // PAT
1666 if (program.pmtPid != -1)
1667 pids_to_record.insert(program.pmtPid); // PMT
1669 if (program.textPid != -1)
1670 pids_to_record.insert(program.textPid); // Videotext
1672 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1673 i(program.videoStreams.begin());
1674 i != program.videoStreams.end(); ++i)
1675 pids_to_record.insert(i->pid);
1677 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1678 i(program.audioStreams.begin());
1679 i != program.audioStreams.end(); ++i)
1680 pids_to_record.insert(i->pid);
1682 std::set<int> new_pids, obsolete_pids;
1684 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1685 m_pids_active.begin(), m_pids_active.end(),
1686 std::inserter(new_pids, new_pids.begin()));
1688 std::set_difference(
1689 m_pids_active.begin(), m_pids_active.end(),
1690 pids_to_record.begin(), pids_to_record.end(),
1691 std::inserter(new_pids, new_pids.begin())
1694 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1695 m_record->addPID(*i);
1697 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1698 m_record->removePID(*i);
1702 void eDVBServicePlay::switchToLive()
1704 if (!m_timeshift_active)
1710 m_teletext_parser = 0;
1711 m_radiotext_parser = 0;
1712 m_subtitle_parser = 0;
1713 m_new_dvb_subtitle_page_connection = 0;
1714 m_new_subtitle_page_connection = 0;
1715 m_radiotext_updated_connection = 0;
1717 /* free the timeshift service handler, we need the resources */
1718 m_service_handler_timeshift.free();
1719 m_timeshift_active = 0;
1721 m_event((iPlayableService*)this, evSeekableStatusChanged);
1726 void eDVBServicePlay::switchToTimeshift()
1728 if (m_timeshift_active)
1733 m_teletext_parser = 0;
1734 m_radiotext_parser = 0;
1735 m_subtitle_parser = 0;
1736 m_new_subtitle_page_connection = 0;
1737 m_new_dvb_subtitle_page_connection = 0;
1738 m_radiotext_updated_connection = 0;
1740 m_timeshift_active = 1;
1742 m_event((iPlayableService*)this, evSeekableStatusChanged);
1744 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1745 r.path = m_timeshift_file;
1747 m_cue = new eCueSheet();
1748 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1749 updateDecoder(); /* mainly to switch off PCR */
1752 void eDVBServicePlay::updateDecoder()
1754 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1756 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1758 bool defaultac3=false;
1759 std::string default_ac3;
1761 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1762 defaultac3 = default_ac3 == "True";
1764 eDVBServicePMTHandler::program program;
1765 if (h.getProgramInfo(program))
1766 eDebug("getting program info failed.");
1769 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1770 if (!program.videoStreams.empty())
1772 eDebugNoNewLine(" (");
1773 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1774 i(program.videoStreams.begin());
1775 i != program.videoStreams.end(); ++i)
1782 if (i != program.videoStreams.begin())
1783 eDebugNoNewLine(", ");
1784 eDebugNoNewLine("%04x", i->pid);
1786 eDebugNoNewLine(")");
1788 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1789 if (!program.audioStreams.empty())
1791 eDebugNoNewLine(" (");
1792 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1793 i(program.audioStreams.begin());
1794 i != program.audioStreams.end(); ++i)
1796 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1798 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1804 if (i != program.audioStreams.begin())
1805 eDebugNoNewLine(", ");
1806 eDebugNoNewLine("%04x", i->pid);
1808 eDebugNoNewLine(")");
1810 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1811 pcrpid = program.pcrPid;
1812 eDebug(", and the text pid is %04x", program.textPid);
1813 tpid = program.textPid;
1818 h.getDecodeDemux(m_decode_demux);
1820 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1822 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1823 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1824 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1825 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1826 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
1833 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1834 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1835 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1837 else // subservice or recording
1839 eServiceReferenceDVB ref;
1840 m_service_handler.getServiceReference(ref);
1841 eServiceReferenceDVB parent = ref.getParentServiceReference();
1846 ePtr<eDVBResourceManager> res_mgr;
1847 if (!eDVBResourceManager::getInstance(res_mgr))
1849 ePtr<iDVBChannelList> db;
1850 if (!res_mgr->getChannelList(db))
1852 ePtr<eDVBService> origService;
1853 if (!db->getService(parent, origService))
1855 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1856 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1862 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1863 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1865 m_decoder->setVideoPID(vpid, vpidtype);
1866 m_decoder->setAudioPID(apid, apidtype);
1867 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1869 m_decoder->setSyncPCR(pcrpid);
1872 ePtr<iDVBDemux> data_demux;
1873 if (!h.getDataDemux(data_demux))
1875 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1876 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1877 m_radiotext_parser->start(apid);
1882 m_decoder->setSyncPCR(-1);
1884 m_decoder->setTextPID(tpid);
1886 m_teletext_parser->start(program.textPid);
1889 m_decoder->setTrickmode(1);
1893 if (vpid > 0 && vpid < 0x2000)
1897 std::string radio_pic;
1898 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1899 m_decoder->setRadioPic(radio_pic);
1902 m_decoder->setAudioChannel(achannel);
1904 // how we can do this better?
1905 // update cache pid when the user changed the audio track or video track
1906 // TODO handling of difference audio types.. default audio types..
1908 /* don't worry about non-existing services, nor pvr services */
1909 if (m_dvb_service && !m_is_pvr)
1911 if (apidtype == eDVBAudio::aMPEG)
1913 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1914 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1918 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1919 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1921 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1922 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1923 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1924 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1927 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1930 void eDVBServicePlay::loadCuesheet()
1932 std::string filename = m_reference.path + ".cuts";
1934 m_cue_entries.clear();
1936 FILE *f = fopen(filename.c_str(), "rb");
1940 eDebug("loading cuts..");
1943 unsigned long long where;
1946 if (!fread(&where, sizeof(where), 1, f))
1948 if (!fread(&what, sizeof(what), 1, f))
1951 #if BYTE_ORDER == LITTLE_ENDIAN
1952 where = bswap_64(where);
1959 m_cue_entries.insert(cueEntry(where, what));
1962 eDebug("%d entries", m_cue_entries.size());
1964 eDebug("cutfile not found!");
1966 m_cuesheet_changed = 0;
1967 cutlistToCuesheet();
1968 m_event((iPlayableService*)this, evCuesheetChanged);
1971 void eDVBServicePlay::saveCuesheet()
1973 std::string filename = m_reference.path + ".cuts";
1975 FILE *f = fopen(filename.c_str(), "wb");
1979 unsigned long long where;
1982 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1984 #if BYTE_ORDER == BIG_ENDIAN
1987 where = bswap_64(i->where);
1989 what = htonl(i->what);
1990 fwrite(&where, sizeof(where), 1, f);
1991 fwrite(&what, sizeof(what), 1, f);
1997 m_cuesheet_changed = 0;
2000 void eDVBServicePlay::cutlistToCuesheet()
2004 eDebug("no cue sheet");
2009 if (!m_cutlist_enabled)
2011 m_cue->commitSpans();
2012 eDebug("cutlists were disabled");
2016 pts_t in = 0, out = 0, length = 0;
2020 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2024 if (i == m_cue_entries.end())
2027 if (i->what == 0) /* in */
2031 } else if (i->what == 1) /* out */
2033 else /* mark (2) or last play position (3) */
2041 m_cue->addSourceSpan(in, out);
2045 if (i == m_cue_entries.end())
2048 m_cue->commitSpans();
2051 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2053 if (m_subtitle_widget)
2054 disableSubtitles(parent);
2057 int tuplesize = PyTuple_Size(tuple);
2060 if (!PyTuple_Check(tuple))
2066 entry = PyTuple_GET_ITEM(tuple, 0);
2068 if (!PyInt_Check(entry))
2071 type = PyInt_AsLong(entry);
2073 if (type == 1) // teletext subtitles
2075 int page, magazine, pid;
2079 if (!m_teletext_parser)
2081 eDebug("enable teletext subtitles.. no parser !!!");
2085 entry = PyTuple_GET_ITEM(tuple, 1);
2086 if (!PyInt_Check(entry))
2088 pid = PyInt_AsLong(entry);
2090 entry = PyTuple_GET_ITEM(tuple, 2);
2091 if (!PyInt_Check(entry))
2093 page = PyInt_AsLong(entry);
2095 entry = PyTuple_GET_ITEM(tuple, 3);
2096 if (!PyInt_Check(entry))
2098 magazine = PyInt_AsLong(entry);
2100 m_subtitle_widget = new eSubtitleWidget(parent);
2101 m_subtitle_widget->resize(parent->size()); /* full size */
2102 m_teletext_parser->setPageAndMagazine(page, magazine);
2104 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2108 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2109 if (!m_subtitle_parser)
2111 eDebug("enable dvb subtitles.. no parser !!!");
2117 entry = PyTuple_GET_ITEM(tuple, 1);
2118 if (!PyInt_Check(entry))
2120 pid = PyInt_AsLong(entry);
2122 entry = PyTuple_GET_ITEM(tuple, 2);
2123 if (!PyInt_Check(entry))
2125 composition_page_id = PyInt_AsLong(entry);
2127 entry = PyTuple_GET_ITEM(tuple, 3);
2128 if (!PyInt_Check(entry))
2130 ancillary_page_id = PyInt_AsLong(entry);
2132 m_subtitle_widget = new eSubtitleWidget(parent);
2133 m_subtitle_widget->resize(parent->size()); /* full size */
2134 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2136 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2142 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2143 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2144 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2148 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2150 delete m_subtitle_widget;
2151 m_subtitle_widget = 0;
2152 if (m_subtitle_parser)
2154 m_subtitle_parser->stop();
2155 m_dvb_subtitle_pages.clear();
2157 if (m_teletext_parser)
2159 m_teletext_parser->setPageAndMagazine(-1, -1);
2160 m_subtitle_pages.clear();
2163 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2167 PyObject *eDVBServicePlay::getCachedSubtitle()
2171 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2174 unsigned int data = (unsigned int)tmp;
2175 int pid = (data&0xFFFF0000)>>16;
2176 ePyObject tuple = PyTuple_New(4);
2177 eDVBServicePMTHandler::program program;
2178 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2179 if (!h.getProgramInfo(program))
2181 if (program.textPid==pid) // teletext
2182 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2184 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2185 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2186 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2187 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2196 PyObject *eDVBServicePlay::getSubtitleList()
2198 if (!m_teletext_parser)
2204 ePyObject l = PyList_New(0);
2205 std::set<int> added_ttx_pages;
2207 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2208 m_teletext_parser->m_found_subtitle_pages;
2210 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2211 eDVBServicePMTHandler::program program;
2212 if (h.getProgramInfo(program))
2213 eDebug("getting program info failed.");
2216 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2217 it != program.subtitleStreams.end(); ++it)
2219 switch(it->subtitling_type)
2221 case 0x01: // ebu teletext subtitles
2223 int page_number = it->teletext_page_number & 0xFF;
2224 int magazine_number = it->teletext_magazine_number & 7;
2225 int hash = magazine_number << 8 | page_number;
2226 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2228 ePyObject tuple = PyTuple_New(5);
2229 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2230 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2231 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2232 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2233 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2234 PyList_Append(l, tuple);
2236 added_ttx_pages.insert(hash);
2241 case 0x20 ... 0x23: // dvb subtitles
2243 ePyObject tuple = PyTuple_New(5);
2244 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2245 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2246 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2247 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2248 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2249 PyList_Insert(l, 0, tuple);
2257 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2258 it != subs.end(); ++it)
2260 int page_number = it->teletext_page_number & 0xFF;
2261 int magazine_number = it->teletext_magazine_number & 7;
2262 int hash = magazine_number << 8 | page_number;
2263 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2265 ePyObject tuple = PyTuple_New(5);
2266 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2267 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2268 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2269 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2270 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2271 PyList_Append(l, tuple);
2279 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2281 if (m_subtitle_widget)
2283 m_subtitle_pages.push_back(page);
2284 checkSubtitleTiming();
2288 void eDVBServicePlay::checkSubtitleTiming()
2290 // eDebug("checkSubtitleTiming");
2291 if (!m_subtitle_widget)
2295 enum { TELETEXT, DVB } type;
2296 eDVBTeletextSubtitlePage page;
2297 eDVBSubtitlePage dvb_page;
2299 if (!m_subtitle_pages.empty())
2301 page = m_subtitle_pages.front();
2303 show_time = page.m_pts;
2305 else if (!m_dvb_subtitle_pages.empty())
2307 dvb_page = m_dvb_subtitle_pages.front();
2309 show_time = dvb_page.m_show_time;
2317 m_decoder->getPTS(0, pos);
2319 // eDebug("%lld %lld", pos, show_time);
2320 int diff = show_time - pos;
2323 eDebug("[late (%d ms)]", -diff / 90);
2328 eDebug("[invalid]");
2334 if (type == TELETEXT)
2336 eDebug("display teletext subtitle page");
2337 m_subtitle_widget->setPage(page);
2338 m_subtitle_pages.pop_front();
2342 eDebug("display dvb subtitle Page");
2343 m_subtitle_widget->setPage(dvb_page);
2344 m_dvb_subtitle_pages.pop_front();
2348 // eDebug("start subtitle delay %d", diff / 90);
2349 m_subtitle_sync_timer.start(diff / 90, 1);
2355 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2357 if (m_subtitle_widget)
2359 m_dvb_subtitle_pages.push_back(p);
2360 checkSubtitleTiming();
2364 int eDVBServicePlay::getAC3Delay()
2367 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2369 return m_decoder->getAC3Delay();
2374 int eDVBServicePlay::getPCMDelay()
2377 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2379 return m_decoder->getPCMDelay();
2384 void eDVBServicePlay::setAC3Delay(int delay)
2387 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2389 m_decoder->setAC3Delay(delay);
2392 void eDVBServicePlay::setPCMDelay(int delay)
2395 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2397 m_decoder->setPCMDelay(delay);
2400 DEFINE_REF(eDVBServicePlay)
2402 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");