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_active)
725 RESULT eDVBServicePlay::getLength(pts_t &len)
727 ePtr<iDVBPVRChannel> pvr_channel;
729 if (m_service_handler.getPVRChannel(pvr_channel))
731 eDebug("getPVRChannel failed!");
735 return pvr_channel->getLength(len);
738 RESULT eDVBServicePlay::pause()
740 if (!m_is_paused && m_decoder)
743 return m_decoder->freeze(0);
748 RESULT eDVBServicePlay::unpause()
750 if (m_is_paused && m_decoder)
753 return m_decoder->unfreeze();
758 RESULT eDVBServicePlay::seekTo(pts_t to)
760 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
765 ePtr<iDVBPVRChannel> pvr_channel;
767 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
773 m_cue->seekTo(0, to);
777 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
779 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
784 ePtr<iDVBPVRChannel> pvr_channel;
786 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
794 m_cue->seekTo(1, to);
798 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
800 ePtr<iDVBPVRChannel> pvr_channel;
805 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
808 return pvr_channel->getCurrentPosition(m_decode_demux, pos, 1);
811 RESULT eDVBServicePlay::setTrickmode(int trick)
814 m_decoder->setTrickmode(trick);
818 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
824 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
830 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
836 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
842 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
845 if (m_timeshift_enabled || !m_is_pvr)
847 if (!m_timeshift_enabled)
849 /* we need enough diskspace */
851 if (statfs(TSPATH "/.", &fs) < 0)
853 eDebug("statfs failed!");
857 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
859 eDebug("not enough diskspace for timeshift! (less than 1GB)");
869 RESULT eDVBServicePlay::getName(std::string &name)
873 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
874 return i->getName(m_reference, name);
878 m_dvb_service->getName(m_reference, name);
882 else if (!m_reference.name.empty())
883 eStaticServiceDVBInformation().getName(m_reference, name);
885 name = "DVB service";
889 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
891 return m_event_handler.getEvent(evt, nownext);
894 int eDVBServicePlay::getInfo(int w)
896 eDVBServicePMTHandler::program program;
898 if (m_service_handler.getProgramInfo(program))
904 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
906 ePtr<eServiceEvent> evt;
907 if (!m_event_handler.getEvent(evt, 0))
909 ePtr<eComponentData> data;
910 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
912 if ( data->getStreamContent() == 1 )
914 switch(data->getComponentType())
917 case 1: // 4:3 SD PAL
919 case 3: // 16:9 SD PAL
920 case 4: // > 16:9 PAL
921 case 5: // 4:3 SD NTSC
923 case 7: // 16:9 SD NTSC
924 case 8: // > 16:9 NTSC
927 case 9: // 4:3 HD PAL
929 case 0xB: // 16:9 HD PAL
930 case 0xC: // > 16:9 HD PAL
931 case 0xD: // 4:3 HD NTSC
933 case 0xF: // 16:9 HD NTSC
934 case 0x10: // > 16:9 HD PAL
935 return data->getComponentType();
942 case sIsCrypted: return program.isCrypted;
943 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
944 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
945 case sPCRPID: return program.pcrPid;
946 case sPMTPID: return program.pmtPid;
947 case sTXTPID: return program.textPid;
948 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
949 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
950 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
951 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
952 case sProvider: if (!m_dvb_service) return -1; return -2;
958 std::string eDVBServicePlay::getInfoString(int w)
963 if (!m_dvb_service) return "";
964 return m_dvb_service->m_provider_name;
970 int eDVBServicePlay::getNumberOfTracks()
972 eDVBServicePMTHandler::program program;
973 if (m_service_handler.getProgramInfo(program))
975 return program.audioStreams.size();
978 RESULT eDVBServicePlay::selectTrack(unsigned int i)
980 int ret = selectAudioStream(i);
982 if (m_decoder->start())
988 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
990 eDVBServicePMTHandler::program program;
992 if (m_service_handler.getProgramInfo(program))
995 if (i >= program.audioStreams.size())
998 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
999 info.m_description = "MPEG";
1000 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1001 info.m_description = "AC3";
1002 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1003 info.m_description = "DTS";
1005 info.m_description = "???";
1007 if (program.audioStreams[i].component_tag != -1)
1009 ePtr<eServiceEvent> evt;
1010 if (!m_event_handler.getEvent(evt, 0))
1012 ePtr<eComponentData> data;
1013 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1014 info.m_language = data->getText();
1018 if (info.m_language.empty())
1019 info.m_language = program.audioStreams[i].language_code;
1024 int eDVBServicePlay::selectAudioStream(int i)
1026 eDVBServicePMTHandler::program program;
1028 if (m_service_handler.getProgramInfo(program))
1031 if ((unsigned int)i >= program.audioStreams.size())
1037 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1040 if (m_dvb_service && !m_is_pvr)
1042 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1044 m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
1045 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1048 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1049 m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
1053 m_current_audio_stream = i;
1058 int eDVBServicePlay::getFrontendInfo(int w)
1062 eUsePtr<iDVBChannel> channel;
1063 if(m_service_handler.getChannel(channel))
1065 ePtr<iDVBFrontend> fe;
1066 if(channel->getFrontend(fe))
1068 return fe->readFrontendData(w);
1071 int eDVBServicePlay::getNumberOfSubservices()
1073 ePtr<eServiceEvent> evt;
1074 if (!m_event_handler.getEvent(evt, 0))
1075 return evt->getNumOfLinkageServices();
1079 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1081 ePtr<eServiceEvent> evt;
1082 if (!m_event_handler.getEvent(evt, 0))
1084 if (!evt->getLinkageService(sub, m_reference, n))
1087 sub.type=eServiceReference::idInvalid;
1091 RESULT eDVBServicePlay::startTimeshift()
1093 ePtr<iDVBDemux> demux;
1095 eDebug("Start timeshift!");
1097 if (m_timeshift_enabled)
1100 /* start recording with the data demux. */
1101 if (m_service_handler.getDataDemux(demux))
1104 demux->createTSRecorder(m_record);
1108 char templ[]=TSPATH "/timeshift.XXXXXX";
1109 m_timeshift_fd = mkstemp(templ);
1110 m_timeshift_file = templ;
1112 eDebug("recording to %s", templ);
1114 if (m_timeshift_fd < 0)
1120 m_record->setTargetFD(m_timeshift_fd);
1122 m_timeshift_enabled = 1;
1124 updateTimeshiftPids();
1130 RESULT eDVBServicePlay::stopTimeshift()
1132 if (!m_timeshift_enabled)
1137 m_timeshift_enabled = 0;
1142 close(m_timeshift_fd);
1143 remove(m_timeshift_file.c_str());
1148 int eDVBServicePlay::isTimeshiftActive()
1150 return m_timeshift_enabled && m_timeshift_active;
1153 RESULT eDVBServicePlay::activateTimeshift()
1155 if (!m_timeshift_enabled)
1158 if (!m_timeshift_active)
1160 switchToTimeshift();
1167 void eDVBServicePlay::updateTimeshiftPids()
1172 eDVBServicePMTHandler::program program;
1173 if (m_service_handler.getProgramInfo(program))
1177 std::set<int> pids_to_record;
1178 pids_to_record.insert(0); // PAT
1179 if (program.pmtPid != -1)
1180 pids_to_record.insert(program.pmtPid); // PMT
1182 if (program.textPid != -1)
1183 pids_to_record.insert(program.textPid); // Videotext
1185 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1186 i(program.videoStreams.begin());
1187 i != program.videoStreams.end(); ++i)
1188 pids_to_record.insert(i->pid);
1190 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1191 i(program.audioStreams.begin());
1192 i != program.audioStreams.end(); ++i)
1193 pids_to_record.insert(i->pid);
1195 std::set<int> new_pids, obsolete_pids;
1197 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1198 m_pids_active.begin(), m_pids_active.end(),
1199 std::inserter(new_pids, new_pids.begin()));
1201 std::set_difference(
1202 m_pids_active.begin(), m_pids_active.end(),
1203 pids_to_record.begin(), pids_to_record.end(),
1204 std::inserter(new_pids, new_pids.begin())
1207 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1208 m_record->addPID(*i);
1210 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1211 m_record->removePID(*i);
1215 void eDVBServicePlay::switchToLive()
1217 if (!m_timeshift_active)
1222 /* free the timeshift service handler, we need the resources */
1223 m_service_handler_timeshift.free();
1224 m_timeshift_active = 0;
1226 m_event((iPlayableService*)this, evSeekableStatusChanged);
1231 void eDVBServicePlay::switchToTimeshift()
1233 if (m_timeshift_active)
1239 m_timeshift_active = 1;
1241 m_event((iPlayableService*)this, evSeekableStatusChanged);
1243 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1244 r.path = m_timeshift_file;
1246 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1249 void eDVBServicePlay::updateDecoder()
1251 int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
1252 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1254 eDVBServicePMTHandler::program program;
1255 if (h.getProgramInfo(program))
1256 eDebug("getting program info failed.");
1259 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1260 if (!program.videoStreams.empty())
1262 eDebugNoNewLine(" (");
1263 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1264 i(program.videoStreams.begin());
1265 i != program.videoStreams.end(); ++i)
1269 if (i != program.videoStreams.begin())
1270 eDebugNoNewLine(", ");
1271 eDebugNoNewLine("%04x", i->pid);
1273 eDebugNoNewLine(")");
1275 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1276 if (!program.audioStreams.empty())
1278 eDebugNoNewLine(" (");
1279 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1280 i(program.audioStreams.begin());
1281 i != program.audioStreams.end(); ++i)
1288 if (i != program.audioStreams.begin())
1289 eDebugNoNewLine(", ");
1290 eDebugNoNewLine("%04x", i->pid);
1292 eDebugNoNewLine(")");
1294 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1295 pcrpid = program.pcrPid;
1296 eDebug(", and the text pid is %04x", program.textPid);
1297 tpid = program.textPid;
1302 h.getDecodeDemux(m_decode_demux);
1304 m_decode_demux->getMPEGDecoder(m_decoder);
1306 m_cue->setDecodingDemux(m_decode_demux);
1311 m_decoder->setVideoPID(vpid);
1312 m_current_audio_stream = 0;
1313 m_decoder->setAudioPID(apid, apidtype);
1314 if (!(m_is_pvr || m_timeshift_active))
1315 m_decoder->setSyncPCR(pcrpid);
1317 m_decoder->setSyncPCR(-1);
1318 m_decoder->setTextPID(tpid);
1320 // how we can do this better?
1321 // update cache pid when the user changed the audio track or video track
1322 // TODO handling of difference audio types.. default audio types..
1324 /* don't worry about non-existing services, nor pvr services */
1325 if (m_dvb_service && !m_is_pvr)
1327 if (apidtype == eDVBAudio::aMPEG)
1329 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
1330 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1334 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1335 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
1337 m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
1338 m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
1339 m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
1344 DEFINE_REF(eDVBServicePlay)
1346 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");