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::frontendInfo(ePtr<iFrontendInformation> &ptr)
994 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1000 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1006 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1012 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1018 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1021 if (m_timeshift_enabled || !m_is_pvr)
1023 if (!m_timeshift_enabled)
1025 /* we need enough diskspace */
1027 if (statfs(TSPATH "/.", &fs) < 0)
1029 eDebug("statfs failed!");
1033 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1035 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1045 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1056 RESULT eDVBServicePlay::getName(std::string &name)
1060 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1061 return i->getName(m_reference, name);
1065 m_dvb_service->getName(m_reference, name);
1069 else if (!m_reference.name.empty())
1070 eStaticServiceDVBInformation().getName(m_reference, name);
1072 name = "DVB service";
1076 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1078 return m_event_handler.getEvent(evt, nownext);
1081 int eDVBServicePlay::getInfo(int w)
1083 eDVBServicePMTHandler::program program;
1086 return resIsPyObject;
1088 if (m_service_handler.getProgramInfo(program))
1094 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1096 ePtr<eServiceEvent> evt;
1097 if (!m_event_handler.getEvent(evt, 0))
1099 ePtr<eComponentData> data;
1100 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1102 if ( data->getStreamContent() == 1 )
1104 switch(data->getComponentType())
1107 case 1: // 4:3 SD PAL
1109 case 3: // 16:9 SD PAL
1110 case 4: // > 16:9 PAL
1111 case 5: // 4:3 SD NTSC
1113 case 7: // 16:9 SD NTSC
1114 case 8: // > 16:9 NTSC
1117 case 9: // 4:3 HD PAL
1119 case 0xB: // 16:9 HD PAL
1120 case 0xC: // > 16:9 HD PAL
1121 case 0xD: // 4:3 HD NTSC
1123 case 0xF: // 16:9 HD NTSC
1124 case 0x10: // > 16:9 HD PAL
1125 return data->getComponentType();
1132 case sIsCrypted: return program.isCrypted;
1133 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1134 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1135 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
1136 case sPCRPID: return program.pcrPid;
1137 case sPMTPID: return program.pmtPid;
1138 case sTXTPID: return program.textPid;
1139 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1140 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1141 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1142 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1143 case sProvider: if (!m_dvb_service) return -1; return -2;
1149 std::string eDVBServicePlay::getInfoString(int w)
1154 if (!m_dvb_service) return "";
1155 return m_dvb_service->m_provider_name;
1159 return iServiceInformation::getInfoString(w);
1162 PyObject *eDVBServicePlay::getInfoObject(int w)
1167 return m_service_handler.getCaIds();
1171 return iServiceInformation::getInfoObject(w);
1174 int eDVBServicePlay::getNumberOfTracks()
1176 eDVBServicePMTHandler::program program;
1177 if (m_service_handler.getProgramInfo(program))
1179 return program.audioStreams.size();
1182 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1184 int ret = selectAudioStream(i);
1186 if (m_decoder->start())
1192 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1194 eDVBServicePMTHandler::program program;
1196 if (m_service_handler.getProgramInfo(program))
1199 if (i >= program.audioStreams.size())
1202 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1203 info.m_description = "MPEG";
1204 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1205 info.m_description = "AC3";
1206 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1207 info.m_description = "AAC";
1208 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1209 info.m_description = "DTS";
1211 info.m_description = "???";
1213 if (program.audioStreams[i].component_tag != -1)
1215 ePtr<eServiceEvent> evt;
1216 if (!m_event_handler.getEvent(evt, 0))
1218 ePtr<eComponentData> data;
1219 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1220 info.m_language = data->getText();
1224 if (info.m_language.empty())
1225 info.m_language = program.audioStreams[i].language_code;
1230 int eDVBServicePlay::selectAudioStream(int i)
1232 eDVBServicePMTHandler::program program;
1234 if (m_service_handler.getProgramInfo(program))
1237 if ((unsigned int)i >= program.audioStreams.size())
1243 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1246 if (m_dvb_service && !m_is_pvr)
1248 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1250 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1251 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1254 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1255 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1259 m_current_audio_stream = i;
1264 int eDVBServicePlay::getCurrentChannel()
1266 int curChannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1267 return curChannel == -1 ? STEREO : curChannel;
1270 RESULT eDVBServicePlay::selectChannel(int i)
1272 if (i < iAudioChannelSelection::LEFT || i > iAudioChannelSelection::RIGHT)
1274 if (m_dvb_service->getCacheEntry(eDVBService::cACHANNEL) != i)
1276 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1278 m_decoder->setAudioChannel(i);
1282 int eDVBServiceBase::getFrontendInfo(int w)
1284 eUsePtr<iDVBChannel> channel;
1285 if(m_service_handler.getChannel(channel))
1287 ePtr<iDVBFrontend> fe;
1288 if(channel->getFrontend(fe))
1290 return fe->readFrontendData(w);
1293 PyObject *eDVBServiceBase::getFrontendData(bool original)
1297 eUsePtr<iDVBChannel> channel;
1298 if(!m_service_handler.getChannel(channel))
1300 ePtr<iDVBFrontend> fe;
1301 if(!channel->getFrontend(fe))
1303 ret = fe->readTransponderData(original);
1306 ePtr<iDVBFrontendParameters> feparm;
1307 channel->getCurrentFrontendParameters(feparm);
1310 eDVBFrontendParametersSatellite osat;
1311 if (!feparm->getDVBS(osat))
1313 void PutToDict(PyObject *, const char*, long);
1314 void PutToDict(PyObject *, const char*, const char*);
1315 PutToDict(ret, "orbital_position", osat.orbital_position);
1316 const char *tmp = "UNKNOWN";
1317 switch(osat.polarisation)
1319 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1320 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1321 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1322 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1325 PutToDict(ret, "polarization", tmp);
1339 int eDVBServicePlay::getNumberOfSubservices()
1341 ePtr<eServiceEvent> evt;
1342 if (!m_event_handler.getEvent(evt, 0))
1343 return evt->getNumOfLinkageServices();
1347 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1349 ePtr<eServiceEvent> evt;
1350 if (!m_event_handler.getEvent(evt, 0))
1352 if (!evt->getLinkageService(sub, m_reference, n))
1355 sub.type=eServiceReference::idInvalid;
1359 RESULT eDVBServicePlay::startTimeshift()
1361 ePtr<iDVBDemux> demux;
1363 eDebug("Start timeshift!");
1365 if (m_timeshift_enabled)
1368 /* start recording with the data demux. */
1369 if (m_service_handler.getDataDemux(demux))
1372 demux->createTSRecorder(m_record);
1376 char templ[]=TSPATH "/timeshift.XXXXXX";
1377 m_timeshift_fd = mkstemp(templ);
1378 m_timeshift_file = templ;
1380 eDebug("recording to %s", templ);
1382 if (m_timeshift_fd < 0)
1388 m_record->setTargetFD(m_timeshift_fd);
1390 m_timeshift_enabled = 1;
1392 updateTimeshiftPids();
1398 RESULT eDVBServicePlay::stopTimeshift()
1400 if (!m_timeshift_enabled)
1405 m_timeshift_enabled = 0;
1410 close(m_timeshift_fd);
1411 eDebug("remove timeshift file");
1412 remove(m_timeshift_file.c_str());
1417 int eDVBServicePlay::isTimeshiftActive()
1419 return m_timeshift_enabled && m_timeshift_active;
1422 RESULT eDVBServicePlay::activateTimeshift()
1424 if (!m_timeshift_enabled)
1427 if (!m_timeshift_active)
1429 switchToTimeshift();
1436 PyObject *eDVBServicePlay::getCutList()
1438 PyObject *list = PyList_New(0);
1440 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1442 PyObject *tuple = PyTuple_New(2);
1443 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1444 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1445 PyList_Append(list, tuple);
1452 void eDVBServicePlay::setCutList(PyObject *list)
1454 if (!PyList_Check(list))
1456 int size = PyList_Size(list);
1459 m_cue_entries.clear();
1461 for (i=0; i<size; ++i)
1463 PyObject *tuple = PyList_GetItem(list, i);
1464 if (!PyTuple_Check(tuple))
1466 eDebug("non-tuple in cutlist");
1469 if (PyTuple_Size(tuple) != 2)
1471 eDebug("cutlist entries need to be a 2-tuple");
1474 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1475 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1477 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1480 pts_t pts = PyLong_AsLongLong(ppts);
1481 int type = PyInt_AsLong(ptype);
1482 m_cue_entries.insert(cueEntry(pts, type));
1483 eDebug("adding %08llx, %d", pts, type);
1485 m_cuesheet_changed = 1;
1487 cutlistToCuesheet();
1488 m_event((iPlayableService*)this, evCuesheetChanged);
1491 void eDVBServicePlay::setCutListEnable(int enable)
1493 m_cutlist_enabled = enable;
1494 cutlistToCuesheet();
1497 void eDVBServicePlay::updateTimeshiftPids()
1502 eDVBServicePMTHandler::program program;
1503 if (m_service_handler.getProgramInfo(program))
1507 std::set<int> pids_to_record;
1508 pids_to_record.insert(0); // PAT
1509 if (program.pmtPid != -1)
1510 pids_to_record.insert(program.pmtPid); // PMT
1512 if (program.textPid != -1)
1513 pids_to_record.insert(program.textPid); // Videotext
1515 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1516 i(program.videoStreams.begin());
1517 i != program.videoStreams.end(); ++i)
1518 pids_to_record.insert(i->pid);
1520 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1521 i(program.audioStreams.begin());
1522 i != program.audioStreams.end(); ++i)
1523 pids_to_record.insert(i->pid);
1525 std::set<int> new_pids, obsolete_pids;
1527 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1528 m_pids_active.begin(), m_pids_active.end(),
1529 std::inserter(new_pids, new_pids.begin()));
1531 std::set_difference(
1532 m_pids_active.begin(), m_pids_active.end(),
1533 pids_to_record.begin(), pids_to_record.end(),
1534 std::inserter(new_pids, new_pids.begin())
1537 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1538 m_record->addPID(*i);
1540 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1541 m_record->removePID(*i);
1545 void eDVBServicePlay::switchToLive()
1547 if (!m_timeshift_active)
1553 m_teletext_parser = 0;
1555 /* free the timeshift service handler, we need the resources */
1556 m_service_handler_timeshift.free();
1557 m_timeshift_active = 0;
1559 m_event((iPlayableService*)this, evSeekableStatusChanged);
1564 void eDVBServicePlay::switchToTimeshift()
1566 if (m_timeshift_active)
1571 m_teletext_parser = 0;
1573 m_timeshift_active = 1;
1575 m_event((iPlayableService*)this, evSeekableStatusChanged);
1577 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1578 r.path = m_timeshift_file;
1580 m_cue = new eCueSheet();
1581 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1582 updateDecoder(); /* mainly to switch off PCR */
1585 void eDVBServicePlay::updateDecoder()
1587 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1;
1588 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1590 bool defaultac3=false;
1591 std::string default_ac3;
1593 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1594 defaultac3 = default_ac3 == "enable";
1596 eDVBServicePMTHandler::program program;
1597 if (h.getProgramInfo(program))
1598 eDebug("getting program info failed.");
1601 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1602 if (!program.videoStreams.empty())
1604 eDebugNoNewLine(" (");
1605 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1606 i(program.videoStreams.begin());
1607 i != program.videoStreams.end(); ++i)
1614 if (i != program.videoStreams.begin())
1615 eDebugNoNewLine(", ");
1616 eDebugNoNewLine("%04x", i->pid);
1618 eDebugNoNewLine(")");
1620 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1621 if (!program.audioStreams.empty())
1623 eDebugNoNewLine(" (");
1624 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1625 i(program.audioStreams.begin());
1626 i != program.audioStreams.end(); ++i)
1628 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1630 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1636 if (i != program.audioStreams.begin())
1637 eDebugNoNewLine(", ");
1638 eDebugNoNewLine("%04x", i->pid);
1640 eDebugNoNewLine(")");
1642 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1643 pcrpid = program.pcrPid;
1644 eDebug(", and the text pid is %04x", program.textPid);
1645 tpid = program.textPid;
1646 achannel = program.audioChannel;
1651 h.getDecodeDemux(m_decode_demux);
1653 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1655 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1656 #ifdef INTERNAL_TELETEXT
1657 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1663 m_decoder->setVideoPID(vpid, vpidtype);
1664 m_current_audio_stream = 0;
1665 m_decoder->setAudioPID(apid, apidtype);
1666 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1667 m_decoder->setSyncPCR(pcrpid);
1669 m_decoder->setSyncPCR(-1);
1670 #ifndef INTERNAL_TELETEXT
1671 m_decoder->setTextPID(tpid);
1673 if (m_teletext_parser)
1674 m_teletext_parser->start(tpid);
1678 m_decoder->setTrickmode(1);
1682 m_decoder->setAudioChannel(achannel);
1684 // how we can do this better?
1685 // update cache pid when the user changed the audio track or video track
1686 // TODO handling of difference audio types.. default audio types..
1688 /* don't worry about non-existing services, nor pvr services */
1689 if (m_dvb_service && !m_is_pvr)
1691 if (apidtype == eDVBAudio::aMPEG)
1693 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1694 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1698 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1699 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1701 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1702 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1703 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1704 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1709 void eDVBServicePlay::loadCuesheet()
1711 std::string filename = m_reference.path + ".cuts";
1713 m_cue_entries.clear();
1715 FILE *f = fopen(filename.c_str(), "rb");
1719 eDebug("loading cuts..");
1722 unsigned long long where;
1725 if (!fread(&where, sizeof(where), 1, f))
1727 if (!fread(&what, sizeof(what), 1, f))
1730 #if BYTE_ORDER == LITTLE_ENDIAN
1731 where = bswap_64(where);
1738 m_cue_entries.insert(cueEntry(where, what));
1741 eDebug("%d entries", m_cue_entries.size());
1743 eDebug("cutfile not found!");
1745 m_cuesheet_changed = 0;
1746 cutlistToCuesheet();
1747 m_event((iPlayableService*)this, evCuesheetChanged);
1750 void eDVBServicePlay::saveCuesheet()
1752 std::string filename = m_reference.path + ".cuts";
1754 FILE *f = fopen(filename.c_str(), "wb");
1758 unsigned long long where;
1761 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1763 #if BYTE_ORDER == BIG_ENDIAN
1766 where = bswap_64(i->where);
1768 what = htonl(i->what);
1769 fwrite(&where, sizeof(where), 1, f);
1770 fwrite(&what, sizeof(what), 1, f);
1776 m_cuesheet_changed = 0;
1779 void eDVBServicePlay::cutlistToCuesheet()
1783 eDebug("no cue sheet");
1788 if (!m_cutlist_enabled)
1790 m_cue->commitSpans();
1791 eDebug("cutlists where disabled");
1795 pts_t in = 0, out = 0, length = 0;
1799 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1803 if (i == m_cue_entries.end())
1806 if (i->what == 0) /* in */
1810 } else if (i->what == 1) /* out */
1820 m_cue->addSourceSpan(in, out);
1824 if (i == m_cue_entries.end())
1827 m_cue->commitSpans();
1830 DEFINE_REF(eDVBServicePlay)
1832 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");