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/init_num.h>
7 #include <lib/base/init.h>
8 #include <lib/base/nconfig.h> // access to python config
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
23 #include <netinet/in.h>
25 #include <dvbsi++/event_information_section.h>
28 #error no byte order defined!
31 #define TSPATH "/media/hdd"
33 class eStaticServiceDVBInformation: public iStaticServiceInformation
35 DECLARE_REF(eStaticServiceDVBInformation);
37 RESULT getName(const eServiceReference &ref, std::string &name);
38 int getLength(const eServiceReference &ref);
41 DEFINE_REF(eStaticServiceDVBInformation);
43 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
45 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
46 if ( !ref.name.empty() )
48 if (service.getParentTransportStreamID().get()) // linkage subservice
50 ePtr<iServiceHandler> service_center;
51 if (!eServiceCenter::getInstance(service_center))
53 eServiceReferenceDVB parent = service;
54 parent.setTransportStreamID( service.getParentTransportStreamID() );
55 parent.setServiceID( service.getParentServiceID() );
56 parent.setParentTransportStreamID(eTransportStreamID(0));
57 parent.setParentServiceID(eServiceID(0));
59 ePtr<iStaticServiceInformation> service_info;
60 if (!service_center->info(parent, service_info))
62 if (!service_info->getName(parent, name))
64 // just show short name
65 unsigned int pos = name.find("\xc2\x86");
66 if ( pos != std::string::npos )
68 pos = name.find("\xc2\x87");
69 if ( pos != std::string::npos )
85 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
90 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
92 DECLARE_REF(eStaticServiceDVBBouquetInformation);
94 RESULT getName(const eServiceReference &ref, std::string &name);
95 int getLength(const eServiceReference &ref);
98 DEFINE_REF(eStaticServiceDVBBouquetInformation);
100 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
102 ePtr<iDVBChannelList> db;
103 ePtr<eDVBResourceManager> res;
106 if ((err = eDVBResourceManager::getInstance(res)) != 0)
108 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
111 if ((err = res->getChannelList(db)) != 0)
113 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
118 if ((err = db->getBouquet(ref, bouquet)) != 0)
120 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
124 if ( bouquet && bouquet->m_bouquet_name.length() )
126 name = bouquet->m_bouquet_name;
133 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
138 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
140 DECLARE_REF(eStaticServiceDVBPVRInformation);
141 eServiceReference m_ref;
142 eDVBMetaParser m_parser;
144 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
145 RESULT getName(const eServiceReference &ref, std::string &name);
146 int getLength(const eServiceReference &ref);
148 int getInfo(const eServiceReference &ref, int w);
149 std::string getInfoString(const eServiceReference &ref,int w);
152 DEFINE_REF(eStaticServiceDVBPVRInformation);
154 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
157 m_parser.parseFile(ref.path);
160 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
162 ASSERT(ref == m_ref);
163 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
167 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
169 ASSERT(ref == m_ref);
173 if (tstools.openFile(ref.path.c_str()))
177 if (tstools.calcLen(len))
183 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
187 case iServiceInformation::sDescription:
188 return iServiceInformation::resIsString;
189 case iServiceInformation::sServiceref:
190 return iServiceInformation::resIsString;
191 case iServiceInformation::sTimeCreate:
192 if (m_parser.m_time_create)
193 return m_parser.m_time_create;
195 return iServiceInformation::resNA;
197 return iServiceInformation::resNA;
201 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
205 case iServiceInformation::sDescription:
206 return m_parser.m_description;
207 case iServiceInformation::sServiceref:
208 return m_parser.m_ref.toString();
214 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
216 DECLARE_REF(eDVBPVRServiceOfflineOperations);
217 eServiceReferenceDVB m_ref;
219 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
221 RESULT deleteFromDisk(int simulate);
222 RESULT getListOfFilenames(std::list<std::string> &);
225 DEFINE_REF(eDVBPVRServiceOfflineOperations);
227 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
231 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
237 std::list<std::string> res;
238 if (getListOfFilenames(res))
241 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
243 eDebug("FATAL !! can't get background file eraser");
245 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
247 eDebug("Removing %s...", i->c_str());
249 eraser->erase(i->c_str());
251 ::unlink(i->c_str());
258 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
261 res.push_back(m_ref.path);
263 // handling for old splitted recordings (enigma 1)
268 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
270 if (stat(buf, &s) < 0)
275 res.push_back(m_ref.path + ".meta");
276 res.push_back(m_ref.path + ".ap");
277 res.push_back(m_ref.path + ".cuts");
278 std::string tmp = m_ref.path;
279 tmp.erase(m_ref.path.length()-3);
280 res.push_back(tmp + ".eit");
284 DEFINE_REF(eServiceFactoryDVB)
286 eServiceFactoryDVB::eServiceFactoryDVB()
288 ePtr<eServiceCenter> sc;
290 eServiceCenter::getPrivInstance(sc);
292 sc->addServiceFactory(eServiceFactoryDVB::id, this);
295 eServiceFactoryDVB::~eServiceFactoryDVB()
297 ePtr<eServiceCenter> sc;
299 eServiceCenter::getPrivInstance(sc);
301 sc->removeServiceFactory(eServiceFactoryDVB::id);
304 DEFINE_REF(eDVBServiceList);
306 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
310 eDVBServiceList::~eDVBServiceList()
314 RESULT eDVBServiceList::startQuery()
316 ePtr<iDVBChannelList> db;
317 ePtr<eDVBResourceManager> res;
320 if ((err = eDVBResourceManager::getInstance(res)) != 0)
322 eDebug("no resource manager");
325 if ((err = res->getChannelList(db)) != 0)
327 eDebug("no channel list");
331 ePtr<eDVBChannelQuery> q;
333 if (!m_parent.path.empty())
335 eDVBChannelQuery::compile(q, m_parent.path);
338 eDebug("compile query failed");
343 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
345 eDebug("startQuery failed");
352 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
354 eServiceReferenceDVB ref;
359 while (!m_query->getNextResult(ref))
363 list.sort(iListableServiceCompare(this));
368 // The first argument of this function is a format string to specify the order and
369 // the content of the returned list
370 // useable format options are
371 // R = Service Reference (as swig object .. this is very slow)
372 // S = Service Reference (as python string object .. same as ref.toString())
373 // N = Service Name (as python string object)
374 // when exactly one return value per service is selected in the format string,
375 // then each value is directly a list entry
376 // when more than one value is returned per service, then the list is a list of
378 // unknown format string chars are returned as python None values !
379 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
382 std::list<eServiceReference> tmplist;
385 if (!format || !(retcount=strlen(format)))
386 format = "R"; // just return service reference swig object ...
388 if (!getContent(tmplist, sorted))
390 int services=tmplist.size();
391 ePtr<iStaticServiceInformation> sptr;
392 eServiceCenterPtr service_center;
394 if (strchr(format, 'N'))
395 eServiceCenter::getPrivInstance(service_center);
397 ret = PyList_New(services);
398 std::list<eServiceReference>::iterator it(tmplist.begin());
400 for (int cnt=0; cnt < services; ++cnt)
402 eServiceReference &ref=*it++;
403 PyObject *tuple = retcount > 1 ? PyTuple_New(retcount) : 0;
404 for (int i=0; i < retcount; ++i)
409 case 'R': // service reference (swig)object
410 tmp = New_eServiceReference(ref);
412 case 'S': // service reference string
413 tmp = PyString_FromString(ref.toString().c_str());
415 case 'N': // service name
418 service_center->info(ref, sptr);
422 sptr->getName(ref, name);
424 tmp = PyString_FromString(name.c_str());
428 tmp = PyString_FromString("<n/a>");
441 PyTuple_SET_ITEM(tuple, i, tmp);
443 PyList_SET_ITEM(ret, cnt, tmp);
447 PyList_SET_ITEM(ret, cnt, tuple);
450 return ret ? ret : PyList_New(0);
453 RESULT eDVBServiceList::getNext(eServiceReference &ref)
458 return m_query->getNextResult((eServiceReferenceDVB&)ref);
461 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
463 return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
466 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
468 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
470 ePtr<iDVBChannelList> db;
471 ePtr<eDVBResourceManager> resm;
473 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
476 if (db->getBouquet(m_parent, m_bouquet) != 0)
487 RESULT eDVBServiceList::addService(eServiceReference &ref)
491 return m_bouquet->addService(ref);
494 RESULT eDVBServiceList::removeService(eServiceReference &ref)
498 return m_bouquet->removeService(ref);
501 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
505 return m_bouquet->moveService(ref, pos);
508 RESULT eDVBServiceList::flushChanges()
512 return m_bouquet->flushChanges();
515 RESULT eDVBServiceList::setListName(const std::string &name)
519 return m_bouquet->setListName(name);
522 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
524 ePtr<eDVBService> service;
525 int r = lookupService(service, ref);
528 // check resources...
529 ptr = new eDVBServicePlay(ref, service);
533 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
535 if (ref.path.empty())
537 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
546 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
548 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
549 if (list->startQuery())
559 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
561 /* is a listable service? */
562 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
564 if ( !ref.name.empty() ) // satellites or providers list
565 ptr = new eStaticServiceDVBInformation;
566 else // a dvb bouquet
567 ptr = new eStaticServiceDVBBouquetInformation;
569 else if (!ref.path.empty()) /* do we have a PVR service? */
570 ptr = new eStaticServiceDVBPVRInformation(ref);
571 else // normal dvb service
573 ePtr<eDVBService> service;
574 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
575 ptr = new eStaticServiceDVBInformation;
577 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
583 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
585 if (ref.path.empty())
591 ptr = new eDVBPVRServiceOfflineOperations(ref);
596 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
598 // TODO: handle the listing itself
599 // if (ref.... == -1) .. return "... bouquets ...";
600 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
602 ePtr<iDVBChannelList> db;
603 ePtr<eDVBResourceManager> res;
606 if ((err = eDVBResourceManager::getInstance(res)) != 0)
608 eDebug("no resource manager");
611 if ((err = res->getChannelList(db)) != 0)
613 eDebug("no channel list");
617 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
618 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
620 eDebug("getService failed!");
627 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
628 m_reference(ref), m_dvb_service(service), m_is_paused(0)
631 m_is_pvr = !m_reference.path.empty();
633 m_timeshift_enabled = m_timeshift_active = 0;
636 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
637 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
638 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
640 m_cuesheet_changed = 0;
641 m_cutlist_enabled = 1;
644 eDVBServicePlay::~eDVBServicePlay()
648 void eDVBServicePlay::gotNewEvent()
652 ePtr<eServiceEvent> m_event_now, m_event_next;
653 getEvent(m_event_now, 0);
654 getEvent(m_event_next, 1);
657 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
659 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
661 m_event((iPlayableService*)this, evUpdatedEventInfo);
664 void eDVBServicePlay::serviceEvent(int event)
668 case eDVBServicePMTHandler::eventTuned:
670 ePtr<iDVBDemux> m_demux;
671 if (!m_service_handler.getDataDemux(m_demux))
673 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
674 int sid = ref.getParentServiceID().get();
676 sid = ref.getServiceID().get();
677 if ( ref.getParentTransportStreamID().get() &&
678 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
679 m_event_handler.startOther(m_demux, sid);
681 m_event_handler.start(m_demux, sid);
685 case eDVBServicePMTHandler::eventTuneFailed:
687 eDebug("DVB service failed to tune");
688 m_event((iPlayableService*)this, evTuneFailed);
691 case eDVBServicePMTHandler::eventNewProgramInfo:
693 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
694 if (m_timeshift_enabled)
695 updateTimeshiftPids();
696 if (!m_timeshift_active)
698 if (m_first_program_info && m_is_pvr)
700 m_first_program_info = 0;
703 m_event((iPlayableService*)this, evUpdatedInfo);
706 case eDVBServicePMTHandler::eventEOF:
707 m_event((iPlayableService*)this, evEOF);
709 case eDVBServicePMTHandler::eventSOF:
710 m_event((iPlayableService*)this, evSOF);
715 void eDVBServicePlay::serviceEventTimeshift(int event)
719 case eDVBServicePMTHandler::eventNewProgramInfo:
720 if (m_timeshift_active)
723 case eDVBServicePMTHandler::eventSOF:
724 m_event((iPlayableService*)this, evSOF);
726 case eDVBServicePMTHandler::eventEOF:
732 RESULT eDVBServicePlay::start()
735 /* in pvr mode, we only want to use one demux. in tv mode, we're using
736 two (one for decoding, one for data source), as we must be prepared
737 to start recording from the data demux. */
739 m_cue = new eCueSheet();
741 m_first_program_info = 1;
742 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
743 r = m_service_handler.tune(service, m_is_pvr, m_cue);
745 /* inject EIT if there is a stored one */
748 std::string filename = service.path;
749 filename.erase(filename.length()-2, 2);
751 int fd = ::open( filename.c_str(), O_RDONLY );
755 int rd = ::read(fd, buf, 4096);
757 if ( rd > 12 /*EIT_LOOP_SIZE*/ )
760 ePtr<eServiceEvent> event = new eServiceEvent;
761 ePtr<eServiceEvent> empty;
762 event->parseFrom(&ev, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get());
763 m_event_handler.inject(event, 0);
764 m_event_handler.inject(empty, 1);
773 m_event(this, evStart);
774 m_event((iPlayableService*)this, evSeekableStatusChanged);
778 RESULT eDVBServicePlay::stop()
780 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
782 m_service_handler_timeshift.free();
783 m_service_handler.free();
785 if (m_is_pvr && m_cuesheet_changed)
791 RESULT eDVBServicePlay::setTarget(int target)
793 m_is_primary = !target;
797 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
799 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
803 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
805 /* note: we check for timeshift to be enabled,
806 not neccessary active. if you pause when timeshift
807 is not active, you should activate it when unpausing */
808 if ((!m_is_pvr) && (!m_timeshift_enabled))
818 RESULT eDVBServicePlay::setSlowMotion(int ratio)
821 return m_decoder->setSlowMotion(ratio);
826 RESULT eDVBServicePlay::setFastForward(int ratio)
828 int skipmode, ffratio;
834 } else if (ratio > 0)
842 } else // if (ratio < 0)
848 if (m_skipmode != skipmode)
850 eDebug("setting cue skipmode to %d", skipmode);
852 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
855 m_skipmode = skipmode;
860 return m_decoder->setFastForward(ffratio);
863 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
865 if (m_is_pvr || m_timeshift_enabled)
875 /* TODO: when timeshift is enabled but not active, this doesn't work. */
876 RESULT eDVBServicePlay::getLength(pts_t &len)
878 ePtr<iDVBPVRChannel> pvr_channel;
880 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
883 return pvr_channel->getLength(len);
886 RESULT eDVBServicePlay::pause()
888 if (!m_is_paused && m_decoder)
891 return m_decoder->freeze(0);
896 RESULT eDVBServicePlay::unpause()
898 if (m_is_paused && m_decoder)
901 return m_decoder->unfreeze();
906 RESULT eDVBServicePlay::seekTo(pts_t to)
908 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
913 ePtr<iDVBPVRChannel> pvr_channel;
915 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
921 m_cue->seekTo(0, to);
925 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
927 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
932 ePtr<iDVBPVRChannel> pvr_channel;
934 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
939 /* HACK until we have skip-AP api */
940 if ((to > 0) && (to < 100))
948 m_cue->seekTo(mode, to);
952 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
954 ePtr<iDVBPVRChannel> pvr_channel;
959 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
964 /* if there is a decoder, use audio or video PTS */
967 r = m_decoder->getPTS(0, pos);
973 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
976 RESULT eDVBServicePlay::setTrickmode(int trick)
979 m_decoder->setTrickmode(trick);
983 RESULT eDVBServicePlay::isCurrentlySeekable()
985 return m_is_pvr || m_timeshift_active;
988 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
994 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1000 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1006 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1012 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1015 if (m_timeshift_enabled || !m_is_pvr)
1017 if (!m_timeshift_enabled)
1019 /* we need enough diskspace */
1021 if (statfs(TSPATH "/.", &fs) < 0)
1023 eDebug("statfs failed!");
1027 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1029 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1039 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1050 RESULT eDVBServicePlay::getName(std::string &name)
1054 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1055 return i->getName(m_reference, name);
1059 m_dvb_service->getName(m_reference, name);
1063 else if (!m_reference.name.empty())
1064 eStaticServiceDVBInformation().getName(m_reference, name);
1066 name = "DVB service";
1070 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1072 return m_event_handler.getEvent(evt, nownext);
1075 int eDVBServicePlay::getInfo(int w)
1077 eDVBServicePMTHandler::program program;
1080 return resIsPyObject;
1082 if (m_service_handler.getProgramInfo(program))
1088 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1090 ePtr<eServiceEvent> evt;
1091 if (!m_event_handler.getEvent(evt, 0))
1093 ePtr<eComponentData> data;
1094 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1096 if ( data->getStreamContent() == 1 )
1098 switch(data->getComponentType())
1101 case 1: // 4:3 SD PAL
1103 case 3: // 16:9 SD PAL
1104 case 4: // > 16:9 PAL
1105 case 5: // 4:3 SD NTSC
1107 case 7: // 16:9 SD NTSC
1108 case 8: // > 16:9 NTSC
1111 case 9: // 4:3 HD PAL
1113 case 0xB: // 16:9 HD PAL
1114 case 0xC: // > 16:9 HD PAL
1115 case 0xD: // 4:3 HD NTSC
1117 case 0xF: // 16:9 HD NTSC
1118 case 0x10: // > 16:9 HD PAL
1119 return data->getComponentType();
1126 case sIsCrypted: return program.isCrypted;
1127 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1128 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1129 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
1130 case sPCRPID: return program.pcrPid;
1131 case sPMTPID: return program.pmtPid;
1132 case sTXTPID: return program.textPid;
1133 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1134 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1135 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1136 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1137 case sProvider: if (!m_dvb_service) return -1; return -2;
1143 std::string eDVBServicePlay::getInfoString(int w)
1148 if (!m_dvb_service) return "";
1149 return m_dvb_service->m_provider_name;
1153 return iServiceInformation::getInfoString(w);
1156 PyObject *eDVBServicePlay::getInfoObject(int w)
1161 return m_service_handler.getCaIds();
1165 return iServiceInformation::getInfoObject(w);
1168 int eDVBServicePlay::getNumberOfTracks()
1170 eDVBServicePMTHandler::program program;
1171 if (m_service_handler.getProgramInfo(program))
1173 return program.audioStreams.size();
1176 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1178 int ret = selectAudioStream(i);
1180 if (m_decoder->start())
1186 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1188 eDVBServicePMTHandler::program program;
1190 if (m_service_handler.getProgramInfo(program))
1193 if (i >= program.audioStreams.size())
1196 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1197 info.m_description = "MPEG";
1198 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1199 info.m_description = "AC3";
1200 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1201 info.m_description = "DTS";
1203 info.m_description = "???";
1205 if (program.audioStreams[i].component_tag != -1)
1207 ePtr<eServiceEvent> evt;
1208 if (!m_event_handler.getEvent(evt, 0))
1210 ePtr<eComponentData> data;
1211 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1212 info.m_language = data->getText();
1216 if (info.m_language.empty())
1217 info.m_language = program.audioStreams[i].language_code;
1222 int eDVBServicePlay::selectAudioStream(int i)
1224 eDVBServicePMTHandler::program program;
1226 if (m_service_handler.getProgramInfo(program))
1229 if ((unsigned int)i >= program.audioStreams.size())
1235 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1238 if (m_dvb_service && !m_is_pvr)
1240 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1242 m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
1243 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1246 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1247 m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
1251 m_current_audio_stream = i;
1256 int eDVBServicePlay::getFrontendInfo(int w)
1260 eUsePtr<iDVBChannel> channel;
1261 if(m_service_handler.getChannel(channel))
1263 ePtr<iDVBFrontend> fe;
1264 if(channel->getFrontend(fe))
1266 return fe->readFrontendData(w);
1269 PyObject *eDVBServicePlay::getFrontendData(bool original)
1273 eUsePtr<iDVBChannel> channel;
1274 if(!m_service_handler.getChannel(channel))
1276 ePtr<iDVBFrontend> fe;
1277 if(!channel->getFrontend(fe))
1279 ret = fe->readTransponderData(original);
1282 ePtr<iDVBFrontendParameters> feparm;
1283 channel->getCurrentFrontendParameters(feparm);
1286 eDVBFrontendParametersSatellite osat;
1287 if (!feparm->getDVBS(osat))
1289 void PutToDict(PyObject *, const char*, long);
1290 void PutToDict(PyObject *, const char*, const char*);
1291 PutToDict(ret, "orbital_position", osat.orbital_position);
1292 const char *tmp = "UNKNOWN";
1293 switch(osat.polarisation)
1295 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1296 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1297 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1298 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1301 PutToDict(ret, "polarization", tmp);
1315 int eDVBServicePlay::getNumberOfSubservices()
1317 ePtr<eServiceEvent> evt;
1318 if (!m_event_handler.getEvent(evt, 0))
1319 return evt->getNumOfLinkageServices();
1323 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1325 ePtr<eServiceEvent> evt;
1326 if (!m_event_handler.getEvent(evt, 0))
1328 if (!evt->getLinkageService(sub, m_reference, n))
1331 sub.type=eServiceReference::idInvalid;
1335 RESULT eDVBServicePlay::startTimeshift()
1337 ePtr<iDVBDemux> demux;
1339 eDebug("Start timeshift!");
1341 if (m_timeshift_enabled)
1344 /* start recording with the data demux. */
1345 if (m_service_handler.getDataDemux(demux))
1348 demux->createTSRecorder(m_record);
1352 char templ[]=TSPATH "/timeshift.XXXXXX";
1353 m_timeshift_fd = mkstemp(templ);
1354 m_timeshift_file = templ;
1356 eDebug("recording to %s", templ);
1358 if (m_timeshift_fd < 0)
1364 m_record->setTargetFD(m_timeshift_fd);
1366 m_timeshift_enabled = 1;
1368 updateTimeshiftPids();
1374 RESULT eDVBServicePlay::stopTimeshift()
1376 if (!m_timeshift_enabled)
1381 m_timeshift_enabled = 0;
1386 close(m_timeshift_fd);
1387 eDebug("remove timeshift file");
1388 remove(m_timeshift_file.c_str());
1393 int eDVBServicePlay::isTimeshiftActive()
1395 return m_timeshift_enabled && m_timeshift_active;
1398 RESULT eDVBServicePlay::activateTimeshift()
1400 if (!m_timeshift_enabled)
1403 if (!m_timeshift_active)
1405 switchToTimeshift();
1412 PyObject *eDVBServicePlay::getCutList()
1414 PyObject *list = PyList_New(0);
1416 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1418 PyObject *tuple = PyTuple_New(2);
1419 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1420 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1421 PyList_Append(list, tuple);
1428 void eDVBServicePlay::setCutList(PyObject *list)
1430 if (!PyList_Check(list))
1432 int size = PyList_Size(list);
1435 m_cue_entries.clear();
1437 for (i=0; i<size; ++i)
1439 PyObject *tuple = PyList_GetItem(list, i);
1440 if (!PyTuple_Check(tuple))
1442 eDebug("non-tuple in cutlist");
1445 if (PyTuple_Size(tuple) != 2)
1447 eDebug("cutlist entries need to be a 2-tuple");
1450 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1451 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1453 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1456 pts_t pts = PyLong_AsLongLong(ppts);
1457 int type = PyInt_AsLong(ptype);
1458 m_cue_entries.insert(cueEntry(pts, type));
1459 eDebug("adding %08llx, %d", pts, type);
1461 m_cuesheet_changed = 1;
1463 cutlistToCuesheet();
1464 m_event((iPlayableService*)this, evCuesheetChanged);
1467 void eDVBServicePlay::setCutListEnable(int enable)
1469 m_cutlist_enabled = enable;
1470 cutlistToCuesheet();
1473 void eDVBServicePlay::updateTimeshiftPids()
1478 eDVBServicePMTHandler::program program;
1479 if (m_service_handler.getProgramInfo(program))
1483 std::set<int> pids_to_record;
1484 pids_to_record.insert(0); // PAT
1485 if (program.pmtPid != -1)
1486 pids_to_record.insert(program.pmtPid); // PMT
1488 if (program.textPid != -1)
1489 pids_to_record.insert(program.textPid); // Videotext
1491 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1492 i(program.videoStreams.begin());
1493 i != program.videoStreams.end(); ++i)
1494 pids_to_record.insert(i->pid);
1496 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1497 i(program.audioStreams.begin());
1498 i != program.audioStreams.end(); ++i)
1499 pids_to_record.insert(i->pid);
1501 std::set<int> new_pids, obsolete_pids;
1503 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1504 m_pids_active.begin(), m_pids_active.end(),
1505 std::inserter(new_pids, new_pids.begin()));
1507 std::set_difference(
1508 m_pids_active.begin(), m_pids_active.end(),
1509 pids_to_record.begin(), pids_to_record.end(),
1510 std::inserter(new_pids, new_pids.begin())
1513 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1514 m_record->addPID(*i);
1516 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1517 m_record->removePID(*i);
1521 void eDVBServicePlay::switchToLive()
1523 if (!m_timeshift_active)
1529 m_teletext_parser = 0;
1531 /* free the timeshift service handler, we need the resources */
1532 m_service_handler_timeshift.free();
1533 m_timeshift_active = 0;
1535 m_event((iPlayableService*)this, evSeekableStatusChanged);
1540 void eDVBServicePlay::switchToTimeshift()
1542 if (m_timeshift_active)
1547 m_teletext_parser = 0;
1549 m_timeshift_active = 1;
1551 m_event((iPlayableService*)this, evSeekableStatusChanged);
1553 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1554 r.path = m_timeshift_file;
1556 m_cue = new eCueSheet();
1557 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1558 updateDecoder(); /* mainly to switch off PCR */
1561 void eDVBServicePlay::updateDecoder()
1563 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
1564 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1566 bool defaultac3=false;
1567 std::string default_ac3;
1569 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1570 defaultac3 = default_ac3 == "enable";
1572 eDVBServicePMTHandler::program program;
1573 if (h.getProgramInfo(program))
1574 eDebug("getting program info failed.");
1577 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1578 if (!program.videoStreams.empty())
1580 eDebugNoNewLine(" (");
1581 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1582 i(program.videoStreams.begin());
1583 i != program.videoStreams.end(); ++i)
1590 if (i != program.videoStreams.begin())
1591 eDebugNoNewLine(", ");
1592 eDebugNoNewLine("%04x", i->pid);
1594 eDebugNoNewLine(")");
1596 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1597 if (!program.audioStreams.empty())
1599 eDebugNoNewLine(" (");
1600 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1601 i(program.audioStreams.begin());
1602 i != program.audioStreams.end(); ++i)
1604 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1606 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1612 if (i != program.audioStreams.begin())
1613 eDebugNoNewLine(", ");
1614 eDebugNoNewLine("%04x", i->pid);
1616 eDebugNoNewLine(")");
1618 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1619 pcrpid = program.pcrPid;
1620 eDebug(", and the text pid is %04x", program.textPid);
1621 tpid = program.textPid;
1626 h.getDecodeDemux(m_decode_demux);
1628 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1630 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1631 #ifdef INTERNAL_TELETEXT
1632 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1638 m_decoder->setVideoPID(vpid, vpidtype);
1639 m_current_audio_stream = 0;
1640 m_decoder->setAudioPID(apid, apidtype);
1641 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1642 m_decoder->setSyncPCR(pcrpid);
1644 m_decoder->setSyncPCR(-1);
1645 #ifndef INTERNAL_TELETEXT
1646 m_decoder->setTextPID(tpid);
1648 if (m_teletext_parser)
1649 m_teletext_parser->start(tpid);
1653 m_decoder->setTrickmode(1);
1655 // how we can do this better?
1656 // update cache pid when the user changed the audio track or video track
1657 // TODO handling of difference audio types.. default audio types..
1659 /* don't worry about non-existing services, nor pvr services */
1660 if (m_dvb_service && !m_is_pvr)
1662 if (apidtype == eDVBAudio::aMPEG)
1664 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
1665 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1669 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1670 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
1672 m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
1673 m_dvb_service->setCachePID(eDVBService::cVTYPE, vpidtype);
1674 m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
1675 m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
1680 void eDVBServicePlay::loadCuesheet()
1682 std::string filename = m_reference.path + ".cuts";
1684 m_cue_entries.clear();
1686 FILE *f = fopen(filename.c_str(), "rb");
1690 eDebug("loading cuts..");
1693 unsigned long long where;
1696 if (!fread(&where, sizeof(where), 1, f))
1698 if (!fread(&what, sizeof(what), 1, f))
1701 #if BYTE_ORDER == LITTLE_ENDIAN
1702 where = bswap_64(where);
1709 m_cue_entries.insert(cueEntry(where, what));
1712 eDebug("%d entries", m_cue_entries.size());
1714 eDebug("cutfile not found!");
1716 m_cuesheet_changed = 0;
1717 cutlistToCuesheet();
1718 m_event((iPlayableService*)this, evCuesheetChanged);
1721 void eDVBServicePlay::saveCuesheet()
1723 std::string filename = m_reference.path + ".cuts";
1725 FILE *f = fopen(filename.c_str(), "wb");
1729 unsigned long long where;
1732 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1734 #if BYTE_ORDER == BIG_ENDIAN
1737 where = bswap_64(i->where);
1739 what = htonl(i->what);
1740 fwrite(&where, sizeof(where), 1, f);
1741 fwrite(&what, sizeof(what), 1, f);
1747 m_cuesheet_changed = 0;
1750 void eDVBServicePlay::cutlistToCuesheet()
1754 eDebug("no cue sheet");
1759 if (!m_cutlist_enabled)
1761 m_cue->commitSpans();
1762 eDebug("cutlists where disabled");
1766 pts_t in = 0, out = 0, length = 0;
1770 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1774 if (i == m_cue_entries.end())
1777 if (i->what == 0) /* in */
1781 } else if (i->what == 1) /* out */
1791 m_cue->addSourceSpan(in, out);
1795 if (i == m_cue_entries.end())
1798 m_cue->commitSpans();
1801 DEFINE_REF(eDVBServicePlay)
1803 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");