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>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/service/servicedvbrecord.h>
14 #include <lib/dvb/metaparser.h>
15 #include <lib/dvb/tstools.h>
16 #include <lib/python/python.h>
20 #define TSPATH "/media/hdd"
22 class eStaticServiceDVBInformation: public iStaticServiceInformation
24 DECLARE_REF(eStaticServiceDVBInformation);
26 RESULT getName(const eServiceReference &ref, std::string &name);
27 int getLength(const eServiceReference &ref);
30 DEFINE_REF(eStaticServiceDVBInformation);
32 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
34 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
35 if ( !ref.name.empty() )
37 if (service.getParentTransportStreamID().get()) // linkage subservice
39 ePtr<iServiceHandler> service_center;
40 if (!eServiceCenter::getInstance(service_center))
42 eServiceReferenceDVB parent = service;
43 parent.setTransportStreamID( service.getParentTransportStreamID() );
44 parent.setServiceID( service.getParentServiceID() );
45 parent.setParentTransportStreamID(eTransportStreamID(0));
46 parent.setParentServiceID(eServiceID(0));
48 ePtr<iStaticServiceInformation> service_info;
49 if (!service_center->info(parent, service_info))
51 if (!service_info->getName(parent, name))
53 // just show short name
54 unsigned int pos = name.find("\xc2\x86");
55 if ( pos != std::string::npos )
57 pos = name.find("\xc2\x87");
58 if ( pos != std::string::npos )
74 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
79 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
81 DECLARE_REF(eStaticServiceDVBBouquetInformation);
83 RESULT getName(const eServiceReference &ref, std::string &name);
84 int getLength(const eServiceReference &ref);
87 DEFINE_REF(eStaticServiceDVBBouquetInformation);
89 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
91 ePtr<iDVBChannelList> db;
92 ePtr<eDVBResourceManager> res;
95 if ((err = eDVBResourceManager::getInstance(res)) != 0)
97 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
100 if ((err = res->getChannelList(db)) != 0)
102 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
107 if ((err = db->getBouquet(ref, bouquet)) != 0)
109 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
113 if ( bouquet && bouquet->m_bouquet_name.length() )
115 name = bouquet->m_bouquet_name;
122 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
127 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
129 DECLARE_REF(eStaticServiceDVBPVRInformation);
130 eServiceReference m_ref;
131 eDVBMetaParser m_parser;
133 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
134 RESULT getName(const eServiceReference &ref, std::string &name);
135 int getLength(const eServiceReference &ref);
137 int getInfo(const eServiceReference &ref, int w);
138 std::string getInfoString(const eServiceReference &ref,int w);
141 DEFINE_REF(eStaticServiceDVBPVRInformation);
143 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
146 m_parser.parseFile(ref.path);
149 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
151 ASSERT(ref == m_ref);
152 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
156 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
158 ASSERT(ref == m_ref);
162 if (tstools.openFile(ref.path.c_str()))
166 if (tstools.calcLen(len))
172 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
176 case iServiceInformation::sDescription:
177 return iServiceInformation::resIsString;
178 case iServiceInformation::sTimeCreate:
179 if (m_parser.m_time_create)
180 return m_parser.m_time_create;
182 return iServiceInformation::resNA;
184 return iServiceInformation::resNA;
188 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
192 case iServiceInformation::sDescription:
193 return m_parser.m_description;
199 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
201 DECLARE_REF(eDVBPVRServiceOfflineOperations);
202 eServiceReferenceDVB m_ref;
204 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
206 RESULT deleteFromDisk(int simulate);
207 RESULT getListOfFilenames(std::list<std::string> &);
210 DEFINE_REF(eDVBPVRServiceOfflineOperations);
212 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
216 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
222 std::list<std::string> res;
223 if (getListOfFilenames(res))
226 /* TODO: deferred removing.. */
227 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
229 eDebug("Removing %s...", i->c_str());
230 ::unlink(i->c_str());
237 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
240 res.push_back(m_ref.path);
241 res.push_back(m_ref.path + ".meta");
245 DEFINE_REF(eServiceFactoryDVB)
247 eServiceFactoryDVB::eServiceFactoryDVB()
249 ePtr<eServiceCenter> sc;
251 eServiceCenter::getPrivInstance(sc);
253 sc->addServiceFactory(eServiceFactoryDVB::id, this);
256 eServiceFactoryDVB::~eServiceFactoryDVB()
258 ePtr<eServiceCenter> sc;
260 eServiceCenter::getPrivInstance(sc);
262 sc->removeServiceFactory(eServiceFactoryDVB::id);
265 DEFINE_REF(eDVBServiceList);
267 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
271 eDVBServiceList::~eDVBServiceList()
275 RESULT eDVBServiceList::startQuery()
277 ePtr<iDVBChannelList> db;
278 ePtr<eDVBResourceManager> res;
281 if ((err = eDVBResourceManager::getInstance(res)) != 0)
283 eDebug("no resource manager");
286 if ((err = res->getChannelList(db)) != 0)
288 eDebug("no channel list");
292 ePtr<eDVBChannelQuery> q;
294 if (!m_parent.path.empty())
296 eDVBChannelQuery::compile(q, m_parent.path);
299 eDebug("compile query failed");
304 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
306 eDebug("startQuery failed");
313 RESULT eDVBServiceList::getContent(PyObject *list, bool sorted)
315 eServiceReferenceDVB ref;
317 if (!m_query || !list || !PyList_Check(list))
320 std::list<eServiceReferenceDVB> tmplist;
322 while (!m_query->getNextResult(ref))
323 tmplist.push_back(ref);
326 tmplist.sort(iListableServiceCompare(this));
328 for (std::list<eServiceReferenceDVB>::iterator it(tmplist.begin());
329 it != tmplist.end(); ++it)
331 PyObject *refobj = New_eServiceReference(*it);
332 PyList_Append(list, refobj);
338 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
340 eServiceReferenceDVB ref;
345 while (!m_query->getNextResult(ref))
349 list.sort(iListableServiceCompare(this));
354 RESULT eDVBServiceList::getNext(eServiceReference &ref)
359 return m_query->getNextResult((eServiceReferenceDVB&)ref);
362 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
364 return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
367 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
369 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
371 ePtr<iDVBChannelList> db;
372 ePtr<eDVBResourceManager> resm;
374 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
377 if (db->getBouquet(m_parent, m_bouquet) != 0)
388 RESULT eDVBServiceList::addService(eServiceReference &ref)
392 return m_bouquet->addService(ref);
395 RESULT eDVBServiceList::removeService(eServiceReference &ref)
399 return m_bouquet->removeService(ref);
402 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
406 return m_bouquet->moveService(ref, pos);
409 RESULT eDVBServiceList::flushChanges()
413 return m_bouquet->flushChanges();
416 RESULT eDVBServiceList::setListName(const std::string &name)
420 return m_bouquet->setListName(name);
423 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
425 ePtr<eDVBService> service;
426 int r = lookupService(service, ref);
429 // check resources...
430 ptr = new eDVBServicePlay(ref, service);
434 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
436 if (ref.path.empty())
438 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
447 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
449 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
450 if (list->startQuery())
460 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
462 /* is a listable service? */
463 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
465 if ( !ref.name.empty() ) // satellites or providers list
466 ptr = new eStaticServiceDVBInformation;
467 else // a dvb bouquet
468 ptr = new eStaticServiceDVBBouquetInformation;
470 else if (!ref.path.empty()) /* do we have a PVR service? */
471 ptr = new eStaticServiceDVBPVRInformation(ref);
472 else // normal dvb service
474 ePtr<eDVBService> service;
475 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
476 ptr = new eStaticServiceDVBInformation;
478 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
484 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
486 if (ref.path.empty())
492 ptr = new eDVBPVRServiceOfflineOperations(ref);
497 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
499 // TODO: handle the listing itself
500 // if (ref.... == -1) .. return "... bouquets ...";
501 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
503 ePtr<iDVBChannelList> db;
504 ePtr<eDVBResourceManager> res;
507 if ((err = eDVBResourceManager::getInstance(res)) != 0)
509 eDebug("no resource manager");
512 if ((err = res->getChannelList(db)) != 0)
514 eDebug("no channel list");
518 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
519 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
521 eDebug("getService failed!");
528 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
529 m_reference(ref), m_dvb_service(service), m_is_paused(0)
531 m_is_pvr = !ref.path.empty();
532 m_timeshift_enabled = m_timeshift_active = 0;
535 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
536 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
537 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
540 eDVBServicePlay::~eDVBServicePlay()
544 void eDVBServicePlay::gotNewEvent()
548 ePtr<eServiceEvent> m_event_now, m_event_next;
549 getEvent(m_event_now, 0);
550 getEvent(m_event_next, 1);
553 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
555 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
557 m_event((iPlayableService*)this, evUpdatedEventInfo);
560 void eDVBServicePlay::serviceEvent(int event)
564 case eDVBServicePMTHandler::eventTuned:
566 ePtr<iDVBDemux> m_demux;
567 if (!m_service_handler.getDataDemux(m_demux))
569 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
570 int sid = ref.getParentServiceID().get();
572 sid = ref.getServiceID().get();
573 if ( ref.getParentTransportStreamID().get() &&
574 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
575 m_event_handler.startOther(m_demux, sid);
577 m_event_handler.start(m_demux, sid);
581 case eDVBServicePMTHandler::eventTuneFailed:
583 eDebug("DVB service failed to tune");
584 m_event((iPlayableService*)this, evTuneFailed);
587 case eDVBServicePMTHandler::eventNewProgramInfo:
589 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
590 if (m_timeshift_enabled)
591 updateTimeshiftPids();
592 if (!m_timeshift_active)
594 m_event((iPlayableService*)this, evUpdatedInfo);
597 case eDVBServicePMTHandler::eventEOF:
598 m_event((iPlayableService*)this, evEOF);
600 case eDVBServicePMTHandler::eventSOF:
601 m_event((iPlayableService*)this, evSOF);
606 void eDVBServicePlay::serviceEventTimeshift(int event)
610 case eDVBServicePMTHandler::eventNewProgramInfo:
611 if (m_timeshift_active)
614 case eDVBServicePMTHandler::eventEOF:
620 RESULT eDVBServicePlay::start()
623 /* in pvr mode, we only want to use one demux. in tv mode, we're using
624 two (one for decoding, one for data source), as we must be prepared
625 to start recording from the data demux. */
626 m_cue = new eCueSheet();
627 r = m_service_handler.tune((eServiceReferenceDVB&)m_reference, m_is_pvr, m_cue);
628 m_event(this, evStart);
629 m_event((iPlayableService*)this, evSeekableStatusChanged);
633 RESULT eDVBServicePlay::stop()
635 eDebug("stop timeshift");
636 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
638 eDebug("free ts handler");
639 m_service_handler_timeshift.free();
640 eDebug("stop service handler");
641 m_service_handler.free();
647 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
649 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
653 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
655 /* note: we check for timeshift to be enabled,
656 not neccessary active. if you pause when timeshift
657 is not active, you should activate it when unpausing */
658 if ((!m_is_pvr) && (!m_timeshift_enabled))
668 RESULT eDVBServicePlay::setSlowMotion(int ratio)
671 return m_decoder->setSlowMotion(ratio);
676 RESULT eDVBServicePlay::setFastForward(int ratio)
678 int skipmode, ffratio;
684 } else if (ratio > 0)
692 } else // if (ratio < 0)
698 if (m_skipmode != skipmode)
700 eDebug("setting cue skipmode to %d", skipmode);
702 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
705 m_skipmode = skipmode;
710 return m_decoder->setFastForward(ffratio);
713 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
715 if (m_is_pvr || m_timeshift_enabled)
725 /* TODO: when timeshift is enabled but not active, this doesn't work. */
726 RESULT eDVBServicePlay::getLength(pts_t &len)
728 ePtr<iDVBPVRChannel> pvr_channel;
730 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
733 return pvr_channel->getLength(len);
736 RESULT eDVBServicePlay::pause()
738 if (!m_is_paused && m_decoder)
741 return m_decoder->freeze(0);
746 RESULT eDVBServicePlay::unpause()
748 if (m_is_paused && m_decoder)
751 return m_decoder->unfreeze();
756 RESULT eDVBServicePlay::seekTo(pts_t to)
758 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
763 ePtr<iDVBPVRChannel> pvr_channel;
765 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
771 m_cue->seekTo(0, to);
775 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
777 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
782 ePtr<iDVBPVRChannel> pvr_channel;
784 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
792 m_cue->seekTo(1, to);
796 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
798 ePtr<iDVBPVRChannel> pvr_channel;
803 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
806 return pvr_channel->getCurrentPosition(m_decode_demux, pos, 1);
809 RESULT eDVBServicePlay::setTrickmode(int trick)
812 m_decoder->setTrickmode(trick);
816 RESULT eDVBServicePlay::isCurrentlySeekable()
818 return m_is_pvr || m_timeshift_active;
821 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
827 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
833 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
839 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
845 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
848 if (m_timeshift_enabled || !m_is_pvr)
850 if (!m_timeshift_enabled)
852 /* we need enough diskspace */
854 if (statfs(TSPATH "/.", &fs) < 0)
856 eDebug("statfs failed!");
860 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
862 eDebug("not enough diskspace for timeshift! (less than 1GB)");
872 RESULT eDVBServicePlay::getName(std::string &name)
876 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
877 return i->getName(m_reference, name);
881 m_dvb_service->getName(m_reference, name);
885 else if (!m_reference.name.empty())
886 eStaticServiceDVBInformation().getName(m_reference, name);
888 name = "DVB service";
892 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
894 return m_event_handler.getEvent(evt, nownext);
897 int eDVBServicePlay::getInfo(int w)
899 eDVBServicePMTHandler::program program;
901 if (m_service_handler.getProgramInfo(program))
907 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
909 ePtr<eServiceEvent> evt;
910 if (!m_event_handler.getEvent(evt, 0))
912 ePtr<eComponentData> data;
913 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
915 if ( data->getStreamContent() == 1 )
917 switch(data->getComponentType())
920 case 1: // 4:3 SD PAL
922 case 3: // 16:9 SD PAL
923 case 4: // > 16:9 PAL
924 case 5: // 4:3 SD NTSC
926 case 7: // 16:9 SD NTSC
927 case 8: // > 16:9 NTSC
930 case 9: // 4:3 HD PAL
932 case 0xB: // 16:9 HD PAL
933 case 0xC: // > 16:9 HD PAL
934 case 0xD: // 4:3 HD NTSC
936 case 0xF: // 16:9 HD NTSC
937 case 0x10: // > 16:9 HD PAL
938 return data->getComponentType();
945 case sIsCrypted: return program.isCrypted;
946 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
947 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
948 case sPCRPID: return program.pcrPid;
949 case sPMTPID: return program.pmtPid;
950 case sTXTPID: return program.textPid;
951 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
952 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
953 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
954 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
955 case sProvider: if (!m_dvb_service) return -1; return -2;
961 std::string eDVBServicePlay::getInfoString(int w)
966 if (!m_dvb_service) return "";
967 return m_dvb_service->m_provider_name;
973 int eDVBServicePlay::getNumberOfTracks()
975 eDVBServicePMTHandler::program program;
976 if (m_service_handler.getProgramInfo(program))
978 return program.audioStreams.size();
981 RESULT eDVBServicePlay::selectTrack(unsigned int i)
983 int ret = selectAudioStream(i);
985 if (m_decoder->start())
991 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
993 eDVBServicePMTHandler::program program;
995 if (m_service_handler.getProgramInfo(program))
998 if (i >= program.audioStreams.size())
1001 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1002 info.m_description = "MPEG";
1003 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1004 info.m_description = "AC3";
1005 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1006 info.m_description = "DTS";
1008 info.m_description = "???";
1010 if (program.audioStreams[i].component_tag != -1)
1012 ePtr<eServiceEvent> evt;
1013 if (!m_event_handler.getEvent(evt, 0))
1015 ePtr<eComponentData> data;
1016 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1017 info.m_language = data->getText();
1021 if (info.m_language.empty())
1022 info.m_language = program.audioStreams[i].language_code;
1027 int eDVBServicePlay::selectAudioStream(int i)
1029 eDVBServicePMTHandler::program program;
1031 if (m_service_handler.getProgramInfo(program))
1034 if ((unsigned int)i >= program.audioStreams.size())
1040 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1043 if (m_dvb_service && !m_is_pvr)
1045 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1047 m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
1048 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1051 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1052 m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
1056 m_current_audio_stream = i;
1061 int eDVBServicePlay::getFrontendInfo(int w)
1065 eUsePtr<iDVBChannel> channel;
1066 if(m_service_handler.getChannel(channel))
1068 ePtr<iDVBFrontend> fe;
1069 if(channel->getFrontend(fe))
1071 return fe->readFrontendData(w);
1074 int eDVBServicePlay::getNumberOfSubservices()
1076 ePtr<eServiceEvent> evt;
1077 if (!m_event_handler.getEvent(evt, 0))
1078 return evt->getNumOfLinkageServices();
1082 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1084 ePtr<eServiceEvent> evt;
1085 if (!m_event_handler.getEvent(evt, 0))
1087 if (!evt->getLinkageService(sub, m_reference, n))
1090 sub.type=eServiceReference::idInvalid;
1094 RESULT eDVBServicePlay::startTimeshift()
1096 ePtr<iDVBDemux> demux;
1098 eDebug("Start timeshift!");
1100 if (m_timeshift_enabled)
1103 /* start recording with the data demux. */
1104 if (m_service_handler.getDataDemux(demux))
1107 demux->createTSRecorder(m_record);
1111 char templ[]=TSPATH "/timeshift.XXXXXX";
1112 m_timeshift_fd = mkstemp(templ);
1113 m_timeshift_file = templ;
1115 eDebug("recording to %s", templ);
1117 if (m_timeshift_fd < 0)
1123 m_record->setTargetFD(m_timeshift_fd);
1125 m_timeshift_enabled = 1;
1127 updateTimeshiftPids();
1133 RESULT eDVBServicePlay::stopTimeshift()
1135 if (!m_timeshift_enabled)
1140 m_timeshift_enabled = 0;
1145 close(m_timeshift_fd);
1146 eDebug("remove timeshift file");
1147 remove(m_timeshift_file.c_str());
1152 int eDVBServicePlay::isTimeshiftActive()
1154 return m_timeshift_enabled && m_timeshift_active;
1157 RESULT eDVBServicePlay::activateTimeshift()
1159 if (!m_timeshift_enabled)
1162 if (!m_timeshift_active)
1164 switchToTimeshift();
1171 void eDVBServicePlay::updateTimeshiftPids()
1176 eDVBServicePMTHandler::program program;
1177 if (m_service_handler.getProgramInfo(program))
1181 std::set<int> pids_to_record;
1182 pids_to_record.insert(0); // PAT
1183 if (program.pmtPid != -1)
1184 pids_to_record.insert(program.pmtPid); // PMT
1186 if (program.textPid != -1)
1187 pids_to_record.insert(program.textPid); // Videotext
1189 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1190 i(program.videoStreams.begin());
1191 i != program.videoStreams.end(); ++i)
1192 pids_to_record.insert(i->pid);
1194 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1195 i(program.audioStreams.begin());
1196 i != program.audioStreams.end(); ++i)
1197 pids_to_record.insert(i->pid);
1199 std::set<int> new_pids, obsolete_pids;
1201 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1202 m_pids_active.begin(), m_pids_active.end(),
1203 std::inserter(new_pids, new_pids.begin()));
1205 std::set_difference(
1206 m_pids_active.begin(), m_pids_active.end(),
1207 pids_to_record.begin(), pids_to_record.end(),
1208 std::inserter(new_pids, new_pids.begin())
1211 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1212 m_record->addPID(*i);
1214 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1215 m_record->removePID(*i);
1219 void eDVBServicePlay::switchToLive()
1221 if (!m_timeshift_active)
1226 /* free the timeshift service handler, we need the resources */
1227 m_service_handler_timeshift.free();
1228 m_timeshift_active = 0;
1230 m_event((iPlayableService*)this, evSeekableStatusChanged);
1235 void eDVBServicePlay::switchToTimeshift()
1237 if (m_timeshift_active)
1243 m_timeshift_active = 1;
1245 m_event((iPlayableService*)this, evSeekableStatusChanged);
1247 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1248 r.path = m_timeshift_file;
1250 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1253 void eDVBServicePlay::updateDecoder()
1255 int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
1256 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1258 eDVBServicePMTHandler::program program;
1259 if (h.getProgramInfo(program))
1260 eDebug("getting program info failed.");
1263 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1264 if (!program.videoStreams.empty())
1266 eDebugNoNewLine(" (");
1267 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1268 i(program.videoStreams.begin());
1269 i != program.videoStreams.end(); ++i)
1273 if (i != program.videoStreams.begin())
1274 eDebugNoNewLine(", ");
1275 eDebugNoNewLine("%04x", i->pid);
1277 eDebugNoNewLine(")");
1279 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1280 if (!program.audioStreams.empty())
1282 eDebugNoNewLine(" (");
1283 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1284 i(program.audioStreams.begin());
1285 i != program.audioStreams.end(); ++i)
1292 if (i != program.audioStreams.begin())
1293 eDebugNoNewLine(", ");
1294 eDebugNoNewLine("%04x", i->pid);
1296 eDebugNoNewLine(")");
1298 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1299 pcrpid = program.pcrPid;
1300 eDebug(", and the text pid is %04x", program.textPid);
1301 tpid = program.textPid;
1306 h.getDecodeDemux(m_decode_demux);
1308 m_decode_demux->getMPEGDecoder(m_decoder);
1310 m_cue->setDecodingDemux(m_decode_demux);
1315 m_decoder->setVideoPID(vpid);
1316 m_current_audio_stream = 0;
1317 m_decoder->setAudioPID(apid, apidtype);
1318 if (!(m_is_pvr || m_timeshift_active))
1319 m_decoder->setSyncPCR(pcrpid);
1321 m_decoder->setSyncPCR(-1);
1322 m_decoder->setTextPID(tpid);
1324 // how we can do this better?
1325 // update cache pid when the user changed the audio track or video track
1326 // TODO handling of difference audio types.. default audio types..
1328 /* don't worry about non-existing services, nor pvr services */
1329 if (m_dvb_service && !m_is_pvr)
1331 if (apidtype == eDVBAudio::aMPEG)
1333 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
1334 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1338 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1339 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
1341 m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
1342 m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
1343 m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
1348 DEFINE_REF(eDVBServicePlay)
1350 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");