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::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 eDVBServicePlay::getFrontendInfo(int w)
1286 eUsePtr<iDVBChannel> channel;
1287 if(m_service_handler.getChannel(channel))
1289 ePtr<iDVBFrontend> fe;
1290 if(channel->getFrontend(fe))
1292 return fe->readFrontendData(w);
1295 PyObject *eDVBServicePlay::getFrontendData(bool original)
1299 eUsePtr<iDVBChannel> channel;
1300 if(!m_service_handler.getChannel(channel))
1302 ePtr<iDVBFrontend> fe;
1303 if(!channel->getFrontend(fe))
1305 ret = fe->readTransponderData(original);
1308 ePtr<iDVBFrontendParameters> feparm;
1309 channel->getCurrentFrontendParameters(feparm);
1312 eDVBFrontendParametersSatellite osat;
1313 if (!feparm->getDVBS(osat))
1315 void PutToDict(PyObject *, const char*, long);
1316 void PutToDict(PyObject *, const char*, const char*);
1317 PutToDict(ret, "orbital_position", osat.orbital_position);
1318 const char *tmp = "UNKNOWN";
1319 switch(osat.polarisation)
1321 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1322 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1323 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1324 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1327 PutToDict(ret, "polarization", tmp);
1341 int eDVBServicePlay::getNumberOfSubservices()
1343 ePtr<eServiceEvent> evt;
1344 if (!m_event_handler.getEvent(evt, 0))
1345 return evt->getNumOfLinkageServices();
1349 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1351 ePtr<eServiceEvent> evt;
1352 if (!m_event_handler.getEvent(evt, 0))
1354 if (!evt->getLinkageService(sub, m_reference, n))
1357 sub.type=eServiceReference::idInvalid;
1361 RESULT eDVBServicePlay::startTimeshift()
1363 ePtr<iDVBDemux> demux;
1365 eDebug("Start timeshift!");
1367 if (m_timeshift_enabled)
1370 /* start recording with the data demux. */
1371 if (m_service_handler.getDataDemux(demux))
1374 demux->createTSRecorder(m_record);
1378 char templ[]=TSPATH "/timeshift.XXXXXX";
1379 m_timeshift_fd = mkstemp(templ);
1380 m_timeshift_file = templ;
1382 eDebug("recording to %s", templ);
1384 if (m_timeshift_fd < 0)
1390 m_record->setTargetFD(m_timeshift_fd);
1392 m_timeshift_enabled = 1;
1394 updateTimeshiftPids();
1400 RESULT eDVBServicePlay::stopTimeshift()
1402 if (!m_timeshift_enabled)
1407 m_timeshift_enabled = 0;
1412 close(m_timeshift_fd);
1413 eDebug("remove timeshift file");
1414 remove(m_timeshift_file.c_str());
1419 int eDVBServicePlay::isTimeshiftActive()
1421 return m_timeshift_enabled && m_timeshift_active;
1424 RESULT eDVBServicePlay::activateTimeshift()
1426 if (!m_timeshift_enabled)
1429 if (!m_timeshift_active)
1431 switchToTimeshift();
1438 PyObject *eDVBServicePlay::getCutList()
1440 PyObject *list = PyList_New(0);
1442 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1444 PyObject *tuple = PyTuple_New(2);
1445 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1446 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1447 PyList_Append(list, tuple);
1454 void eDVBServicePlay::setCutList(PyObject *list)
1456 if (!PyList_Check(list))
1458 int size = PyList_Size(list);
1461 m_cue_entries.clear();
1463 for (i=0; i<size; ++i)
1465 PyObject *tuple = PyList_GetItem(list, i);
1466 if (!PyTuple_Check(tuple))
1468 eDebug("non-tuple in cutlist");
1471 if (PyTuple_Size(tuple) != 2)
1473 eDebug("cutlist entries need to be a 2-tuple");
1476 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1477 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1479 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1482 pts_t pts = PyLong_AsLongLong(ppts);
1483 int type = PyInt_AsLong(ptype);
1484 m_cue_entries.insert(cueEntry(pts, type));
1485 eDebug("adding %08llx, %d", pts, type);
1487 m_cuesheet_changed = 1;
1489 cutlistToCuesheet();
1490 m_event((iPlayableService*)this, evCuesheetChanged);
1493 void eDVBServicePlay::setCutListEnable(int enable)
1495 m_cutlist_enabled = enable;
1496 cutlistToCuesheet();
1499 void eDVBServicePlay::updateTimeshiftPids()
1504 eDVBServicePMTHandler::program program;
1505 if (m_service_handler.getProgramInfo(program))
1509 std::set<int> pids_to_record;
1510 pids_to_record.insert(0); // PAT
1511 if (program.pmtPid != -1)
1512 pids_to_record.insert(program.pmtPid); // PMT
1514 if (program.textPid != -1)
1515 pids_to_record.insert(program.textPid); // Videotext
1517 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1518 i(program.videoStreams.begin());
1519 i != program.videoStreams.end(); ++i)
1520 pids_to_record.insert(i->pid);
1522 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1523 i(program.audioStreams.begin());
1524 i != program.audioStreams.end(); ++i)
1525 pids_to_record.insert(i->pid);
1527 std::set<int> new_pids, obsolete_pids;
1529 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1530 m_pids_active.begin(), m_pids_active.end(),
1531 std::inserter(new_pids, new_pids.begin()));
1533 std::set_difference(
1534 m_pids_active.begin(), m_pids_active.end(),
1535 pids_to_record.begin(), pids_to_record.end(),
1536 std::inserter(new_pids, new_pids.begin())
1539 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1540 m_record->addPID(*i);
1542 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1543 m_record->removePID(*i);
1547 void eDVBServicePlay::switchToLive()
1549 if (!m_timeshift_active)
1555 m_teletext_parser = 0;
1557 /* free the timeshift service handler, we need the resources */
1558 m_service_handler_timeshift.free();
1559 m_timeshift_active = 0;
1561 m_event((iPlayableService*)this, evSeekableStatusChanged);
1566 void eDVBServicePlay::switchToTimeshift()
1568 if (m_timeshift_active)
1573 m_teletext_parser = 0;
1575 m_timeshift_active = 1;
1577 m_event((iPlayableService*)this, evSeekableStatusChanged);
1579 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1580 r.path = m_timeshift_file;
1582 m_cue = new eCueSheet();
1583 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1584 updateDecoder(); /* mainly to switch off PCR */
1587 void eDVBServicePlay::updateDecoder()
1589 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1;
1590 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1592 bool defaultac3=false;
1593 std::string default_ac3;
1595 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1596 defaultac3 = default_ac3 == "enable";
1598 eDVBServicePMTHandler::program program;
1599 if (h.getProgramInfo(program))
1600 eDebug("getting program info failed.");
1603 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1604 if (!program.videoStreams.empty())
1606 eDebugNoNewLine(" (");
1607 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1608 i(program.videoStreams.begin());
1609 i != program.videoStreams.end(); ++i)
1616 if (i != program.videoStreams.begin())
1617 eDebugNoNewLine(", ");
1618 eDebugNoNewLine("%04x", i->pid);
1620 eDebugNoNewLine(")");
1622 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1623 if (!program.audioStreams.empty())
1625 eDebugNoNewLine(" (");
1626 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1627 i(program.audioStreams.begin());
1628 i != program.audioStreams.end(); ++i)
1630 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1632 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1638 if (i != program.audioStreams.begin())
1639 eDebugNoNewLine(", ");
1640 eDebugNoNewLine("%04x", i->pid);
1642 eDebugNoNewLine(")");
1644 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1645 pcrpid = program.pcrPid;
1646 eDebug(", and the text pid is %04x", program.textPid);
1647 tpid = program.textPid;
1648 achannel = program.audioChannel;
1653 h.getDecodeDemux(m_decode_demux);
1655 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1657 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1658 #ifdef INTERNAL_TELETEXT
1659 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1665 m_decoder->setVideoPID(vpid, vpidtype);
1666 m_current_audio_stream = 0;
1667 m_decoder->setAudioPID(apid, apidtype);
1668 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1669 m_decoder->setSyncPCR(pcrpid);
1671 m_decoder->setSyncPCR(-1);
1672 #ifndef INTERNAL_TELETEXT
1673 m_decoder->setTextPID(tpid);
1675 if (m_teletext_parser)
1676 m_teletext_parser->start(tpid);
1680 m_decoder->setTrickmode(1);
1684 m_decoder->setAudioChannel(achannel);
1686 // how we can do this better?
1687 // update cache pid when the user changed the audio track or video track
1688 // TODO handling of difference audio types.. default audio types..
1690 /* don't worry about non-existing services, nor pvr services */
1691 if (m_dvb_service && !m_is_pvr)
1693 if (apidtype == eDVBAudio::aMPEG)
1695 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1696 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1700 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1701 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1703 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1704 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1705 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1706 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1711 void eDVBServicePlay::loadCuesheet()
1713 std::string filename = m_reference.path + ".cuts";
1715 m_cue_entries.clear();
1717 FILE *f = fopen(filename.c_str(), "rb");
1721 eDebug("loading cuts..");
1724 unsigned long long where;
1727 if (!fread(&where, sizeof(where), 1, f))
1729 if (!fread(&what, sizeof(what), 1, f))
1732 #if BYTE_ORDER == LITTLE_ENDIAN
1733 where = bswap_64(where);
1740 m_cue_entries.insert(cueEntry(where, what));
1743 eDebug("%d entries", m_cue_entries.size());
1745 eDebug("cutfile not found!");
1747 m_cuesheet_changed = 0;
1748 cutlistToCuesheet();
1749 m_event((iPlayableService*)this, evCuesheetChanged);
1752 void eDVBServicePlay::saveCuesheet()
1754 std::string filename = m_reference.path + ".cuts";
1756 FILE *f = fopen(filename.c_str(), "wb");
1760 unsigned long long where;
1763 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1765 #if BYTE_ORDER == BIG_ENDIAN
1768 where = bswap_64(i->where);
1770 what = htonl(i->what);
1771 fwrite(&where, sizeof(where), 1, f);
1772 fwrite(&what, sizeof(what), 1, f);
1778 m_cuesheet_changed = 0;
1781 void eDVBServicePlay::cutlistToCuesheet()
1785 eDebug("no cue sheet");
1790 if (!m_cutlist_enabled)
1792 m_cue->commitSpans();
1793 eDebug("cutlists where disabled");
1797 pts_t in = 0, out = 0, length = 0;
1801 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1805 if (i == m_cue_entries.end())
1808 if (i->what == 0) /* in */
1812 } else if (i->what == 1) /* out */
1822 m_cue->addSourceSpan(in, out);
1826 if (i == m_cue_entries.end())
1829 m_cue->commitSpans();
1832 DEFINE_REF(eDVBServicePlay)
1834 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");