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);
177 eDebug("%d %s", tmp, it->toString().c_str());
180 m_playable_service = *it;
187 m_playable_service = eServiceReference();
191 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
196 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
198 DECLARE_REF(eStaticServiceDVBPVRInformation);
199 eServiceReference m_ref;
200 eDVBMetaParser m_parser;
202 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
203 RESULT getName(const eServiceReference &ref, std::string &name);
204 int getLength(const eServiceReference &ref);
205 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
206 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
207 int getInfo(const eServiceReference &ref, int w);
208 std::string getInfoString(const eServiceReference &ref,int w);
211 DEFINE_REF(eStaticServiceDVBPVRInformation);
213 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
216 m_parser.parseFile(ref.path);
219 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
221 ASSERT(ref == m_ref);
222 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
226 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
228 ASSERT(ref == m_ref);
232 if (tstools.openFile(ref.path.c_str()))
236 if (tstools.calcLen(len))
242 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
246 case iServiceInformation::sDescription:
247 return iServiceInformation::resIsString;
248 case iServiceInformation::sServiceref:
249 return iServiceInformation::resIsString;
250 case iServiceInformation::sTimeCreate:
251 if (m_parser.m_time_create)
252 return m_parser.m_time_create;
254 return iServiceInformation::resNA;
256 return iServiceInformation::resNA;
260 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
264 case iServiceInformation::sDescription:
265 return m_parser.m_description;
266 case iServiceInformation::sServiceref:
267 return m_parser.m_ref.toString();
268 case iServiceInformation::sTags:
269 return m_parser.m_tags;
275 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
277 if (!ref.path.empty())
279 ePtr<eServiceEvent> event = new eServiceEvent;
280 std::string filename = ref.path;
281 filename.erase(filename.length()-2, 2);
283 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
293 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
295 DECLARE_REF(eDVBPVRServiceOfflineOperations);
296 eServiceReferenceDVB m_ref;
298 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
300 RESULT deleteFromDisk(int simulate);
301 RESULT getListOfFilenames(std::list<std::string> &);
304 DEFINE_REF(eDVBPVRServiceOfflineOperations);
306 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
310 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
316 std::list<std::string> res;
317 if (getListOfFilenames(res))
320 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
322 eDebug("FATAL !! can't get background file eraser");
324 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
326 eDebug("Removing %s...", i->c_str());
328 eraser->erase(i->c_str());
330 ::unlink(i->c_str());
337 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
340 res.push_back(m_ref.path);
342 // handling for old splitted recordings (enigma 1)
347 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
349 if (stat(buf, &s) < 0)
354 res.push_back(m_ref.path + ".meta");
355 res.push_back(m_ref.path + ".ap");
356 res.push_back(m_ref.path + ".cuts");
357 std::string tmp = m_ref.path;
358 tmp.erase(m_ref.path.length()-3);
359 res.push_back(tmp + ".eit");
363 DEFINE_REF(eServiceFactoryDVB)
365 eServiceFactoryDVB::eServiceFactoryDVB()
367 ePtr<eServiceCenter> sc;
369 eServiceCenter::getPrivInstance(sc);
371 sc->addServiceFactory(eServiceFactoryDVB::id, this);
373 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
374 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
377 eServiceFactoryDVB::~eServiceFactoryDVB()
379 ePtr<eServiceCenter> sc;
381 eServiceCenter::getPrivInstance(sc);
383 sc->removeServiceFactory(eServiceFactoryDVB::id);
386 DEFINE_REF(eDVBServiceList);
388 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
392 eDVBServiceList::~eDVBServiceList()
396 RESULT eDVBServiceList::startQuery()
398 ePtr<iDVBChannelList> db;
399 ePtr<eDVBResourceManager> res;
402 if ((err = eDVBResourceManager::getInstance(res)) != 0)
404 eDebug("no resource manager");
407 if ((err = res->getChannelList(db)) != 0)
409 eDebug("no channel list");
413 ePtr<eDVBChannelQuery> q;
415 if (!m_parent.path.empty())
417 eDVBChannelQuery::compile(q, m_parent.path);
420 eDebug("compile query failed");
425 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
427 eDebug("startQuery failed");
434 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
436 eServiceReferenceDVB ref;
441 while (!m_query->getNextResult(ref))
445 list.sort(iListableServiceCompare(this));
450 // The first argument of this function is a format string to specify the order and
451 // the content of the returned list
452 // useable format options are
453 // R = Service Reference (as swig object .. this is very slow)
454 // S = Service Reference (as python string object .. same as ref.toString())
455 // C = Service Reference (as python string object .. same as ref.toCompareString())
456 // N = Service Name (as python string object)
457 // when exactly one return value per service is selected in the format string,
458 // then each value is directly a list entry
459 // when more than one value is returned per service, then the list is a list of
461 // unknown format string chars are returned as python None values !
462 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
465 std::list<eServiceReference> tmplist;
468 if (!format || !(retcount=strlen(format)))
469 format = "R"; // just return service reference swig object ...
471 if (!getContent(tmplist, sorted))
473 int services=tmplist.size();
474 ePtr<iStaticServiceInformation> sptr;
475 eServiceCenterPtr service_center;
477 if (strchr(format, 'N'))
478 eServiceCenter::getPrivInstance(service_center);
480 ret = PyList_New(services);
481 std::list<eServiceReference>::iterator it(tmplist.begin());
483 for (int cnt=0; cnt < services; ++cnt)
485 eServiceReference &ref=*it++;
486 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
487 for (int i=0; i < retcount; ++i)
492 case 'R': // service reference (swig)object
493 tmp = NEW_eServiceReference(ref);
495 case 'C': // service reference compare string
496 tmp = PyString_FromString(ref.toCompareString().c_str());
498 case 'S': // service reference string
499 tmp = PyString_FromString(ref.toString().c_str());
501 case 'N': // service name
504 service_center->info(ref, sptr);
508 sptr->getName(ref, name);
510 tmp = PyString_FromString(name.c_str());
514 tmp = PyString_FromString("<n/a>");
527 PyTuple_SET_ITEM(tuple, i, tmp);
529 PyList_SET_ITEM(ret, cnt, tmp);
533 PyList_SET_ITEM(ret, cnt, tuple);
536 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
539 RESULT eDVBServiceList::getNext(eServiceReference &ref)
544 return m_query->getNextResult((eServiceReferenceDVB&)ref);
547 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
549 if (m_parent.flags & eServiceReference::canDescent) // bouquet
551 ePtr<iDVBChannelList> db;
552 ePtr<eDVBResourceManager> resm;
554 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
557 if (db->getBouquet(m_parent, m_bouquet) != 0)
568 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
572 return m_bouquet->addService(ref, before);
575 RESULT eDVBServiceList::removeService(eServiceReference &ref)
579 return m_bouquet->removeService(ref);
582 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
586 return m_bouquet->moveService(ref, pos);
589 RESULT eDVBServiceList::flushChanges()
593 return m_bouquet->flushChanges();
596 RESULT eDVBServiceList::setListName(const std::string &name)
600 return m_bouquet->setListName(name);
603 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
605 ePtr<eDVBService> service;
606 int r = lookupService(service, ref);
609 // check resources...
610 ptr = new eDVBServicePlay(ref, service);
614 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
616 if (ref.path.empty())
618 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
627 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
629 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
630 if (list->startQuery())
640 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
642 /* is a listable service? */
643 if (ref.flags & eServiceReference::canDescent) // bouquet
645 if ( !ref.name.empty() ) // satellites or providers list
646 ptr = m_StaticServiceDVBInfo;
647 else // a dvb bouquet
648 ptr = m_StaticServiceDVBBouquetInfo;
650 else if (!ref.path.empty()) /* do we have a PVR service? */
651 ptr = new eStaticServiceDVBPVRInformation(ref);
652 else // normal dvb service
654 ePtr<eDVBService> service;
655 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
656 ptr = m_StaticServiceDVBInfo;
658 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
664 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
666 if (ref.path.empty())
672 ptr = new eDVBPVRServiceOfflineOperations(ref);
677 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
679 // TODO: handle the listing itself
680 // if (ref.... == -1) .. return "... bouquets ...";
681 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
683 ePtr<iDVBChannelList> db;
684 ePtr<eDVBResourceManager> res;
687 if ((err = eDVBResourceManager::getInstance(res)) != 0)
689 eDebug("no resource manager");
692 if ((err = res->getChannelList(db)) != 0)
694 eDebug("no channel list");
698 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
699 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
701 eDebug("getService failed!");
708 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
709 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
712 m_is_pvr = !m_reference.path.empty();
714 m_timeshift_enabled = m_timeshift_active = 0;
717 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
718 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
719 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
721 m_cuesheet_changed = 0;
722 m_cutlist_enabled = 1;
724 m_subtitle_widget = 0;
726 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
729 eDVBServicePlay::~eDVBServicePlay()
731 delete m_subtitle_widget;
734 void eDVBServicePlay::gotNewEvent()
738 ePtr<eServiceEvent> m_event_now, m_event_next;
739 getEvent(m_event_now, 0);
740 getEvent(m_event_next, 1);
743 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
745 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
747 m_event((iPlayableService*)this, evUpdatedEventInfo);
750 void eDVBServicePlay::serviceEvent(int event)
754 case eDVBServicePMTHandler::eventTuned:
756 ePtr<iDVBDemux> m_demux;
757 if (!m_service_handler.getDataDemux(m_demux))
759 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
760 int sid = ref.getParentServiceID().get();
762 sid = ref.getServiceID().get();
763 if ( ref.getParentTransportStreamID().get() &&
764 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
765 m_event_handler.startOther(m_demux, sid);
767 m_event_handler.start(m_demux, sid);
771 case eDVBServicePMTHandler::eventTuneFailed:
773 eDebug("DVB service failed to tune");
774 m_event((iPlayableService*)this, evTuneFailed);
777 case eDVBServicePMTHandler::eventNewProgramInfo:
779 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
780 if (m_timeshift_enabled)
781 updateTimeshiftPids();
782 if (!m_timeshift_active)
784 if (m_first_program_info && m_is_pvr)
786 m_first_program_info = 0;
789 m_event((iPlayableService*)this, evUpdatedInfo);
792 case eDVBServicePMTHandler::eventEOF:
793 m_event((iPlayableService*)this, evEOF);
795 case eDVBServicePMTHandler::eventSOF:
796 m_event((iPlayableService*)this, evSOF);
801 void eDVBServicePlay::serviceEventTimeshift(int event)
805 case eDVBServicePMTHandler::eventNewProgramInfo:
806 if (m_timeshift_active)
809 case eDVBServicePMTHandler::eventSOF:
810 m_event((iPlayableService*)this, evSOF);
812 case eDVBServicePMTHandler::eventEOF:
818 RESULT eDVBServicePlay::start()
821 /* in pvr mode, we only want to use one demux. in tv mode, we're using
822 two (one for decoding, one for data source), as we must be prepared
823 to start recording from the data demux. */
825 m_cue = new eCueSheet();
827 m_first_program_info = 1;
828 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
829 r = m_service_handler.tune(service, m_is_pvr, m_cue);
831 /* inject EIT if there is a stored one */
834 std::string filename = service.path;
835 filename.erase(filename.length()-2, 2);
837 ePtr<eServiceEvent> event = new eServiceEvent;
838 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
840 ePtr<eServiceEvent> empty;
841 m_event_handler.inject(event, 0);
842 m_event_handler.inject(empty, 1);
849 m_event(this, evStart);
850 m_event((iPlayableService*)this, evSeekableStatusChanged);
854 RESULT eDVBServicePlay::stop()
856 /* add bookmark for last play position */
860 if (!getPlayPosition(play_position))
862 /* remove last position */
863 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
865 if (i->what == 3) /* current play position */
867 m_cue_entries.erase(i);
868 i = m_cue_entries.begin();
874 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
875 m_cuesheet_changed = 1;
879 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
881 m_service_handler_timeshift.free();
882 m_service_handler.free();
884 if (m_is_pvr && m_cuesheet_changed)
887 /* save cuesheet only when main file is accessible. */
888 if (!::stat(m_reference.path.c_str(), &s))
895 RESULT eDVBServicePlay::setTarget(int target)
897 m_is_primary = !target;
901 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
903 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
907 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
909 /* note: we check for timeshift to be enabled,
910 not neccessary active. if you pause when timeshift
911 is not active, you should activate it when unpausing */
912 if ((!m_is_pvr) && (!m_timeshift_enabled))
922 RESULT eDVBServicePlay::setSlowMotion(int ratio)
925 return m_decoder->setSlowMotion(ratio);
930 RESULT eDVBServicePlay::setFastForward(int ratio)
932 int skipmode, ffratio;
938 } else if (ratio > 0)
946 } else // if (ratio < 0)
952 if (m_skipmode != skipmode)
954 eDebug("setting cue skipmode to %d", skipmode);
956 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
959 m_skipmode = skipmode;
964 return m_decoder->setFastForward(ffratio);
967 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
969 if (m_is_pvr || m_timeshift_enabled)
979 /* TODO: when timeshift is enabled but not active, this doesn't work. */
980 RESULT eDVBServicePlay::getLength(pts_t &len)
982 ePtr<iDVBPVRChannel> pvr_channel;
984 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
987 return pvr_channel->getLength(len);
990 RESULT eDVBServicePlay::pause()
992 if (!m_is_paused && m_decoder)
995 return m_decoder->freeze(0);
1000 RESULT eDVBServicePlay::unpause()
1002 if (m_is_paused && m_decoder)
1005 return m_decoder->unfreeze();
1010 RESULT eDVBServicePlay::seekTo(pts_t to)
1012 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1014 if (!m_decode_demux)
1017 ePtr<iDVBPVRChannel> pvr_channel;
1019 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1025 m_cue->seekTo(0, to);
1029 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1031 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1033 if (!m_decode_demux)
1036 ePtr<iDVBPVRChannel> pvr_channel;
1038 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1043 /* HACK until we have skip-AP api */
1044 if ((to > 0) && (to < 100))
1052 m_cue->seekTo(mode, to);
1056 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1058 ePtr<iDVBPVRChannel> pvr_channel;
1060 if (!m_decode_demux)
1063 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1068 /* if there is a decoder, use audio or video PTS */
1071 r = m_decoder->getPTS(0, pos);
1077 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1080 RESULT eDVBServicePlay::setTrickmode(int trick)
1083 m_decoder->setTrickmode(trick);
1087 RESULT eDVBServicePlay::isCurrentlySeekable()
1089 return m_is_pvr || m_timeshift_active;
1092 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1098 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1104 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1110 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1116 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1122 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1125 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1126 (m_timeshift_enabled || !m_is_pvr))
1128 if (!m_timeshift_enabled)
1130 /* we need enough diskspace */
1132 if (statfs(TSPATH "/.", &fs) < 0)
1134 eDebug("statfs failed!");
1138 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1140 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1150 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1161 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1167 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1173 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1179 RESULT eDVBServicePlay::getName(std::string &name)
1183 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1184 return i->getName(m_reference, name);
1188 m_dvb_service->getName(m_reference, name);
1192 else if (!m_reference.name.empty())
1193 eStaticServiceDVBInformation().getName(m_reference, name);
1195 name = "DVB service";
1199 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1201 return m_event_handler.getEvent(evt, nownext);
1204 int eDVBServicePlay::getInfo(int w)
1206 eDVBServicePMTHandler::program program;
1209 return resIsPyObject;
1211 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1213 if (h.getProgramInfo(program))
1219 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1221 ePtr<eServiceEvent> evt;
1222 if (!m_event_handler.getEvent(evt, 0))
1224 ePtr<eComponentData> data;
1225 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1227 if ( data->getStreamContent() == 1 )
1229 switch(data->getComponentType())
1232 case 1: // 4:3 SD PAL
1234 case 3: // 16:9 SD PAL
1235 case 4: // > 16:9 PAL
1236 case 5: // 4:3 SD NTSC
1238 case 7: // 16:9 SD NTSC
1239 case 8: // > 16:9 NTSC
1242 case 9: // 4:3 HD PAL
1244 case 0xB: // 16:9 HD PAL
1245 case 0xC: // > 16:9 HD PAL
1246 case 0xD: // 4:3 HD NTSC
1248 case 0xF: // 16:9 HD NTSC
1249 case 0x10: // > 16:9 HD PAL
1250 return data->getComponentType();
1257 case sIsCrypted: return program.isCrypted();
1258 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1259 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1260 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1261 case sPCRPID: return program.pcrPid;
1262 case sPMTPID: return program.pmtPid;
1263 case sTXTPID: return program.textPid;
1264 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1265 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1266 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1267 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1268 case sProvider: if (!m_dvb_service) return -1; return -2;
1269 case sServiceref: return resIsString;
1275 std::string eDVBServicePlay::getInfoString(int w)
1280 if (!m_dvb_service) return "";
1281 return m_dvb_service->m_provider_name;
1283 return m_reference.toString();
1287 return iServiceInformation::getInfoString(w);
1290 PyObject *eDVBServicePlay::getInfoObject(int w)
1295 return m_service_handler.getCaIds();
1299 return iServiceInformation::getInfoObject(w);
1302 int eDVBServicePlay::getNumberOfTracks()
1304 eDVBServicePMTHandler::program program;
1305 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1306 if (h.getProgramInfo(program))
1308 return program.audioStreams.size();
1311 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1313 int ret = selectAudioStream(i);
1315 if (m_decoder->start())
1321 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1323 eDVBServicePMTHandler::program program;
1324 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1326 if (h.getProgramInfo(program))
1329 if (i >= program.audioStreams.size())
1332 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1333 info.m_description = "MPEG";
1334 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1335 info.m_description = "AC3";
1336 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1337 info.m_description = "AAC";
1338 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1339 info.m_description = "DTS";
1341 info.m_description = "???";
1343 if (program.audioStreams[i].component_tag != -1)
1345 ePtr<eServiceEvent> evt;
1346 if (!m_event_handler.getEvent(evt, 0))
1348 ePtr<eComponentData> data;
1349 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1350 info.m_language = data->getText();
1354 if (info.m_language.empty())
1355 info.m_language = program.audioStreams[i].language_code;
1360 int eDVBServicePlay::selectAudioStream(int i)
1362 eDVBServicePMTHandler::program program;
1363 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1365 if (h.getProgramInfo(program))
1368 if ((unsigned int)i >= program.audioStreams.size())
1374 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1377 if (m_radiotext_parser)
1378 m_radiotext_parser->start(program.audioStreams[i].pid);
1380 if (m_dvb_service && !m_is_pvr)
1382 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1384 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1385 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1389 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1390 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1394 h.resetCachedProgram();
1399 int eDVBServicePlay::getCurrentChannel()
1401 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1404 RESULT eDVBServicePlay::selectChannel(int i)
1406 if (i < LEFT || i > RIGHT || i == STEREO)
1409 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1411 m_decoder->setAudioChannel(i);
1415 std::string eDVBServicePlay::getRadioText(int x)
1417 if (m_radiotext_parser)
1421 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1426 void eDVBServicePlay::radioTextUpdated()
1428 m_event((iPlayableService*)this, evUpdatedRadioText);
1431 int eDVBServiceBase::getFrontendInfo(int w)
1433 eUsePtr<iDVBChannel> channel;
1434 if(m_service_handler.getChannel(channel))
1436 ePtr<iDVBFrontend> fe;
1437 if(channel->getFrontend(fe))
1439 return fe->readFrontendData(w);
1442 PyObject *eDVBServiceBase::getFrontendData(bool original)
1446 eUsePtr<iDVBChannel> channel;
1447 if(!m_service_handler.getChannel(channel))
1449 ePtr<iDVBFrontend> fe;
1450 if(!channel->getFrontend(fe))
1452 ret = fe->readTransponderData(original);
1455 ePtr<iDVBFrontendParameters> feparm;
1456 channel->getCurrentFrontendParameters(feparm);
1459 eDVBFrontendParametersSatellite osat;
1460 if (!feparm->getDVBS(osat))
1462 void PutToDict(ePyObject &, const char*, long);
1463 void PutToDict(ePyObject &, const char*, const char*);
1464 PutToDict(ret, "orbital_position", osat.orbital_position);
1465 const char *tmp = "UNKNOWN";
1466 switch(osat.polarisation)
1468 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1469 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1470 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1471 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1474 PutToDict(ret, "polarization", tmp);
1488 int eDVBServicePlay::getNumberOfSubservices()
1490 ePtr<eServiceEvent> evt;
1491 if (!m_event_handler.getEvent(evt, 0))
1492 return evt->getNumOfLinkageServices();
1496 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1498 ePtr<eServiceEvent> evt;
1499 if (!m_event_handler.getEvent(evt, 0))
1501 if (!evt->getLinkageService(sub, m_reference, n))
1504 sub.type=eServiceReference::idInvalid;
1508 RESULT eDVBServicePlay::startTimeshift()
1510 ePtr<iDVBDemux> demux;
1512 eDebug("Start timeshift!");
1514 if (m_timeshift_enabled)
1517 /* start recording with the data demux. */
1518 if (m_service_handler.getDataDemux(demux))
1521 demux->createTSRecorder(m_record);
1525 char templ[]=TSPATH "/timeshift.XXXXXX";
1526 m_timeshift_fd = mkstemp(templ);
1527 m_timeshift_file = templ;
1529 eDebug("recording to %s", templ);
1531 if (m_timeshift_fd < 0)
1537 m_record->setTargetFD(m_timeshift_fd);
1539 m_timeshift_enabled = 1;
1541 updateTimeshiftPids();
1547 RESULT eDVBServicePlay::stopTimeshift()
1549 if (!m_timeshift_enabled)
1554 m_timeshift_enabled = 0;
1559 close(m_timeshift_fd);
1560 eDebug("remove timeshift file");
1561 remove(m_timeshift_file.c_str());
1566 int eDVBServicePlay::isTimeshiftActive()
1568 return m_timeshift_enabled && m_timeshift_active;
1571 RESULT eDVBServicePlay::activateTimeshift()
1573 if (!m_timeshift_enabled)
1576 if (!m_timeshift_active)
1578 switchToTimeshift();
1585 PyObject *eDVBServicePlay::getCutList()
1587 ePyObject list = PyList_New(0);
1589 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1591 ePyObject tuple = PyTuple_New(2);
1592 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1593 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1594 PyList_Append(list, tuple);
1601 void eDVBServicePlay::setCutList(ePyObject list)
1603 if (!PyList_Check(list))
1605 int size = PyList_Size(list);
1608 m_cue_entries.clear();
1610 for (i=0; i<size; ++i)
1612 ePyObject tuple = PyList_GET_ITEM(list, i);
1613 if (!PyTuple_Check(tuple))
1615 eDebug("non-tuple in cutlist");
1618 if (PyTuple_Size(tuple) != 2)
1620 eDebug("cutlist entries need to be a 2-tuple");
1623 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1624 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1626 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1629 pts_t pts = PyLong_AsLongLong(ppts);
1630 int type = PyInt_AsLong(ptype);
1631 m_cue_entries.insert(cueEntry(pts, type));
1632 eDebug("adding %08llx, %d", pts, type);
1634 m_cuesheet_changed = 1;
1636 cutlistToCuesheet();
1637 m_event((iPlayableService*)this, evCuesheetChanged);
1640 void eDVBServicePlay::setCutListEnable(int enable)
1642 m_cutlist_enabled = enable;
1643 cutlistToCuesheet();
1646 void eDVBServicePlay::updateTimeshiftPids()
1651 eDVBServicePMTHandler::program program;
1652 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1654 if (h.getProgramInfo(program))
1658 std::set<int> pids_to_record;
1659 pids_to_record.insert(0); // PAT
1660 if (program.pmtPid != -1)
1661 pids_to_record.insert(program.pmtPid); // PMT
1663 if (program.textPid != -1)
1664 pids_to_record.insert(program.textPid); // Videotext
1666 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1667 i(program.videoStreams.begin());
1668 i != program.videoStreams.end(); ++i)
1669 pids_to_record.insert(i->pid);
1671 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1672 i(program.audioStreams.begin());
1673 i != program.audioStreams.end(); ++i)
1674 pids_to_record.insert(i->pid);
1676 std::set<int> new_pids, obsolete_pids;
1678 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1679 m_pids_active.begin(), m_pids_active.end(),
1680 std::inserter(new_pids, new_pids.begin()));
1682 std::set_difference(
1683 m_pids_active.begin(), m_pids_active.end(),
1684 pids_to_record.begin(), pids_to_record.end(),
1685 std::inserter(new_pids, new_pids.begin())
1688 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1689 m_record->addPID(*i);
1691 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1692 m_record->removePID(*i);
1696 void eDVBServicePlay::switchToLive()
1698 if (!m_timeshift_active)
1704 m_teletext_parser = 0;
1705 m_radiotext_parser = 0;
1706 m_subtitle_parser = 0;
1707 m_new_dvb_subtitle_page_connection = 0;
1708 m_new_subtitle_page_connection = 0;
1709 m_radiotext_updated_connection = 0;
1711 /* free the timeshift service handler, we need the resources */
1712 m_service_handler_timeshift.free();
1713 m_timeshift_active = 0;
1715 m_event((iPlayableService*)this, evSeekableStatusChanged);
1720 void eDVBServicePlay::switchToTimeshift()
1722 if (m_timeshift_active)
1727 m_teletext_parser = 0;
1728 m_radiotext_parser = 0;
1729 m_subtitle_parser = 0;
1730 m_new_subtitle_page_connection = 0;
1731 m_new_dvb_subtitle_page_connection = 0;
1732 m_radiotext_updated_connection = 0;
1734 m_timeshift_active = 1;
1736 m_event((iPlayableService*)this, evSeekableStatusChanged);
1738 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1739 r.path = m_timeshift_file;
1741 m_cue = new eCueSheet();
1742 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1743 updateDecoder(); /* mainly to switch off PCR */
1746 void eDVBServicePlay::updateDecoder()
1748 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1750 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1752 bool defaultac3=false;
1753 std::string default_ac3;
1755 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1756 defaultac3 = default_ac3 == "True";
1758 eDVBServicePMTHandler::program program;
1759 if (h.getProgramInfo(program))
1760 eDebug("getting program info failed.");
1763 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1764 if (!program.videoStreams.empty())
1766 eDebugNoNewLine(" (");
1767 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1768 i(program.videoStreams.begin());
1769 i != program.videoStreams.end(); ++i)
1776 if (i != program.videoStreams.begin())
1777 eDebugNoNewLine(", ");
1778 eDebugNoNewLine("%04x", i->pid);
1780 eDebugNoNewLine(")");
1782 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1783 if (!program.audioStreams.empty())
1785 eDebugNoNewLine(" (");
1786 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1787 i(program.audioStreams.begin());
1788 i != program.audioStreams.end(); ++i)
1790 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1792 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1798 if (i != program.audioStreams.begin())
1799 eDebugNoNewLine(", ");
1800 eDebugNoNewLine("%04x", i->pid);
1802 eDebugNoNewLine(")");
1804 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1805 pcrpid = program.pcrPid;
1806 eDebug(", and the text pid is %04x", program.textPid);
1807 tpid = program.textPid;
1812 h.getDecodeDemux(m_decode_demux);
1814 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1816 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1817 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1818 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1819 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1820 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
1827 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1828 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1829 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1831 else // subservice or recording
1833 eServiceReferenceDVB ref;
1834 m_service_handler.getServiceReference(ref);
1835 eServiceReferenceDVB parent = ref.getParentServiceReference();
1840 ePtr<eDVBResourceManager> res_mgr;
1841 if (!eDVBResourceManager::getInstance(res_mgr))
1843 ePtr<iDVBChannelList> db;
1844 if (!res_mgr->getChannelList(db))
1846 ePtr<eDVBService> origService;
1847 if (!db->getService(parent, origService))
1849 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1850 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1856 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1857 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1859 m_decoder->setVideoPID(vpid, vpidtype);
1860 m_decoder->setAudioPID(apid, apidtype);
1861 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1863 m_decoder->setSyncPCR(pcrpid);
1866 ePtr<iDVBDemux> data_demux;
1867 if (!h.getDataDemux(data_demux))
1869 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1870 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1871 m_radiotext_parser->start(apid);
1876 m_decoder->setSyncPCR(-1);
1878 m_decoder->setTextPID(tpid);
1880 m_teletext_parser->start(program.textPid);
1883 m_decoder->setTrickmode(1);
1887 if (vpid > 0 && vpid < 0x2000)
1891 std::string radio_pic;
1892 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1893 m_decoder->setRadioPic(radio_pic);
1896 m_decoder->setAudioChannel(achannel);
1898 // how we can do this better?
1899 // update cache pid when the user changed the audio track or video track
1900 // TODO handling of difference audio types.. default audio types..
1902 /* don't worry about non-existing services, nor pvr services */
1903 if (m_dvb_service && !m_is_pvr)
1905 if (apidtype == eDVBAudio::aMPEG)
1907 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1908 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1912 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1913 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1915 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1916 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1917 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1918 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1921 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1924 void eDVBServicePlay::loadCuesheet()
1926 std::string filename = m_reference.path + ".cuts";
1928 m_cue_entries.clear();
1930 FILE *f = fopen(filename.c_str(), "rb");
1934 eDebug("loading cuts..");
1937 unsigned long long where;
1940 if (!fread(&where, sizeof(where), 1, f))
1942 if (!fread(&what, sizeof(what), 1, f))
1945 #if BYTE_ORDER == LITTLE_ENDIAN
1946 where = bswap_64(where);
1953 m_cue_entries.insert(cueEntry(where, what));
1956 eDebug("%d entries", m_cue_entries.size());
1958 eDebug("cutfile not found!");
1960 m_cuesheet_changed = 0;
1961 cutlistToCuesheet();
1962 m_event((iPlayableService*)this, evCuesheetChanged);
1965 void eDVBServicePlay::saveCuesheet()
1967 std::string filename = m_reference.path + ".cuts";
1969 FILE *f = fopen(filename.c_str(), "wb");
1973 unsigned long long where;
1976 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1978 #if BYTE_ORDER == BIG_ENDIAN
1981 where = bswap_64(i->where);
1983 what = htonl(i->what);
1984 fwrite(&where, sizeof(where), 1, f);
1985 fwrite(&what, sizeof(what), 1, f);
1991 m_cuesheet_changed = 0;
1994 void eDVBServicePlay::cutlistToCuesheet()
1998 eDebug("no cue sheet");
2003 if (!m_cutlist_enabled)
2005 m_cue->commitSpans();
2006 eDebug("cutlists were disabled");
2010 pts_t in = 0, out = 0, length = 0;
2014 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2018 if (i == m_cue_entries.end())
2021 if (i->what == 0) /* in */
2025 } else if (i->what == 1) /* out */
2027 else /* mark (2) or last play position (3) */
2035 m_cue->addSourceSpan(in, out);
2039 if (i == m_cue_entries.end())
2042 m_cue->commitSpans();
2045 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2047 if (m_subtitle_widget)
2048 disableSubtitles(parent);
2051 int tuplesize = PyTuple_Size(tuple);
2054 if (!PyTuple_Check(tuple))
2060 entry = PyTuple_GET_ITEM(tuple, 0);
2062 if (!PyInt_Check(entry))
2065 type = PyInt_AsLong(entry);
2067 if (type == 1) // teletext subtitles
2069 int page, magazine, pid;
2073 if (!m_teletext_parser)
2075 eDebug("enable teletext subtitles.. no parser !!!");
2079 entry = PyTuple_GET_ITEM(tuple, 1);
2080 if (!PyInt_Check(entry))
2082 pid = PyInt_AsLong(entry);
2084 entry = PyTuple_GET_ITEM(tuple, 2);
2085 if (!PyInt_Check(entry))
2087 page = PyInt_AsLong(entry);
2089 entry = PyTuple_GET_ITEM(tuple, 3);
2090 if (!PyInt_Check(entry))
2092 magazine = PyInt_AsLong(entry);
2094 m_subtitle_widget = new eSubtitleWidget(parent);
2095 m_subtitle_widget->resize(parent->size()); /* full size */
2096 m_teletext_parser->setPageAndMagazine(page, magazine);
2098 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2102 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2103 if (!m_subtitle_parser)
2105 eDebug("enable dvb subtitles.. no parser !!!");
2111 entry = PyTuple_GET_ITEM(tuple, 1);
2112 if (!PyInt_Check(entry))
2114 pid = PyInt_AsLong(entry);
2116 entry = PyTuple_GET_ITEM(tuple, 2);
2117 if (!PyInt_Check(entry))
2119 composition_page_id = PyInt_AsLong(entry);
2121 entry = PyTuple_GET_ITEM(tuple, 3);
2122 if (!PyInt_Check(entry))
2124 ancillary_page_id = PyInt_AsLong(entry);
2126 m_subtitle_widget = new eSubtitleWidget(parent);
2127 m_subtitle_widget->resize(parent->size()); /* full size */
2128 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2130 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2136 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2137 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2138 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2142 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2144 delete m_subtitle_widget;
2145 m_subtitle_widget = 0;
2146 if (m_subtitle_parser)
2148 m_subtitle_parser->stop();
2149 m_dvb_subtitle_pages.clear();
2151 if (m_teletext_parser)
2153 m_teletext_parser->setPageAndMagazine(-1, -1);
2154 m_subtitle_pages.clear();
2157 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2161 PyObject *eDVBServicePlay::getCachedSubtitle()
2165 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2168 unsigned int data = (unsigned int)tmp;
2169 int pid = (data&0xFFFF0000)>>16;
2170 ePyObject tuple = PyTuple_New(4);
2171 eDVBServicePMTHandler::program program;
2172 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2173 if (!h.getProgramInfo(program))
2175 if (program.textPid==pid) // teletext
2176 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2178 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2179 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2180 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2181 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2190 PyObject *eDVBServicePlay::getSubtitleList()
2192 if (!m_teletext_parser)
2198 ePyObject l = PyList_New(0);
2199 std::set<int> added_ttx_pages;
2201 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2202 m_teletext_parser->m_found_subtitle_pages;
2204 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2205 eDVBServicePMTHandler::program program;
2206 if (h.getProgramInfo(program))
2207 eDebug("getting program info failed.");
2210 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2211 it != program.subtitleStreams.end(); ++it)
2213 switch(it->subtitling_type)
2215 case 0x01: // ebu teletext subtitles
2217 int page_number = it->teletext_page_number & 0xFF;
2218 int magazine_number = it->teletext_magazine_number & 7;
2219 int hash = magazine_number << 8 | page_number;
2220 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2222 ePyObject tuple = PyTuple_New(5);
2223 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2224 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2225 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2226 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2227 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2228 PyList_Append(l, tuple);
2230 added_ttx_pages.insert(hash);
2235 case 0x20 ... 0x23: // dvb subtitles
2237 ePyObject tuple = PyTuple_New(5);
2238 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2239 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2240 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2241 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2242 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2243 PyList_Insert(l, 0, tuple);
2251 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2252 it != subs.end(); ++it)
2254 int page_number = it->teletext_page_number & 0xFF;
2255 int magazine_number = it->teletext_magazine_number & 7;
2256 int hash = magazine_number << 8 | page_number;
2257 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2259 ePyObject tuple = PyTuple_New(5);
2260 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2261 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2262 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2263 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2264 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2265 PyList_Append(l, tuple);
2273 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2275 if (m_subtitle_widget)
2277 m_subtitle_pages.push_back(page);
2278 checkSubtitleTiming();
2282 void eDVBServicePlay::checkSubtitleTiming()
2284 // eDebug("checkSubtitleTiming");
2285 if (!m_subtitle_widget)
2289 enum { TELETEXT, DVB } type;
2290 eDVBTeletextSubtitlePage page;
2291 eDVBSubtitlePage dvb_page;
2293 if (!m_subtitle_pages.empty())
2295 page = m_subtitle_pages.front();
2297 show_time = page.m_pts;
2299 else if (!m_dvb_subtitle_pages.empty())
2301 dvb_page = m_dvb_subtitle_pages.front();
2303 show_time = dvb_page.m_show_time;
2311 m_decoder->getPTS(0, pos);
2313 // eDebug("%lld %lld", pos, show_time);
2314 int diff = show_time - pos;
2317 eDebug("[late (%d ms)]", -diff / 90);
2322 eDebug("[invalid]");
2328 if (type == TELETEXT)
2330 eDebug("display teletext subtitle page");
2331 m_subtitle_widget->setPage(page);
2332 m_subtitle_pages.pop_front();
2336 eDebug("display dvb subtitle Page");
2337 m_subtitle_widget->setPage(dvb_page);
2338 m_dvb_subtitle_pages.pop_front();
2342 // eDebug("start subtitle delay %d", diff / 90);
2343 m_subtitle_sync_timer.start(diff / 90, 1);
2349 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2351 if (m_subtitle_widget)
2353 m_dvb_subtitle_pages.push_back(p);
2354 checkSubtitleTiming();
2358 int eDVBServicePlay::getAC3Delay()
2361 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2363 return m_decoder->getAC3Delay();
2368 int eDVBServicePlay::getPCMDelay()
2371 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2373 return m_decoder->getPCMDelay();
2378 void eDVBServicePlay::setAC3Delay(int delay)
2381 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2383 m_decoder->setAC3Delay(delay);
2386 void eDVBServicePlay::setPCMDelay(int delay)
2389 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2391 m_decoder->setPCMDelay(delay);
2394 DEFINE_REF(eDVBServicePlay)
2396 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");