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/service/event.h>
15 #include <lib/dvb/metaparser.h>
16 #include <lib/dvb/tstools.h>
17 #include <lib/python/python.h>
22 #include <netinet/in.h>
24 #include <dvbsi++/event_information_section.h>
27 #error no byte order defined!
30 #define TSPATH "/media/hdd"
32 class eStaticServiceDVBInformation: public iStaticServiceInformation
34 DECLARE_REF(eStaticServiceDVBInformation);
36 RESULT getName(const eServiceReference &ref, std::string &name);
37 int getLength(const eServiceReference &ref);
40 DEFINE_REF(eStaticServiceDVBInformation);
42 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
44 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
45 if ( !ref.name.empty() )
47 if (service.getParentTransportStreamID().get()) // linkage subservice
49 ePtr<iServiceHandler> service_center;
50 if (!eServiceCenter::getInstance(service_center))
52 eServiceReferenceDVB parent = service;
53 parent.setTransportStreamID( service.getParentTransportStreamID() );
54 parent.setServiceID( service.getParentServiceID() );
55 parent.setParentTransportStreamID(eTransportStreamID(0));
56 parent.setParentServiceID(eServiceID(0));
58 ePtr<iStaticServiceInformation> service_info;
59 if (!service_center->info(parent, service_info))
61 if (!service_info->getName(parent, name))
63 // just show short name
64 unsigned int pos = name.find("\xc2\x86");
65 if ( pos != std::string::npos )
67 pos = name.find("\xc2\x87");
68 if ( pos != std::string::npos )
84 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
89 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
91 DECLARE_REF(eStaticServiceDVBBouquetInformation);
93 RESULT getName(const eServiceReference &ref, std::string &name);
94 int getLength(const eServiceReference &ref);
97 DEFINE_REF(eStaticServiceDVBBouquetInformation);
99 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
101 ePtr<iDVBChannelList> db;
102 ePtr<eDVBResourceManager> res;
105 if ((err = eDVBResourceManager::getInstance(res)) != 0)
107 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
110 if ((err = res->getChannelList(db)) != 0)
112 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
117 if ((err = db->getBouquet(ref, bouquet)) != 0)
119 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
123 if ( bouquet && bouquet->m_bouquet_name.length() )
125 name = bouquet->m_bouquet_name;
132 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
137 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
139 DECLARE_REF(eStaticServiceDVBPVRInformation);
140 eServiceReference m_ref;
141 eDVBMetaParser m_parser;
143 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
144 RESULT getName(const eServiceReference &ref, std::string &name);
145 int getLength(const eServiceReference &ref);
147 int getInfo(const eServiceReference &ref, int w);
148 std::string getInfoString(const eServiceReference &ref,int w);
151 DEFINE_REF(eStaticServiceDVBPVRInformation);
153 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
156 m_parser.parseFile(ref.path);
159 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
161 ASSERT(ref == m_ref);
162 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
166 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
168 ASSERT(ref == m_ref);
172 if (tstools.openFile(ref.path.c_str()))
176 if (tstools.calcLen(len))
182 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
186 case iServiceInformation::sDescription:
187 return iServiceInformation::resIsString;
188 case iServiceInformation::sTimeCreate:
189 if (m_parser.m_time_create)
190 return m_parser.m_time_create;
192 return iServiceInformation::resNA;
194 return iServiceInformation::resNA;
198 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
202 case iServiceInformation::sDescription:
203 return m_parser.m_description;
209 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
211 DECLARE_REF(eDVBPVRServiceOfflineOperations);
212 eServiceReferenceDVB m_ref;
214 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
216 RESULT deleteFromDisk(int simulate);
217 RESULT getListOfFilenames(std::list<std::string> &);
220 DEFINE_REF(eDVBPVRServiceOfflineOperations);
222 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
226 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
232 std::list<std::string> res;
233 if (getListOfFilenames(res))
236 /* TODO: deferred removing.. */
237 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
239 eDebug("Removing %s...", i->c_str());
240 ::unlink(i->c_str());
247 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
250 res.push_back(m_ref.path);
251 res.push_back(m_ref.path + ".meta");
252 res.push_back(m_ref.path + ".ap");
253 res.push_back(m_ref.path + ".cuts");
254 res.push_back(m_ref.path + ".eit");
258 DEFINE_REF(eServiceFactoryDVB)
260 eServiceFactoryDVB::eServiceFactoryDVB()
262 ePtr<eServiceCenter> sc;
264 eServiceCenter::getPrivInstance(sc);
266 sc->addServiceFactory(eServiceFactoryDVB::id, this);
269 eServiceFactoryDVB::~eServiceFactoryDVB()
271 ePtr<eServiceCenter> sc;
273 eServiceCenter::getPrivInstance(sc);
275 sc->removeServiceFactory(eServiceFactoryDVB::id);
278 DEFINE_REF(eDVBServiceList);
280 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
284 eDVBServiceList::~eDVBServiceList()
288 RESULT eDVBServiceList::startQuery()
290 ePtr<iDVBChannelList> db;
291 ePtr<eDVBResourceManager> res;
294 if ((err = eDVBResourceManager::getInstance(res)) != 0)
296 eDebug("no resource manager");
299 if ((err = res->getChannelList(db)) != 0)
301 eDebug("no channel list");
305 ePtr<eDVBChannelQuery> q;
307 if (!m_parent.path.empty())
309 eDVBChannelQuery::compile(q, m_parent.path);
312 eDebug("compile query failed");
317 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
319 eDebug("startQuery failed");
326 RESULT eDVBServiceList::getContent(PyObject *list, bool sorted)
328 eServiceReferenceDVB ref;
330 if (!m_query || !list || !PyList_Check(list))
333 std::list<eServiceReferenceDVB> tmplist;
335 while (!m_query->getNextResult(ref))
336 tmplist.push_back(ref);
339 tmplist.sort(iListableServiceCompare(this));
341 for (std::list<eServiceReferenceDVB>::iterator it(tmplist.begin());
342 it != tmplist.end(); ++it)
344 PyObject *refobj = New_eServiceReference(*it);
345 PyList_Append(list, refobj);
351 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
353 eServiceReferenceDVB ref;
358 while (!m_query->getNextResult(ref))
362 list.sort(iListableServiceCompare(this));
367 RESULT eDVBServiceList::getNext(eServiceReference &ref)
372 return m_query->getNextResult((eServiceReferenceDVB&)ref);
375 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
377 return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
380 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
382 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
384 ePtr<iDVBChannelList> db;
385 ePtr<eDVBResourceManager> resm;
387 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
390 if (db->getBouquet(m_parent, m_bouquet) != 0)
401 RESULT eDVBServiceList::addService(eServiceReference &ref)
405 return m_bouquet->addService(ref);
408 RESULT eDVBServiceList::removeService(eServiceReference &ref)
412 return m_bouquet->removeService(ref);
415 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
419 return m_bouquet->moveService(ref, pos);
422 RESULT eDVBServiceList::flushChanges()
426 return m_bouquet->flushChanges();
429 RESULT eDVBServiceList::setListName(const std::string &name)
433 return m_bouquet->setListName(name);
436 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
438 ePtr<eDVBService> service;
439 int r = lookupService(service, ref);
442 // check resources...
443 ptr = new eDVBServicePlay(ref, service);
447 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
449 if (ref.path.empty())
451 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
460 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
462 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
463 if (list->startQuery())
473 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
475 /* is a listable service? */
476 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
478 if ( !ref.name.empty() ) // satellites or providers list
479 ptr = new eStaticServiceDVBInformation;
480 else // a dvb bouquet
481 ptr = new eStaticServiceDVBBouquetInformation;
483 else if (!ref.path.empty()) /* do we have a PVR service? */
484 ptr = new eStaticServiceDVBPVRInformation(ref);
485 else // normal dvb service
487 ePtr<eDVBService> service;
488 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
489 ptr = new eStaticServiceDVBInformation;
491 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
497 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
499 if (ref.path.empty())
505 ptr = new eDVBPVRServiceOfflineOperations(ref);
510 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
512 // TODO: handle the listing itself
513 // if (ref.... == -1) .. return "... bouquets ...";
514 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
516 ePtr<iDVBChannelList> db;
517 ePtr<eDVBResourceManager> res;
520 if ((err = eDVBResourceManager::getInstance(res)) != 0)
522 eDebug("no resource manager");
525 if ((err = res->getChannelList(db)) != 0)
527 eDebug("no channel list");
531 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
532 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
534 eDebug("getService failed!");
541 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
542 m_reference(ref), m_dvb_service(service), m_is_paused(0)
544 m_is_pvr = !ref.path.empty();
546 m_timeshift_enabled = m_timeshift_active = 0;
549 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
550 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
551 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
553 m_cuesheet_changed = 0;
559 eDVBServicePlay::~eDVBServicePlay()
563 void eDVBServicePlay::gotNewEvent()
567 ePtr<eServiceEvent> m_event_now, m_event_next;
568 getEvent(m_event_now, 0);
569 getEvent(m_event_next, 1);
572 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
574 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
576 m_event((iPlayableService*)this, evUpdatedEventInfo);
579 void eDVBServicePlay::serviceEvent(int event)
583 case eDVBServicePMTHandler::eventTuned:
585 ePtr<iDVBDemux> m_demux;
586 if (!m_service_handler.getDataDemux(m_demux))
588 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
589 int sid = ref.getParentServiceID().get();
591 sid = ref.getServiceID().get();
592 if ( ref.getParentTransportStreamID().get() &&
593 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
594 m_event_handler.startOther(m_demux, sid);
596 m_event_handler.start(m_demux, sid);
600 case eDVBServicePMTHandler::eventTuneFailed:
602 eDebug("DVB service failed to tune");
603 m_event((iPlayableService*)this, evTuneFailed);
606 case eDVBServicePMTHandler::eventNewProgramInfo:
608 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
609 if (m_timeshift_enabled)
610 updateTimeshiftPids();
611 if (!m_timeshift_active)
613 if (m_first_program_info && m_is_pvr)
615 m_first_program_info = 0;
618 m_event((iPlayableService*)this, evUpdatedInfo);
621 case eDVBServicePMTHandler::eventEOF:
622 m_event((iPlayableService*)this, evEOF);
624 case eDVBServicePMTHandler::eventSOF:
625 m_event((iPlayableService*)this, evSOF);
630 void eDVBServicePlay::serviceEventTimeshift(int event)
634 case eDVBServicePMTHandler::eventNewProgramInfo:
635 if (m_timeshift_active)
638 case eDVBServicePMTHandler::eventEOF:
644 RESULT eDVBServicePlay::start()
647 /* in pvr mode, we only want to use one demux. in tv mode, we're using
648 two (one for decoding, one for data source), as we must be prepared
649 to start recording from the data demux. */
650 m_cue = new eCueSheet();
651 m_first_program_info = 1;
652 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
653 r = m_service_handler.tune(service, m_is_pvr, m_cue);
656 std::string filename = service.path;
657 filename.erase(filename.length()-2, 2);
659 int fd = ::open( filename.c_str(), O_RDONLY );
663 int rd = ::read(fd, buf, 4096);
665 if ( rd > 12 /*EIT_LOOP_SIZE*/ )
668 ePtr<eServiceEvent> event = new eServiceEvent;
669 ePtr<eServiceEvent> empty;
670 event->parseFrom(&ev, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get());
671 m_event_handler.inject(event, 0);
672 m_event_handler.inject(empty, 1);
677 m_event(this, evStart);
678 m_event((iPlayableService*)this, evSeekableStatusChanged);
682 RESULT eDVBServicePlay::stop()
684 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
686 m_service_handler_timeshift.free();
687 m_service_handler.free();
689 if (m_is_pvr && m_cuesheet_changed)
695 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
697 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
701 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
703 /* note: we check for timeshift to be enabled,
704 not neccessary active. if you pause when timeshift
705 is not active, you should activate it when unpausing */
706 if ((!m_is_pvr) && (!m_timeshift_enabled))
716 RESULT eDVBServicePlay::setSlowMotion(int ratio)
719 return m_decoder->setSlowMotion(ratio);
724 RESULT eDVBServicePlay::setFastForward(int ratio)
726 int skipmode, ffratio;
732 } else if (ratio > 0)
740 } else // if (ratio < 0)
746 if (m_skipmode != skipmode)
748 eDebug("setting cue skipmode to %d", skipmode);
750 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
753 m_skipmode = skipmode;
758 return m_decoder->setFastForward(ffratio);
761 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
763 if (m_is_pvr || m_timeshift_enabled)
773 /* TODO: when timeshift is enabled but not active, this doesn't work. */
774 RESULT eDVBServicePlay::getLength(pts_t &len)
776 ePtr<iDVBPVRChannel> pvr_channel;
778 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
781 return pvr_channel->getLength(len);
784 RESULT eDVBServicePlay::pause()
786 if (!m_is_paused && m_decoder)
789 return m_decoder->freeze(0);
794 RESULT eDVBServicePlay::unpause()
796 if (m_is_paused && m_decoder)
799 return m_decoder->unfreeze();
804 RESULT eDVBServicePlay::seekTo(pts_t to)
806 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
811 ePtr<iDVBPVRChannel> pvr_channel;
813 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
819 m_cue->seekTo(0, to);
823 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
825 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
830 ePtr<iDVBPVRChannel> pvr_channel;
832 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
840 m_cue->seekTo(1, to);
844 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
846 ePtr<iDVBPVRChannel> pvr_channel;
851 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
856 /* if there is a decoder, use audio or video PTS */
859 r = m_decoder->getPTS(0, pos);
865 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
868 RESULT eDVBServicePlay::setTrickmode(int trick)
871 m_decoder->setTrickmode(trick);
875 RESULT eDVBServicePlay::isCurrentlySeekable()
877 return m_is_pvr || m_timeshift_active;
880 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
886 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
892 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
898 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
904 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
907 if (m_timeshift_enabled || !m_is_pvr)
909 if (!m_timeshift_enabled)
911 /* we need enough diskspace */
913 if (statfs(TSPATH "/.", &fs) < 0)
915 eDebug("statfs failed!");
919 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
921 eDebug("not enough diskspace for timeshift! (less than 1GB)");
931 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
942 RESULT eDVBServicePlay::getName(std::string &name)
946 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
947 return i->getName(m_reference, name);
951 m_dvb_service->getName(m_reference, name);
955 else if (!m_reference.name.empty())
956 eStaticServiceDVBInformation().getName(m_reference, name);
958 name = "DVB service";
962 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
964 return m_event_handler.getEvent(evt, nownext);
967 int eDVBServicePlay::getInfo(int w)
969 eDVBServicePMTHandler::program program;
971 if (m_service_handler.getProgramInfo(program))
977 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
979 ePtr<eServiceEvent> evt;
980 if (!m_event_handler.getEvent(evt, 0))
982 ePtr<eComponentData> data;
983 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
985 if ( data->getStreamContent() == 1 )
987 switch(data->getComponentType())
990 case 1: // 4:3 SD PAL
992 case 3: // 16:9 SD PAL
993 case 4: // > 16:9 PAL
994 case 5: // 4:3 SD NTSC
996 case 7: // 16:9 SD NTSC
997 case 8: // > 16:9 NTSC
1000 case 9: // 4:3 HD PAL
1002 case 0xB: // 16:9 HD PAL
1003 case 0xC: // > 16:9 HD PAL
1004 case 0xD: // 4:3 HD NTSC
1006 case 0xF: // 16:9 HD NTSC
1007 case 0x10: // > 16:9 HD PAL
1008 return data->getComponentType();
1015 case sIsCrypted: return program.isCrypted;
1016 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1017 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
1018 case sPCRPID: return program.pcrPid;
1019 case sPMTPID: return program.pmtPid;
1020 case sTXTPID: return program.textPid;
1021 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1022 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1023 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1024 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1025 case sProvider: if (!m_dvb_service) return -1; return -2;
1031 std::string eDVBServicePlay::getInfoString(int w)
1036 if (!m_dvb_service) return "";
1037 return m_dvb_service->m_provider_name;
1043 int eDVBServicePlay::getNumberOfTracks()
1045 eDVBServicePMTHandler::program program;
1046 if (m_service_handler.getProgramInfo(program))
1048 return program.audioStreams.size();
1051 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1053 int ret = selectAudioStream(i);
1055 if (m_decoder->start())
1061 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1063 eDVBServicePMTHandler::program program;
1065 if (m_service_handler.getProgramInfo(program))
1068 if (i >= program.audioStreams.size())
1071 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1072 info.m_description = "MPEG";
1073 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1074 info.m_description = "AC3";
1075 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1076 info.m_description = "DTS";
1078 info.m_description = "???";
1080 if (program.audioStreams[i].component_tag != -1)
1082 ePtr<eServiceEvent> evt;
1083 if (!m_event_handler.getEvent(evt, 0))
1085 ePtr<eComponentData> data;
1086 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1087 info.m_language = data->getText();
1091 if (info.m_language.empty())
1092 info.m_language = program.audioStreams[i].language_code;
1097 int eDVBServicePlay::selectAudioStream(int i)
1099 eDVBServicePMTHandler::program program;
1101 if (m_service_handler.getProgramInfo(program))
1104 if ((unsigned int)i >= program.audioStreams.size())
1110 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1113 if (m_dvb_service && !m_is_pvr)
1115 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1117 m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
1118 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1121 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1122 m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
1126 m_current_audio_stream = i;
1131 int eDVBServicePlay::getFrontendInfo(int w)
1135 eUsePtr<iDVBChannel> channel;
1136 if(m_service_handler.getChannel(channel))
1138 ePtr<iDVBFrontend> fe;
1139 if(channel->getFrontend(fe))
1141 return fe->readFrontendData(w);
1144 int eDVBServicePlay::getNumberOfSubservices()
1146 ePtr<eServiceEvent> evt;
1147 if (!m_event_handler.getEvent(evt, 0))
1148 return evt->getNumOfLinkageServices();
1152 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1154 ePtr<eServiceEvent> evt;
1155 if (!m_event_handler.getEvent(evt, 0))
1157 if (!evt->getLinkageService(sub, m_reference, n))
1160 sub.type=eServiceReference::idInvalid;
1164 RESULT eDVBServicePlay::startTimeshift()
1166 ePtr<iDVBDemux> demux;
1168 eDebug("Start timeshift!");
1170 if (m_timeshift_enabled)
1173 /* start recording with the data demux. */
1174 if (m_service_handler.getDataDemux(demux))
1177 demux->createTSRecorder(m_record);
1181 char templ[]=TSPATH "/timeshift.XXXXXX";
1182 m_timeshift_fd = mkstemp(templ);
1183 m_timeshift_file = templ;
1185 eDebug("recording to %s", templ);
1187 if (m_timeshift_fd < 0)
1193 m_record->setTargetFD(m_timeshift_fd);
1195 m_timeshift_enabled = 1;
1197 updateTimeshiftPids();
1203 RESULT eDVBServicePlay::stopTimeshift()
1205 if (!m_timeshift_enabled)
1210 m_timeshift_enabled = 0;
1215 close(m_timeshift_fd);
1216 eDebug("remove timeshift file");
1217 remove(m_timeshift_file.c_str());
1222 int eDVBServicePlay::isTimeshiftActive()
1224 return m_timeshift_enabled && m_timeshift_active;
1227 RESULT eDVBServicePlay::activateTimeshift()
1229 if (!m_timeshift_enabled)
1232 if (!m_timeshift_active)
1234 switchToTimeshift();
1241 PyObject *eDVBServicePlay::getCutList()
1243 PyObject *list = PyList_New(0);
1245 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1247 PyObject *tuple = PyTuple_New(2);
1248 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1249 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1250 PyList_Append(list, tuple);
1257 void eDVBServicePlay::setCutList(PyObject *list)
1259 if (!PyList_Check(list))
1261 int size = PyList_Size(list);
1264 m_cue_entries.clear();
1266 for (i=0; i<size; ++i)
1268 PyObject *tuple = PyList_GetItem(list, i);
1269 if (!PyTuple_Check(tuple))
1271 eDebug("non-tuple in cutlist");
1274 if (PyTuple_Size(tuple) != 2)
1276 eDebug("cutlist entries need to be a 2-tuple");
1279 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1280 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1282 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1285 pts_t pts = PyLong_AsLongLong(ppts);
1286 int type = PyInt_AsLong(ptype);
1287 m_cue_entries.insert(cueEntry(pts, type));
1288 eDebug("adding %08llx, %d", pts, type);
1290 m_cuesheet_changed = 1;
1292 m_event((iPlayableService*)this, evCuesheetChanged);
1295 void eDVBServicePlay::updateTimeshiftPids()
1300 eDVBServicePMTHandler::program program;
1301 if (m_service_handler.getProgramInfo(program))
1305 std::set<int> pids_to_record;
1306 pids_to_record.insert(0); // PAT
1307 if (program.pmtPid != -1)
1308 pids_to_record.insert(program.pmtPid); // PMT
1310 if (program.textPid != -1)
1311 pids_to_record.insert(program.textPid); // Videotext
1313 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1314 i(program.videoStreams.begin());
1315 i != program.videoStreams.end(); ++i)
1316 pids_to_record.insert(i->pid);
1318 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1319 i(program.audioStreams.begin());
1320 i != program.audioStreams.end(); ++i)
1321 pids_to_record.insert(i->pid);
1323 std::set<int> new_pids, obsolete_pids;
1325 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1326 m_pids_active.begin(), m_pids_active.end(),
1327 std::inserter(new_pids, new_pids.begin()));
1329 std::set_difference(
1330 m_pids_active.begin(), m_pids_active.end(),
1331 pids_to_record.begin(), pids_to_record.end(),
1332 std::inserter(new_pids, new_pids.begin())
1335 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1336 m_record->addPID(*i);
1338 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1339 m_record->removePID(*i);
1343 void eDVBServicePlay::switchToLive()
1345 if (!m_timeshift_active)
1350 /* free the timeshift service handler, we need the resources */
1351 m_service_handler_timeshift.free();
1352 m_timeshift_active = 0;
1354 m_event((iPlayableService*)this, evSeekableStatusChanged);
1359 void eDVBServicePlay::switchToTimeshift()
1361 if (m_timeshift_active)
1367 m_timeshift_active = 1;
1369 m_event((iPlayableService*)this, evSeekableStatusChanged);
1371 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1372 r.path = m_timeshift_file;
1374 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1377 void eDVBServicePlay::updateDecoder()
1379 int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
1380 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1382 eDVBServicePMTHandler::program program;
1383 if (h.getProgramInfo(program))
1384 eDebug("getting program info failed.");
1387 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1388 if (!program.videoStreams.empty())
1390 eDebugNoNewLine(" (");
1391 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1392 i(program.videoStreams.begin());
1393 i != program.videoStreams.end(); ++i)
1397 if (i != program.videoStreams.begin())
1398 eDebugNoNewLine(", ");
1399 eDebugNoNewLine("%04x", i->pid);
1401 eDebugNoNewLine(")");
1403 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1404 if (!program.audioStreams.empty())
1406 eDebugNoNewLine(" (");
1407 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1408 i(program.audioStreams.begin());
1409 i != program.audioStreams.end(); ++i)
1416 if (i != program.audioStreams.begin())
1417 eDebugNoNewLine(", ");
1418 eDebugNoNewLine("%04x", i->pid);
1420 eDebugNoNewLine(")");
1422 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1423 pcrpid = program.pcrPid;
1424 eDebug(", and the text pid is %04x", program.textPid);
1425 tpid = program.textPid;
1430 h.getDecodeDemux(m_decode_demux);
1432 m_decode_demux->getMPEGDecoder(m_decoder);
1434 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1439 m_decoder->setVideoPID(vpid);
1440 m_current_audio_stream = 0;
1441 m_decoder->setAudioPID(apid, apidtype);
1442 if (!(m_is_pvr || m_timeshift_active))
1443 m_decoder->setSyncPCR(pcrpid);
1445 m_decoder->setSyncPCR(-1);
1446 m_decoder->setTextPID(tpid);
1448 // how we can do this better?
1449 // update cache pid when the user changed the audio track or video track
1450 // TODO handling of difference audio types.. default audio types..
1452 /* don't worry about non-existing services, nor pvr services */
1453 if (m_dvb_service && !m_is_pvr)
1455 if (apidtype == eDVBAudio::aMPEG)
1457 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
1458 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1462 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1463 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
1465 m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
1466 m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
1467 m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
1472 void eDVBServicePlay::loadCuesheet()
1474 std::string filename = m_reference.path + ".cuts";
1476 m_cue_entries.clear();
1478 FILE *f = fopen(filename.c_str(), "rb");
1482 eDebug("loading cuts..");
1485 unsigned long long where;
1488 if (!fread(&where, sizeof(where), 1, f))
1490 if (!fread(&what, sizeof(what), 1, f))
1493 #if BYTE_ORDER == LITTLE_ENDIAN
1494 where = bswap_64(where);
1501 m_cue_entries.insert(cueEntry(where, what));
1504 eDebug("%d entries", m_cue_entries.size());
1506 eDebug("cutfile not found!");
1508 m_cuesheet_changed = 0;
1509 m_event((iPlayableService*)this, evCuesheetChanged);
1512 void eDVBServicePlay::saveCuesheet()
1514 std::string filename = m_reference.path + ".cuts";
1516 FILE *f = fopen(filename.c_str(), "wb");
1520 unsigned long long where;
1523 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1525 #if BYTE_ORDER == BIG_ENDIAN
1528 where = bswap_64(i->where);
1530 what = htonl(i->what);
1531 fwrite(&where, sizeof(where), 1, f);
1532 fwrite(&what, sizeof(what), 1, f);
1538 m_cuesheet_changed = 0;
1541 DEFINE_REF(eDVBServicePlay)
1543 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");