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 sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
1129 case sPCRPID: return program.pcrPid;
1130 case sPMTPID: return program.pmtPid;
1131 case sTXTPID: return program.textPid;
1132 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1133 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1134 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1135 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1136 case sProvider: if (!m_dvb_service) return -1; return -2;
1142 std::string eDVBServicePlay::getInfoString(int w)
1147 if (!m_dvb_service) return "";
1148 return m_dvb_service->m_provider_name;
1152 return iServiceInformation::getInfoString(w);
1155 PyObject *eDVBServicePlay::getInfoObject(int w)
1160 return m_service_handler.getCaIds();
1164 return iServiceInformation::getInfoObject(w);
1167 int eDVBServicePlay::getNumberOfTracks()
1169 eDVBServicePMTHandler::program program;
1170 if (m_service_handler.getProgramInfo(program))
1172 return program.audioStreams.size();
1175 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1177 int ret = selectAudioStream(i);
1179 if (m_decoder->start())
1185 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1187 eDVBServicePMTHandler::program program;
1189 if (m_service_handler.getProgramInfo(program))
1192 if (i >= program.audioStreams.size())
1195 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1196 info.m_description = "MPEG";
1197 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1198 info.m_description = "AC3";
1199 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1200 info.m_description = "DTS";
1202 info.m_description = "???";
1204 if (program.audioStreams[i].component_tag != -1)
1206 ePtr<eServiceEvent> evt;
1207 if (!m_event_handler.getEvent(evt, 0))
1209 ePtr<eComponentData> data;
1210 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1211 info.m_language = data->getText();
1215 if (info.m_language.empty())
1216 info.m_language = program.audioStreams[i].language_code;
1221 int eDVBServicePlay::selectAudioStream(int i)
1223 eDVBServicePMTHandler::program program;
1225 if (m_service_handler.getProgramInfo(program))
1228 if ((unsigned int)i >= program.audioStreams.size())
1234 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1237 if (m_dvb_service && !m_is_pvr)
1239 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1241 m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
1242 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1245 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1246 m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
1250 m_current_audio_stream = i;
1255 int eDVBServicePlay::getFrontendInfo(int w)
1259 eUsePtr<iDVBChannel> channel;
1260 if(m_service_handler.getChannel(channel))
1262 ePtr<iDVBFrontend> fe;
1263 if(channel->getFrontend(fe))
1265 return fe->readFrontendData(w);
1268 PyObject *eDVBServicePlay::getFrontendData(bool original)
1272 eUsePtr<iDVBChannel> channel;
1273 if(!m_service_handler.getChannel(channel))
1275 ePtr<iDVBFrontend> fe;
1276 if(!channel->getFrontend(fe))
1278 ret = fe->readTransponderData(original);
1281 ePtr<iDVBFrontendParameters> feparm;
1282 channel->getCurrentFrontendParameters(feparm);
1285 eDVBFrontendParametersSatellite osat;
1286 if (!feparm->getDVBS(osat))
1288 void PutToDict(PyObject *, const char*, long);
1289 void PutToDict(PyObject *, const char*, const char*);
1290 PutToDict(ret, "orbital_position", osat.orbital_position);
1291 const char *tmp = "UNKNOWN";
1292 switch(osat.polarisation)
1294 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1295 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1296 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1297 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1300 PutToDict(ret, "polarization", tmp);
1314 int eDVBServicePlay::getNumberOfSubservices()
1316 ePtr<eServiceEvent> evt;
1317 if (!m_event_handler.getEvent(evt, 0))
1318 return evt->getNumOfLinkageServices();
1322 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1324 ePtr<eServiceEvent> evt;
1325 if (!m_event_handler.getEvent(evt, 0))
1327 if (!evt->getLinkageService(sub, m_reference, n))
1330 sub.type=eServiceReference::idInvalid;
1334 RESULT eDVBServicePlay::startTimeshift()
1336 ePtr<iDVBDemux> demux;
1338 eDebug("Start timeshift!");
1340 if (m_timeshift_enabled)
1343 /* start recording with the data demux. */
1344 if (m_service_handler.getDataDemux(demux))
1347 demux->createTSRecorder(m_record);
1351 char templ[]=TSPATH "/timeshift.XXXXXX";
1352 m_timeshift_fd = mkstemp(templ);
1353 m_timeshift_file = templ;
1355 eDebug("recording to %s", templ);
1357 if (m_timeshift_fd < 0)
1363 m_record->setTargetFD(m_timeshift_fd);
1365 m_timeshift_enabled = 1;
1367 updateTimeshiftPids();
1373 RESULT eDVBServicePlay::stopTimeshift()
1375 if (!m_timeshift_enabled)
1380 m_timeshift_enabled = 0;
1385 close(m_timeshift_fd);
1386 eDebug("remove timeshift file");
1387 remove(m_timeshift_file.c_str());
1392 int eDVBServicePlay::isTimeshiftActive()
1394 return m_timeshift_enabled && m_timeshift_active;
1397 RESULT eDVBServicePlay::activateTimeshift()
1399 if (!m_timeshift_enabled)
1402 if (!m_timeshift_active)
1404 switchToTimeshift();
1411 PyObject *eDVBServicePlay::getCutList()
1413 PyObject *list = PyList_New(0);
1415 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1417 PyObject *tuple = PyTuple_New(2);
1418 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1419 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1420 PyList_Append(list, tuple);
1427 void eDVBServicePlay::setCutList(PyObject *list)
1429 if (!PyList_Check(list))
1431 int size = PyList_Size(list);
1434 m_cue_entries.clear();
1436 for (i=0; i<size; ++i)
1438 PyObject *tuple = PyList_GetItem(list, i);
1439 if (!PyTuple_Check(tuple))
1441 eDebug("non-tuple in cutlist");
1444 if (PyTuple_Size(tuple) != 2)
1446 eDebug("cutlist entries need to be a 2-tuple");
1449 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1450 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1452 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1455 pts_t pts = PyLong_AsLongLong(ppts);
1456 int type = PyInt_AsLong(ptype);
1457 m_cue_entries.insert(cueEntry(pts, type));
1458 eDebug("adding %08llx, %d", pts, type);
1460 m_cuesheet_changed = 1;
1462 cutlistToCuesheet();
1463 m_event((iPlayableService*)this, evCuesheetChanged);
1466 void eDVBServicePlay::setCutListEnable(int enable)
1468 m_cutlist_enabled = enable;
1469 cutlistToCuesheet();
1472 void eDVBServicePlay::updateTimeshiftPids()
1477 eDVBServicePMTHandler::program program;
1478 if (m_service_handler.getProgramInfo(program))
1482 std::set<int> pids_to_record;
1483 pids_to_record.insert(0); // PAT
1484 if (program.pmtPid != -1)
1485 pids_to_record.insert(program.pmtPid); // PMT
1487 if (program.textPid != -1)
1488 pids_to_record.insert(program.textPid); // Videotext
1490 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1491 i(program.videoStreams.begin());
1492 i != program.videoStreams.end(); ++i)
1493 pids_to_record.insert(i->pid);
1495 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1496 i(program.audioStreams.begin());
1497 i != program.audioStreams.end(); ++i)
1498 pids_to_record.insert(i->pid);
1500 std::set<int> new_pids, obsolete_pids;
1502 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1503 m_pids_active.begin(), m_pids_active.end(),
1504 std::inserter(new_pids, new_pids.begin()));
1506 std::set_difference(
1507 m_pids_active.begin(), m_pids_active.end(),
1508 pids_to_record.begin(), pids_to_record.end(),
1509 std::inserter(new_pids, new_pids.begin())
1512 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1513 m_record->addPID(*i);
1515 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1516 m_record->removePID(*i);
1520 void eDVBServicePlay::switchToLive()
1522 if (!m_timeshift_active)
1528 m_teletext_parser = 0;
1530 /* free the timeshift service handler, we need the resources */
1531 m_service_handler_timeshift.free();
1532 m_timeshift_active = 0;
1534 m_event((iPlayableService*)this, evSeekableStatusChanged);
1539 void eDVBServicePlay::switchToTimeshift()
1541 if (m_timeshift_active)
1546 m_teletext_parser = 0;
1548 m_timeshift_active = 1;
1550 m_event((iPlayableService*)this, evSeekableStatusChanged);
1552 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1553 r.path = m_timeshift_file;
1555 m_cue = new eCueSheet();
1556 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1557 updateDecoder(); /* mainly to switch off PCR */
1560 void eDVBServicePlay::updateDecoder()
1562 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
1563 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1565 bool defaultac3=false;
1566 std::string default_ac3;
1568 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1569 defaultac3 = default_ac3 == "enable";
1571 eDVBServicePMTHandler::program program;
1572 if (h.getProgramInfo(program))
1573 eDebug("getting program info failed.");
1576 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1577 if (!program.videoStreams.empty())
1579 eDebugNoNewLine(" (");
1580 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1581 i(program.videoStreams.begin());
1582 i != program.videoStreams.end(); ++i)
1589 if (i != program.videoStreams.begin())
1590 eDebugNoNewLine(", ");
1591 eDebugNoNewLine("%04x", i->pid);
1593 eDebugNoNewLine(")");
1595 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1596 if (!program.audioStreams.empty())
1598 eDebugNoNewLine(" (");
1599 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1600 i(program.audioStreams.begin());
1601 i != program.audioStreams.end(); ++i)
1603 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1605 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1611 if (i != program.audioStreams.begin())
1612 eDebugNoNewLine(", ");
1613 eDebugNoNewLine("%04x", i->pid);
1615 eDebugNoNewLine(")");
1617 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1618 pcrpid = program.pcrPid;
1619 eDebug(", and the text pid is %04x", program.textPid);
1620 tpid = program.textPid;
1625 h.getDecodeDemux(m_decode_demux);
1627 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1629 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1630 #ifdef INTERNAL_TELETEXT
1631 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1637 m_decoder->setVideoPID(vpid, vpidtype);
1638 m_current_audio_stream = 0;
1639 m_decoder->setAudioPID(apid, apidtype);
1640 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1641 m_decoder->setSyncPCR(pcrpid);
1643 m_decoder->setSyncPCR(-1);
1644 #ifndef INTERNAL_TELETEXT
1645 m_decoder->setTextPID(tpid);
1647 if (m_teletext_parser)
1648 m_teletext_parser->start(tpid);
1652 m_decoder->setTrickmode(1);
1654 // how we can do this better?
1655 // update cache pid when the user changed the audio track or video track
1656 // TODO handling of difference audio types.. default audio types..
1658 /* don't worry about non-existing services, nor pvr services */
1659 if (m_dvb_service && !m_is_pvr)
1661 if (apidtype == eDVBAudio::aMPEG)
1663 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
1664 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1668 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1669 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
1671 m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
1672 m_dvb_service->setCachePID(eDVBService::cVTYPE, vpidtype);
1673 m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
1674 m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
1679 void eDVBServicePlay::loadCuesheet()
1681 std::string filename = m_reference.path + ".cuts";
1683 m_cue_entries.clear();
1685 FILE *f = fopen(filename.c_str(), "rb");
1689 eDebug("loading cuts..");
1692 unsigned long long where;
1695 if (!fread(&where, sizeof(where), 1, f))
1697 if (!fread(&what, sizeof(what), 1, f))
1700 #if BYTE_ORDER == LITTLE_ENDIAN
1701 where = bswap_64(where);
1708 m_cue_entries.insert(cueEntry(where, what));
1711 eDebug("%d entries", m_cue_entries.size());
1713 eDebug("cutfile not found!");
1715 m_cuesheet_changed = 0;
1716 cutlistToCuesheet();
1717 m_event((iPlayableService*)this, evCuesheetChanged);
1720 void eDVBServicePlay::saveCuesheet()
1722 std::string filename = m_reference.path + ".cuts";
1724 FILE *f = fopen(filename.c_str(), "wb");
1728 unsigned long long where;
1731 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1733 #if BYTE_ORDER == BIG_ENDIAN
1736 where = bswap_64(i->where);
1738 what = htonl(i->what);
1739 fwrite(&where, sizeof(where), 1, f);
1740 fwrite(&what, sizeof(what), 1, f);
1746 m_cuesheet_changed = 0;
1749 void eDVBServicePlay::cutlistToCuesheet()
1753 eDebug("no cue sheet");
1758 if (!m_cutlist_enabled)
1760 m_cue->commitSpans();
1761 eDebug("cutlists where disabled");
1765 pts_t in = 0, out = 0, length = 0;
1769 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1773 if (i == m_cue_entries.end())
1776 if (i->what == 0) /* in */
1780 } else if (i->what == 1) /* out */
1790 m_cue->addSourceSpan(in, out);
1794 if (i == m_cue_entries.end())
1797 m_cue->commitSpans();
1800 DEFINE_REF(eDVBServicePlay)
1802 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");