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>
21 #include <lib/gui/esubtitle.h>
26 #include <netinet/in.h>
28 #include <dvbsi++/event_information_section.h>
30 #define INTERNAL_TELETEXT
33 #error no byte order defined!
36 #define TSPATH "/media/hdd"
38 class eStaticServiceDVBInformation: public iStaticServiceInformation
40 DECLARE_REF(eStaticServiceDVBInformation);
42 RESULT getName(const eServiceReference &ref, std::string &name);
43 int getLength(const eServiceReference &ref);
46 DEFINE_REF(eStaticServiceDVBInformation);
48 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
50 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
51 if ( !ref.name.empty() )
53 if (service.getParentTransportStreamID().get()) // linkage subservice
55 ePtr<iServiceHandler> service_center;
56 if (!eServiceCenter::getInstance(service_center))
58 eServiceReferenceDVB parent = service;
59 parent.setTransportStreamID( service.getParentTransportStreamID() );
60 parent.setServiceID( service.getParentServiceID() );
61 parent.setParentTransportStreamID(eTransportStreamID(0));
62 parent.setParentServiceID(eServiceID(0));
64 ePtr<iStaticServiceInformation> service_info;
65 if (!service_center->info(parent, service_info))
67 if (!service_info->getName(parent, name))
69 // just show short name
70 unsigned int pos = name.find("\xc2\x86");
71 if ( pos != std::string::npos )
73 pos = name.find("\xc2\x87");
74 if ( pos != std::string::npos )
90 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
95 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
97 DECLARE_REF(eStaticServiceDVBBouquetInformation);
99 RESULT getName(const eServiceReference &ref, std::string &name);
100 int getLength(const eServiceReference &ref);
103 DEFINE_REF(eStaticServiceDVBBouquetInformation);
105 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
107 ePtr<iDVBChannelList> db;
108 ePtr<eDVBResourceManager> res;
111 if ((err = eDVBResourceManager::getInstance(res)) != 0)
113 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
116 if ((err = res->getChannelList(db)) != 0)
118 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
123 if ((err = db->getBouquet(ref, bouquet)) != 0)
125 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
129 if ( bouquet && bouquet->m_bouquet_name.length() )
131 name = bouquet->m_bouquet_name;
138 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
143 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
145 DECLARE_REF(eStaticServiceDVBPVRInformation);
146 eServiceReference m_ref;
147 eDVBMetaParser m_parser;
149 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
150 RESULT getName(const eServiceReference &ref, std::string &name);
151 int getLength(const eServiceReference &ref);
153 int getInfo(const eServiceReference &ref, int w);
154 std::string getInfoString(const eServiceReference &ref,int w);
157 DEFINE_REF(eStaticServiceDVBPVRInformation);
159 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
162 m_parser.parseFile(ref.path);
165 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
167 ASSERT(ref == m_ref);
168 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
172 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
174 ASSERT(ref == m_ref);
178 if (tstools.openFile(ref.path.c_str()))
182 if (tstools.calcLen(len))
188 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
192 case iServiceInformation::sDescription:
193 return iServiceInformation::resIsString;
194 case iServiceInformation::sServiceref:
195 return iServiceInformation::resIsString;
196 case iServiceInformation::sTimeCreate:
197 if (m_parser.m_time_create)
198 return m_parser.m_time_create;
200 return iServiceInformation::resNA;
202 return iServiceInformation::resNA;
206 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
210 case iServiceInformation::sDescription:
211 return m_parser.m_description;
212 case iServiceInformation::sServiceref:
213 return m_parser.m_ref.toString();
219 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
221 DECLARE_REF(eDVBPVRServiceOfflineOperations);
222 eServiceReferenceDVB m_ref;
224 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
226 RESULT deleteFromDisk(int simulate);
227 RESULT getListOfFilenames(std::list<std::string> &);
230 DEFINE_REF(eDVBPVRServiceOfflineOperations);
232 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
236 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
242 std::list<std::string> res;
243 if (getListOfFilenames(res))
246 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
248 eDebug("FATAL !! can't get background file eraser");
250 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
252 eDebug("Removing %s...", i->c_str());
254 eraser->erase(i->c_str());
256 ::unlink(i->c_str());
263 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
266 res.push_back(m_ref.path);
268 // handling for old splitted recordings (enigma 1)
273 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
275 if (stat(buf, &s) < 0)
280 res.push_back(m_ref.path + ".meta");
281 res.push_back(m_ref.path + ".ap");
282 res.push_back(m_ref.path + ".cuts");
283 std::string tmp = m_ref.path;
284 tmp.erase(m_ref.path.length()-3);
285 res.push_back(tmp + ".eit");
289 DEFINE_REF(eServiceFactoryDVB)
291 eServiceFactoryDVB::eServiceFactoryDVB()
293 ePtr<eServiceCenter> sc;
295 eServiceCenter::getPrivInstance(sc);
297 sc->addServiceFactory(eServiceFactoryDVB::id, this);
300 eServiceFactoryDVB::~eServiceFactoryDVB()
302 ePtr<eServiceCenter> sc;
304 eServiceCenter::getPrivInstance(sc);
306 sc->removeServiceFactory(eServiceFactoryDVB::id);
309 DEFINE_REF(eDVBServiceList);
311 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
315 eDVBServiceList::~eDVBServiceList()
319 RESULT eDVBServiceList::startQuery()
321 ePtr<iDVBChannelList> db;
322 ePtr<eDVBResourceManager> res;
325 if ((err = eDVBResourceManager::getInstance(res)) != 0)
327 eDebug("no resource manager");
330 if ((err = res->getChannelList(db)) != 0)
332 eDebug("no channel list");
336 ePtr<eDVBChannelQuery> q;
338 if (!m_parent.path.empty())
340 eDVBChannelQuery::compile(q, m_parent.path);
343 eDebug("compile query failed");
348 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
350 eDebug("startQuery failed");
357 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
359 eServiceReferenceDVB ref;
364 while (!m_query->getNextResult(ref))
368 list.sort(iListableServiceCompare(this));
373 // The first argument of this function is a format string to specify the order and
374 // the content of the returned list
375 // useable format options are
376 // R = Service Reference (as swig object .. this is very slow)
377 // S = Service Reference (as python string object .. same as ref.toString())
378 // N = Service Name (as python string object)
379 // when exactly one return value per service is selected in the format string,
380 // then each value is directly a list entry
381 // when more than one value is returned per service, then the list is a list of
383 // unknown format string chars are returned as python None values !
384 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
387 std::list<eServiceReference> tmplist;
390 if (!format || !(retcount=strlen(format)))
391 format = "R"; // just return service reference swig object ...
393 if (!getContent(tmplist, sorted))
395 int services=tmplist.size();
396 ePtr<iStaticServiceInformation> sptr;
397 eServiceCenterPtr service_center;
399 if (strchr(format, 'N'))
400 eServiceCenter::getPrivInstance(service_center);
402 ret = PyList_New(services);
403 std::list<eServiceReference>::iterator it(tmplist.begin());
405 for (int cnt=0; cnt < services; ++cnt)
407 eServiceReference &ref=*it++;
408 PyObject *tuple = retcount > 1 ? PyTuple_New(retcount) : 0;
409 for (int i=0; i < retcount; ++i)
414 case 'R': // service reference (swig)object
415 tmp = New_eServiceReference(ref);
417 case 'S': // service reference string
418 tmp = PyString_FromString(ref.toString().c_str());
420 case 'N': // service name
423 service_center->info(ref, sptr);
427 sptr->getName(ref, name);
429 tmp = PyString_FromString(name.c_str());
433 tmp = PyString_FromString("<n/a>");
446 PyTuple_SET_ITEM(tuple, i, tmp);
448 PyList_SET_ITEM(ret, cnt, tmp);
452 PyList_SET_ITEM(ret, cnt, tuple);
455 return ret ? ret : PyList_New(0);
458 RESULT eDVBServiceList::getNext(eServiceReference &ref)
463 return m_query->getNextResult((eServiceReferenceDVB&)ref);
466 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
468 return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
471 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
473 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
475 ePtr<iDVBChannelList> db;
476 ePtr<eDVBResourceManager> resm;
478 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
481 if (db->getBouquet(m_parent, m_bouquet) != 0)
492 RESULT eDVBServiceList::addService(eServiceReference &ref)
496 return m_bouquet->addService(ref);
499 RESULT eDVBServiceList::removeService(eServiceReference &ref)
503 return m_bouquet->removeService(ref);
506 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
510 return m_bouquet->moveService(ref, pos);
513 RESULT eDVBServiceList::flushChanges()
517 return m_bouquet->flushChanges();
520 RESULT eDVBServiceList::setListName(const std::string &name)
524 return m_bouquet->setListName(name);
527 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
529 ePtr<eDVBService> service;
530 int r = lookupService(service, ref);
533 // check resources...
534 ptr = new eDVBServicePlay(ref, service);
538 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
540 if (ref.path.empty())
542 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
551 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
553 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
554 if (list->startQuery())
564 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
566 /* is a listable service? */
567 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
569 if ( !ref.name.empty() ) // satellites or providers list
570 ptr = new eStaticServiceDVBInformation;
571 else // a dvb bouquet
572 ptr = new eStaticServiceDVBBouquetInformation;
574 else if (!ref.path.empty()) /* do we have a PVR service? */
575 ptr = new eStaticServiceDVBPVRInformation(ref);
576 else // normal dvb service
578 ePtr<eDVBService> service;
579 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
580 ptr = new eStaticServiceDVBInformation;
582 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
588 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
590 if (ref.path.empty())
596 ptr = new eDVBPVRServiceOfflineOperations(ref);
601 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
603 // TODO: handle the listing itself
604 // if (ref.... == -1) .. return "... bouquets ...";
605 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
607 ePtr<iDVBChannelList> db;
608 ePtr<eDVBResourceManager> res;
611 if ((err = eDVBResourceManager::getInstance(res)) != 0)
613 eDebug("no resource manager");
616 if ((err = res->getChannelList(db)) != 0)
618 eDebug("no channel list");
622 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
623 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
625 eDebug("getService failed!");
632 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
633 m_reference(ref), m_dvb_service(service), m_is_paused(0), m_current_audio_channel(-1)
636 m_is_pvr = !m_reference.path.empty();
638 m_timeshift_enabled = m_timeshift_active = 0;
641 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
642 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
643 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
645 m_cuesheet_changed = 0;
646 m_cutlist_enabled = 1;
648 m_subtitle_widget = 0;
650 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
653 eDVBServicePlay::~eDVBServicePlay()
655 delete m_subtitle_widget;
658 void eDVBServicePlay::gotNewEvent()
662 ePtr<eServiceEvent> m_event_now, m_event_next;
663 getEvent(m_event_now, 0);
664 getEvent(m_event_next, 1);
667 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
669 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
671 m_event((iPlayableService*)this, evUpdatedEventInfo);
674 void eDVBServicePlay::serviceEvent(int event)
678 case eDVBServicePMTHandler::eventTuned:
680 ePtr<iDVBDemux> m_demux;
681 if (!m_service_handler.getDataDemux(m_demux))
683 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
684 int sid = ref.getParentServiceID().get();
686 sid = ref.getServiceID().get();
687 if ( ref.getParentTransportStreamID().get() &&
688 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
689 m_event_handler.startOther(m_demux, sid);
691 m_event_handler.start(m_demux, sid);
695 case eDVBServicePMTHandler::eventTuneFailed:
697 eDebug("DVB service failed to tune");
698 m_event((iPlayableService*)this, evTuneFailed);
701 case eDVBServicePMTHandler::eventNewProgramInfo:
703 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
704 if (m_timeshift_enabled)
705 updateTimeshiftPids();
706 if (!m_timeshift_active)
708 if (m_first_program_info && m_is_pvr)
710 m_first_program_info = 0;
713 m_event((iPlayableService*)this, evUpdatedInfo);
716 case eDVBServicePMTHandler::eventEOF:
717 m_event((iPlayableService*)this, evEOF);
719 case eDVBServicePMTHandler::eventSOF:
720 m_event((iPlayableService*)this, evSOF);
725 void eDVBServicePlay::serviceEventTimeshift(int event)
729 case eDVBServicePMTHandler::eventNewProgramInfo:
730 if (m_timeshift_active)
733 case eDVBServicePMTHandler::eventSOF:
734 m_event((iPlayableService*)this, evSOF);
736 case eDVBServicePMTHandler::eventEOF:
742 RESULT eDVBServicePlay::start()
745 /* in pvr mode, we only want to use one demux. in tv mode, we're using
746 two (one for decoding, one for data source), as we must be prepared
747 to start recording from the data demux. */
749 m_cue = new eCueSheet();
751 m_first_program_info = 1;
752 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
753 r = m_service_handler.tune(service, m_is_pvr, m_cue);
755 /* inject EIT if there is a stored one */
758 std::string filename = service.path;
759 filename.erase(filename.length()-2, 2);
761 int fd = ::open( filename.c_str(), O_RDONLY );
765 int rd = ::read(fd, buf, 4096);
767 if ( rd > 12 /*EIT_LOOP_SIZE*/ )
770 ePtr<eServiceEvent> event = new eServiceEvent;
771 ePtr<eServiceEvent> empty;
772 event->parseFrom(&ev, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get());
773 m_event_handler.inject(event, 0);
774 m_event_handler.inject(empty, 1);
783 m_event(this, evStart);
784 m_event((iPlayableService*)this, evSeekableStatusChanged);
788 RESULT eDVBServicePlay::stop()
790 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
792 m_service_handler_timeshift.free();
793 m_service_handler.free();
795 if (m_is_pvr && m_cuesheet_changed)
801 RESULT eDVBServicePlay::setTarget(int target)
803 m_is_primary = !target;
807 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
809 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
813 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
815 /* note: we check for timeshift to be enabled,
816 not neccessary active. if you pause when timeshift
817 is not active, you should activate it when unpausing */
818 if ((!m_is_pvr) && (!m_timeshift_enabled))
828 RESULT eDVBServicePlay::setSlowMotion(int ratio)
831 return m_decoder->setSlowMotion(ratio);
836 RESULT eDVBServicePlay::setFastForward(int ratio)
838 int skipmode, ffratio;
844 } else if (ratio > 0)
852 } else // if (ratio < 0)
858 if (m_skipmode != skipmode)
860 eDebug("setting cue skipmode to %d", skipmode);
862 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
865 m_skipmode = skipmode;
870 return m_decoder->setFastForward(ffratio);
873 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
875 if (m_is_pvr || m_timeshift_enabled)
885 /* TODO: when timeshift is enabled but not active, this doesn't work. */
886 RESULT eDVBServicePlay::getLength(pts_t &len)
888 ePtr<iDVBPVRChannel> pvr_channel;
890 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
893 return pvr_channel->getLength(len);
896 RESULT eDVBServicePlay::pause()
898 if (!m_is_paused && m_decoder)
901 return m_decoder->freeze(0);
906 RESULT eDVBServicePlay::unpause()
908 if (m_is_paused && m_decoder)
911 return m_decoder->unfreeze();
916 RESULT eDVBServicePlay::seekTo(pts_t to)
918 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
923 ePtr<iDVBPVRChannel> pvr_channel;
925 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
931 m_cue->seekTo(0, to);
935 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
937 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
942 ePtr<iDVBPVRChannel> pvr_channel;
944 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
949 /* HACK until we have skip-AP api */
950 if ((to > 0) && (to < 100))
958 m_cue->seekTo(mode, to);
962 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
964 ePtr<iDVBPVRChannel> pvr_channel;
969 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
974 /* if there is a decoder, use audio or video PTS */
977 r = m_decoder->getPTS(0, pos);
983 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
986 RESULT eDVBServicePlay::setTrickmode(int trick)
989 m_decoder->setTrickmode(trick);
993 RESULT eDVBServicePlay::isCurrentlySeekable()
995 return m_is_pvr || m_timeshift_active;
998 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1004 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1010 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1016 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1022 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1028 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1031 if (m_timeshift_enabled || !m_is_pvr)
1033 if (!m_timeshift_enabled)
1035 /* we need enough diskspace */
1037 if (statfs(TSPATH "/.", &fs) < 0)
1039 eDebug("statfs failed!");
1043 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1045 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1055 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1066 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1072 RESULT eDVBServicePlay::getName(std::string &name)
1076 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1077 return i->getName(m_reference, name);
1081 m_dvb_service->getName(m_reference, name);
1085 else if (!m_reference.name.empty())
1086 eStaticServiceDVBInformation().getName(m_reference, name);
1088 name = "DVB service";
1092 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1094 return m_event_handler.getEvent(evt, nownext);
1097 int eDVBServicePlay::getInfo(int w)
1099 eDVBServicePMTHandler::program program;
1102 return resIsPyObject;
1104 if (m_service_handler.getProgramInfo(program))
1110 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1112 ePtr<eServiceEvent> evt;
1113 if (!m_event_handler.getEvent(evt, 0))
1115 ePtr<eComponentData> data;
1116 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1118 if ( data->getStreamContent() == 1 )
1120 switch(data->getComponentType())
1123 case 1: // 4:3 SD PAL
1125 case 3: // 16:9 SD PAL
1126 case 4: // > 16:9 PAL
1127 case 5: // 4:3 SD NTSC
1129 case 7: // 16:9 SD NTSC
1130 case 8: // > 16:9 NTSC
1133 case 9: // 4:3 HD PAL
1135 case 0xB: // 16:9 HD PAL
1136 case 0xC: // > 16:9 HD PAL
1137 case 0xD: // 4:3 HD NTSC
1139 case 0xF: // 16:9 HD NTSC
1140 case 0x10: // > 16:9 HD PAL
1141 return data->getComponentType();
1148 case sIsCrypted: return program.isCrypted();
1149 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1150 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1151 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
1152 case sPCRPID: return program.pcrPid;
1153 case sPMTPID: return program.pmtPid;
1154 case sTXTPID: return program.textPid;
1155 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1156 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1157 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1158 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1159 case sProvider: if (!m_dvb_service) return -1; return -2;
1165 std::string eDVBServicePlay::getInfoString(int w)
1170 if (!m_dvb_service) return "";
1171 return m_dvb_service->m_provider_name;
1175 return iServiceInformation::getInfoString(w);
1178 PyObject *eDVBServicePlay::getInfoObject(int w)
1183 return m_service_handler.getCaIds();
1187 return iServiceInformation::getInfoObject(w);
1190 int eDVBServicePlay::getNumberOfTracks()
1192 eDVBServicePMTHandler::program program;
1193 if (m_service_handler.getProgramInfo(program))
1195 return program.audioStreams.size();
1198 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1200 int ret = selectAudioStream(i);
1202 if (m_decoder->start())
1208 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1210 eDVBServicePMTHandler::program program;
1212 if (m_service_handler.getProgramInfo(program))
1215 if (i >= program.audioStreams.size())
1218 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1219 info.m_description = "MPEG";
1220 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1221 info.m_description = "AC3";
1222 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1223 info.m_description = "AAC";
1224 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1225 info.m_description = "DTS";
1227 info.m_description = "???";
1229 if (program.audioStreams[i].component_tag != -1)
1231 ePtr<eServiceEvent> evt;
1232 if (!m_event_handler.getEvent(evt, 0))
1234 ePtr<eComponentData> data;
1235 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1236 info.m_language = data->getText();
1240 if (info.m_language.empty())
1241 info.m_language = program.audioStreams[i].language_code;
1246 int eDVBServicePlay::selectAudioStream(int i)
1248 eDVBServicePMTHandler::program program;
1250 if (m_service_handler.getProgramInfo(program))
1253 if ((unsigned int)i >= program.audioStreams.size())
1259 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1262 if (m_dvb_service && !m_is_pvr)
1264 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1266 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1267 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1270 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1271 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1275 m_current_audio_stream = i;
1280 int eDVBServicePlay::getCurrentChannel()
1282 return m_current_audio_channel == -1 ? STEREO : m_current_audio_channel;
1285 RESULT eDVBServicePlay::selectChannel(int i)
1287 if (i < iAudioChannelSelection::LEFT || i > iAudioChannelSelection::RIGHT)
1289 if (m_current_audio_channel != i)
1292 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1293 m_current_audio_channel=i;
1295 m_decoder->setAudioChannel(i);
1300 int eDVBServiceBase::getFrontendInfo(int w)
1302 eUsePtr<iDVBChannel> channel;
1303 if(m_service_handler.getChannel(channel))
1305 ePtr<iDVBFrontend> fe;
1306 if(channel->getFrontend(fe))
1308 return fe->readFrontendData(w);
1311 PyObject *eDVBServiceBase::getFrontendData(bool original)
1315 eUsePtr<iDVBChannel> channel;
1316 if(!m_service_handler.getChannel(channel))
1318 ePtr<iDVBFrontend> fe;
1319 if(!channel->getFrontend(fe))
1321 ret = fe->readTransponderData(original);
1324 ePtr<iDVBFrontendParameters> feparm;
1325 channel->getCurrentFrontendParameters(feparm);
1328 eDVBFrontendParametersSatellite osat;
1329 if (!feparm->getDVBS(osat))
1331 void PutToDict(PyObject *, const char*, long);
1332 void PutToDict(PyObject *, const char*, const char*);
1333 PutToDict(ret, "orbital_position", osat.orbital_position);
1334 const char *tmp = "UNKNOWN";
1335 switch(osat.polarisation)
1337 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1338 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1339 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1340 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1343 PutToDict(ret, "polarization", tmp);
1357 int eDVBServicePlay::getNumberOfSubservices()
1359 ePtr<eServiceEvent> evt;
1360 if (!m_event_handler.getEvent(evt, 0))
1361 return evt->getNumOfLinkageServices();
1365 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1367 ePtr<eServiceEvent> evt;
1368 if (!m_event_handler.getEvent(evt, 0))
1370 if (!evt->getLinkageService(sub, m_reference, n))
1373 sub.type=eServiceReference::idInvalid;
1377 RESULT eDVBServicePlay::startTimeshift()
1379 ePtr<iDVBDemux> demux;
1381 eDebug("Start timeshift!");
1383 if (m_timeshift_enabled)
1386 /* start recording with the data demux. */
1387 if (m_service_handler.getDataDemux(demux))
1390 demux->createTSRecorder(m_record);
1394 char templ[]=TSPATH "/timeshift.XXXXXX";
1395 m_timeshift_fd = mkstemp(templ);
1396 m_timeshift_file = templ;
1398 eDebug("recording to %s", templ);
1400 if (m_timeshift_fd < 0)
1406 m_record->setTargetFD(m_timeshift_fd);
1408 m_timeshift_enabled = 1;
1410 updateTimeshiftPids();
1416 RESULT eDVBServicePlay::stopTimeshift()
1418 if (!m_timeshift_enabled)
1423 m_timeshift_enabled = 0;
1428 close(m_timeshift_fd);
1429 eDebug("remove timeshift file");
1430 remove(m_timeshift_file.c_str());
1435 int eDVBServicePlay::isTimeshiftActive()
1437 return m_timeshift_enabled && m_timeshift_active;
1440 RESULT eDVBServicePlay::activateTimeshift()
1442 if (!m_timeshift_enabled)
1445 if (!m_timeshift_active)
1447 switchToTimeshift();
1454 PyObject *eDVBServicePlay::getCutList()
1456 PyObject *list = PyList_New(0);
1458 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1460 PyObject *tuple = PyTuple_New(2);
1461 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1462 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1463 PyList_Append(list, tuple);
1470 void eDVBServicePlay::setCutList(PyObject *list)
1472 if (!PyList_Check(list))
1474 int size = PyList_Size(list);
1477 m_cue_entries.clear();
1479 for (i=0; i<size; ++i)
1481 PyObject *tuple = PyList_GetItem(list, i);
1482 if (!PyTuple_Check(tuple))
1484 eDebug("non-tuple in cutlist");
1487 if (PyTuple_Size(tuple) != 2)
1489 eDebug("cutlist entries need to be a 2-tuple");
1492 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1493 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1495 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1498 pts_t pts = PyLong_AsLongLong(ppts);
1499 int type = PyInt_AsLong(ptype);
1500 m_cue_entries.insert(cueEntry(pts, type));
1501 eDebug("adding %08llx, %d", pts, type);
1503 m_cuesheet_changed = 1;
1505 cutlistToCuesheet();
1506 m_event((iPlayableService*)this, evCuesheetChanged);
1509 void eDVBServicePlay::setCutListEnable(int enable)
1511 m_cutlist_enabled = enable;
1512 cutlistToCuesheet();
1515 void eDVBServicePlay::updateTimeshiftPids()
1520 eDVBServicePMTHandler::program program;
1521 if (m_service_handler.getProgramInfo(program))
1525 std::set<int> pids_to_record;
1526 pids_to_record.insert(0); // PAT
1527 if (program.pmtPid != -1)
1528 pids_to_record.insert(program.pmtPid); // PMT
1530 if (program.textPid != -1)
1531 pids_to_record.insert(program.textPid); // Videotext
1533 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1534 i(program.videoStreams.begin());
1535 i != program.videoStreams.end(); ++i)
1536 pids_to_record.insert(i->pid);
1538 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1539 i(program.audioStreams.begin());
1540 i != program.audioStreams.end(); ++i)
1541 pids_to_record.insert(i->pid);
1543 std::set<int> new_pids, obsolete_pids;
1545 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1546 m_pids_active.begin(), m_pids_active.end(),
1547 std::inserter(new_pids, new_pids.begin()));
1549 std::set_difference(
1550 m_pids_active.begin(), m_pids_active.end(),
1551 pids_to_record.begin(), pids_to_record.end(),
1552 std::inserter(new_pids, new_pids.begin())
1555 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1556 m_record->addPID(*i);
1558 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1559 m_record->removePID(*i);
1563 void eDVBServicePlay::switchToLive()
1565 if (!m_timeshift_active)
1571 m_teletext_parser = 0;
1573 /* free the timeshift service handler, we need the resources */
1574 m_service_handler_timeshift.free();
1575 m_timeshift_active = 0;
1577 m_event((iPlayableService*)this, evSeekableStatusChanged);
1582 void eDVBServicePlay::switchToTimeshift()
1584 if (m_timeshift_active)
1589 m_teletext_parser = 0;
1591 m_timeshift_active = 1;
1593 m_event((iPlayableService*)this, evSeekableStatusChanged);
1595 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1596 r.path = m_timeshift_file;
1598 m_cue = new eCueSheet();
1599 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1600 updateDecoder(); /* mainly to switch off PCR */
1603 void eDVBServicePlay::updateDecoder()
1605 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1;
1606 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1608 bool defaultac3=false;
1609 std::string default_ac3;
1611 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1612 defaultac3 = default_ac3 == "enable";
1614 eDVBServicePMTHandler::program program;
1615 if (h.getProgramInfo(program))
1616 eDebug("getting program info failed.");
1619 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1620 if (!program.videoStreams.empty())
1622 eDebugNoNewLine(" (");
1623 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1624 i(program.videoStreams.begin());
1625 i != program.videoStreams.end(); ++i)
1632 if (i != program.videoStreams.begin())
1633 eDebugNoNewLine(", ");
1634 eDebugNoNewLine("%04x", i->pid);
1636 eDebugNoNewLine(")");
1638 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1639 if (!program.audioStreams.empty())
1641 eDebugNoNewLine(" (");
1642 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1643 i(program.audioStreams.begin());
1644 i != program.audioStreams.end(); ++i)
1646 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1648 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1654 if (i != program.audioStreams.begin())
1655 eDebugNoNewLine(", ");
1656 eDebugNoNewLine("%04x", i->pid);
1658 eDebugNoNewLine(")");
1660 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1661 pcrpid = program.pcrPid;
1662 eDebug(", and the text pid is %04x", program.textPid);
1663 tpid = program.textPid;
1664 achannel = program.audioChannel;
1669 h.getDecodeDemux(m_decode_demux);
1671 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1673 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1674 #ifdef INTERNAL_TELETEXT
1675 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1676 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1682 m_decoder->setVideoPID(vpid, vpidtype);
1683 m_current_audio_stream = 0;
1684 m_decoder->setAudioPID(apid, apidtype);
1685 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1686 m_decoder->setSyncPCR(pcrpid);
1688 m_decoder->setSyncPCR(-1);
1690 m_decoder->setTextPID(tpid);
1692 if (m_teletext_parser)
1693 m_teletext_parser->start(tpid);
1696 m_decoder->setTrickmode(1);
1700 m_current_audio_channel=achannel;
1701 m_decoder->setAudioChannel(achannel);
1703 // how we can do this better?
1704 // update cache pid when the user changed the audio track or video track
1705 // TODO handling of difference audio types.. default audio types..
1707 /* don't worry about non-existing services, nor pvr services */
1708 if (m_dvb_service && !m_is_pvr)
1710 if (apidtype == eDVBAudio::aMPEG)
1712 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1713 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1717 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1718 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1720 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1721 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1722 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1723 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1728 void eDVBServicePlay::loadCuesheet()
1730 std::string filename = m_reference.path + ".cuts";
1732 m_cue_entries.clear();
1734 FILE *f = fopen(filename.c_str(), "rb");
1738 eDebug("loading cuts..");
1741 unsigned long long where;
1744 if (!fread(&where, sizeof(where), 1, f))
1746 if (!fread(&what, sizeof(what), 1, f))
1749 #if BYTE_ORDER == LITTLE_ENDIAN
1750 where = bswap_64(where);
1757 m_cue_entries.insert(cueEntry(where, what));
1760 eDebug("%d entries", m_cue_entries.size());
1762 eDebug("cutfile not found!");
1764 m_cuesheet_changed = 0;
1765 cutlistToCuesheet();
1766 m_event((iPlayableService*)this, evCuesheetChanged);
1769 void eDVBServicePlay::saveCuesheet()
1771 std::string filename = m_reference.path + ".cuts";
1773 FILE *f = fopen(filename.c_str(), "wb");
1777 unsigned long long where;
1780 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1782 #if BYTE_ORDER == BIG_ENDIAN
1785 where = bswap_64(i->where);
1787 what = htonl(i->what);
1788 fwrite(&where, sizeof(where), 1, f);
1789 fwrite(&what, sizeof(what), 1, f);
1795 m_cuesheet_changed = 0;
1798 void eDVBServicePlay::cutlistToCuesheet()
1802 eDebug("no cue sheet");
1807 if (!m_cutlist_enabled)
1809 m_cue->commitSpans();
1810 eDebug("cutlists where disabled");
1814 pts_t in = 0, out = 0, length = 0;
1818 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1822 if (i == m_cue_entries.end())
1825 if (i->what == 0) /* in */
1829 } else if (i->what == 1) /* out */
1839 m_cue->addSourceSpan(in, out);
1843 if (i == m_cue_entries.end())
1846 m_cue->commitSpans();
1849 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1851 if (m_subtitle_widget)
1852 disableSubtitles(parent);
1854 if (!m_teletext_parser)
1857 if (!PyInt_Check(entry))
1860 m_subtitle_widget = new eSubtitleWidget(parent);
1861 m_subtitle_widget->resize(parent->size()); /* full size */
1863 int page = PyInt_AsLong(entry);
1865 m_teletext_parser->setPage(page);
1870 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
1872 delete m_subtitle_widget;
1873 m_subtitle_widget = 0;
1877 PyObject *eDVBServicePlay::getSubtitleList()
1879 if (!m_teletext_parser)
1885 PyObject *l = PyList_New(0);
1887 for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
1889 PyObject *tuple = PyTuple_New(2);
1891 sprintf(desc, "Page %x", *i);
1892 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
1893 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
1894 PyList_Append(l, tuple);
1900 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
1902 if (m_subtitle_widget)
1904 m_subtitle_pages.push_back(page);
1906 checkSubtitleTiming();
1910 void eDVBServicePlay::checkSubtitleTiming()
1914 if (m_subtitle_pages.empty())
1917 eDVBTeletextSubtitlePage p = m_subtitle_pages.front();
1922 m_decoder->getPTS(0, pos);
1924 int diff = p.m_pts - pos;
1927 eDebug("[late (%d ms)]", -diff / 90);
1932 eDebug("[invalid]");
1938 m_subtitle_widget->setPage(p);
1939 m_subtitle_pages.pop_front();
1942 m_subtitle_sync_timer.start(diff / 90, 1);
1948 DEFINE_REF(eDVBServicePlay)
1950 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");