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)
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;
651 eDVBServicePlay::~eDVBServicePlay()
653 delete m_subtitle_widget;
656 void eDVBServicePlay::gotNewEvent()
660 ePtr<eServiceEvent> m_event_now, m_event_next;
661 getEvent(m_event_now, 0);
662 getEvent(m_event_next, 1);
665 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
667 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
669 m_event((iPlayableService*)this, evUpdatedEventInfo);
672 void eDVBServicePlay::serviceEvent(int event)
676 case eDVBServicePMTHandler::eventTuned:
678 ePtr<iDVBDemux> m_demux;
679 if (!m_service_handler.getDataDemux(m_demux))
681 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
682 int sid = ref.getParentServiceID().get();
684 sid = ref.getServiceID().get();
685 if ( ref.getParentTransportStreamID().get() &&
686 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
687 m_event_handler.startOther(m_demux, sid);
689 m_event_handler.start(m_demux, sid);
693 case eDVBServicePMTHandler::eventTuneFailed:
695 eDebug("DVB service failed to tune");
696 m_event((iPlayableService*)this, evTuneFailed);
699 case eDVBServicePMTHandler::eventNewProgramInfo:
701 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
702 if (m_timeshift_enabled)
703 updateTimeshiftPids();
704 if (!m_timeshift_active)
706 if (m_first_program_info && m_is_pvr)
708 m_first_program_info = 0;
711 m_event((iPlayableService*)this, evUpdatedInfo);
714 case eDVBServicePMTHandler::eventEOF:
715 m_event((iPlayableService*)this, evEOF);
717 case eDVBServicePMTHandler::eventSOF:
718 m_event((iPlayableService*)this, evSOF);
723 void eDVBServicePlay::serviceEventTimeshift(int event)
727 case eDVBServicePMTHandler::eventNewProgramInfo:
728 if (m_timeshift_active)
731 case eDVBServicePMTHandler::eventSOF:
732 m_event((iPlayableService*)this, evSOF);
734 case eDVBServicePMTHandler::eventEOF:
740 RESULT eDVBServicePlay::start()
743 /* in pvr mode, we only want to use one demux. in tv mode, we're using
744 two (one for decoding, one for data source), as we must be prepared
745 to start recording from the data demux. */
747 m_cue = new eCueSheet();
749 m_first_program_info = 1;
750 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
751 r = m_service_handler.tune(service, m_is_pvr, m_cue);
753 /* inject EIT if there is a stored one */
756 std::string filename = service.path;
757 filename.erase(filename.length()-2, 2);
759 int fd = ::open( filename.c_str(), O_RDONLY );
763 int rd = ::read(fd, buf, 4096);
765 if ( rd > 12 /*EIT_LOOP_SIZE*/ )
768 ePtr<eServiceEvent> event = new eServiceEvent;
769 ePtr<eServiceEvent> empty;
770 event->parseFrom(&ev, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get());
771 m_event_handler.inject(event, 0);
772 m_event_handler.inject(empty, 1);
781 m_event(this, evStart);
782 m_event((iPlayableService*)this, evSeekableStatusChanged);
786 RESULT eDVBServicePlay::stop()
788 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
790 m_service_handler_timeshift.free();
791 m_service_handler.free();
793 if (m_is_pvr && m_cuesheet_changed)
799 RESULT eDVBServicePlay::setTarget(int target)
801 m_is_primary = !target;
805 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
807 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
811 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
813 /* note: we check for timeshift to be enabled,
814 not neccessary active. if you pause when timeshift
815 is not active, you should activate it when unpausing */
816 if ((!m_is_pvr) && (!m_timeshift_enabled))
826 RESULT eDVBServicePlay::setSlowMotion(int ratio)
829 return m_decoder->setSlowMotion(ratio);
834 RESULT eDVBServicePlay::setFastForward(int ratio)
836 int skipmode, ffratio;
842 } else if (ratio > 0)
850 } else // if (ratio < 0)
856 if (m_skipmode != skipmode)
858 eDebug("setting cue skipmode to %d", skipmode);
860 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
863 m_skipmode = skipmode;
868 return m_decoder->setFastForward(ffratio);
871 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
873 if (m_is_pvr || m_timeshift_enabled)
883 /* TODO: when timeshift is enabled but not active, this doesn't work. */
884 RESULT eDVBServicePlay::getLength(pts_t &len)
886 ePtr<iDVBPVRChannel> pvr_channel;
888 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
891 return pvr_channel->getLength(len);
894 RESULT eDVBServicePlay::pause()
896 if (!m_is_paused && m_decoder)
899 return m_decoder->freeze(0);
904 RESULT eDVBServicePlay::unpause()
906 if (m_is_paused && m_decoder)
909 return m_decoder->unfreeze();
914 RESULT eDVBServicePlay::seekTo(pts_t to)
916 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
921 ePtr<iDVBPVRChannel> pvr_channel;
923 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
929 m_cue->seekTo(0, to);
933 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
935 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
940 ePtr<iDVBPVRChannel> pvr_channel;
942 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
947 /* HACK until we have skip-AP api */
948 if ((to > 0) && (to < 100))
956 m_cue->seekTo(mode, to);
960 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
962 ePtr<iDVBPVRChannel> pvr_channel;
967 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
972 /* if there is a decoder, use audio or video PTS */
975 r = m_decoder->getPTS(0, pos);
981 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
984 RESULT eDVBServicePlay::setTrickmode(int trick)
987 m_decoder->setTrickmode(trick);
991 RESULT eDVBServicePlay::isCurrentlySeekable()
993 return m_is_pvr || m_timeshift_active;
996 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1002 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1008 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1014 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1020 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1026 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1029 if (m_timeshift_enabled || !m_is_pvr)
1031 if (!m_timeshift_enabled)
1033 /* we need enough diskspace */
1035 if (statfs(TSPATH "/.", &fs) < 0)
1037 eDebug("statfs failed!");
1041 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1043 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1053 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1064 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1070 RESULT eDVBServicePlay::getName(std::string &name)
1074 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1075 return i->getName(m_reference, name);
1079 m_dvb_service->getName(m_reference, name);
1083 else if (!m_reference.name.empty())
1084 eStaticServiceDVBInformation().getName(m_reference, name);
1086 name = "DVB service";
1090 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1092 return m_event_handler.getEvent(evt, nownext);
1095 int eDVBServicePlay::getInfo(int w)
1097 eDVBServicePMTHandler::program program;
1100 return resIsPyObject;
1102 if (m_service_handler.getProgramInfo(program))
1108 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1110 ePtr<eServiceEvent> evt;
1111 if (!m_event_handler.getEvent(evt, 0))
1113 ePtr<eComponentData> data;
1114 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1116 if ( data->getStreamContent() == 1 )
1118 switch(data->getComponentType())
1121 case 1: // 4:3 SD PAL
1123 case 3: // 16:9 SD PAL
1124 case 4: // > 16:9 PAL
1125 case 5: // 4:3 SD NTSC
1127 case 7: // 16:9 SD NTSC
1128 case 8: // > 16:9 NTSC
1131 case 9: // 4:3 HD PAL
1133 case 0xB: // 16:9 HD PAL
1134 case 0xC: // > 16:9 HD PAL
1135 case 0xD: // 4:3 HD NTSC
1137 case 0xF: // 16:9 HD NTSC
1138 case 0x10: // > 16:9 HD PAL
1139 return data->getComponentType();
1146 case sIsCrypted: return program.isCrypted();
1147 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1148 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1149 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
1150 case sPCRPID: return program.pcrPid;
1151 case sPMTPID: return program.pmtPid;
1152 case sTXTPID: return program.textPid;
1153 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1154 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1155 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1156 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1157 case sProvider: if (!m_dvb_service) return -1; return -2;
1163 std::string eDVBServicePlay::getInfoString(int w)
1168 if (!m_dvb_service) return "";
1169 return m_dvb_service->m_provider_name;
1173 return iServiceInformation::getInfoString(w);
1176 PyObject *eDVBServicePlay::getInfoObject(int w)
1181 return m_service_handler.getCaIds();
1185 return iServiceInformation::getInfoObject(w);
1188 int eDVBServicePlay::getNumberOfTracks()
1190 eDVBServicePMTHandler::program program;
1191 if (m_service_handler.getProgramInfo(program))
1193 return program.audioStreams.size();
1196 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1198 int ret = selectAudioStream(i);
1200 if (m_decoder->start())
1206 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1208 eDVBServicePMTHandler::program program;
1210 if (m_service_handler.getProgramInfo(program))
1213 if (i >= program.audioStreams.size())
1216 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1217 info.m_description = "MPEG";
1218 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1219 info.m_description = "AC3";
1220 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1221 info.m_description = "AAC";
1222 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1223 info.m_description = "DTS";
1225 info.m_description = "???";
1227 if (program.audioStreams[i].component_tag != -1)
1229 ePtr<eServiceEvent> evt;
1230 if (!m_event_handler.getEvent(evt, 0))
1232 ePtr<eComponentData> data;
1233 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1234 info.m_language = data->getText();
1238 if (info.m_language.empty())
1239 info.m_language = program.audioStreams[i].language_code;
1244 int eDVBServicePlay::selectAudioStream(int i)
1246 eDVBServicePMTHandler::program program;
1248 if (m_service_handler.getProgramInfo(program))
1251 if ((unsigned int)i >= program.audioStreams.size())
1257 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1260 if (m_dvb_service && !m_is_pvr)
1262 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1264 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1265 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1268 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1269 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1273 m_current_audio_stream = i;
1278 int eDVBServicePlay::getCurrentChannel()
1280 int curChannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1281 return curChannel == -1 ? STEREO : curChannel;
1284 RESULT eDVBServicePlay::selectChannel(int i)
1286 if (i < iAudioChannelSelection::LEFT || i > iAudioChannelSelection::RIGHT)
1288 if (m_dvb_service->getCacheEntry(eDVBService::cACHANNEL) != i)
1290 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1292 m_decoder->setAudioChannel(i);
1297 int eDVBServiceBase::getFrontendInfo(int w)
1299 eUsePtr<iDVBChannel> channel;
1300 if(m_service_handler.getChannel(channel))
1302 ePtr<iDVBFrontend> fe;
1303 if(channel->getFrontend(fe))
1305 return fe->readFrontendData(w);
1308 PyObject *eDVBServiceBase::getFrontendData(bool original)
1312 eUsePtr<iDVBChannel> channel;
1313 if(!m_service_handler.getChannel(channel))
1315 ePtr<iDVBFrontend> fe;
1316 if(!channel->getFrontend(fe))
1318 ret = fe->readTransponderData(original);
1321 ePtr<iDVBFrontendParameters> feparm;
1322 channel->getCurrentFrontendParameters(feparm);
1325 eDVBFrontendParametersSatellite osat;
1326 if (!feparm->getDVBS(osat))
1328 void PutToDict(PyObject *, const char*, long);
1329 void PutToDict(PyObject *, const char*, const char*);
1330 PutToDict(ret, "orbital_position", osat.orbital_position);
1331 const char *tmp = "UNKNOWN";
1332 switch(osat.polarisation)
1334 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1335 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1336 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1337 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1340 PutToDict(ret, "polarization", tmp);
1354 int eDVBServicePlay::getNumberOfSubservices()
1356 ePtr<eServiceEvent> evt;
1357 if (!m_event_handler.getEvent(evt, 0))
1358 return evt->getNumOfLinkageServices();
1362 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1364 ePtr<eServiceEvent> evt;
1365 if (!m_event_handler.getEvent(evt, 0))
1367 if (!evt->getLinkageService(sub, m_reference, n))
1370 sub.type=eServiceReference::idInvalid;
1374 RESULT eDVBServicePlay::startTimeshift()
1376 ePtr<iDVBDemux> demux;
1378 eDebug("Start timeshift!");
1380 if (m_timeshift_enabled)
1383 /* start recording with the data demux. */
1384 if (m_service_handler.getDataDemux(demux))
1387 demux->createTSRecorder(m_record);
1391 char templ[]=TSPATH "/timeshift.XXXXXX";
1392 m_timeshift_fd = mkstemp(templ);
1393 m_timeshift_file = templ;
1395 eDebug("recording to %s", templ);
1397 if (m_timeshift_fd < 0)
1403 m_record->setTargetFD(m_timeshift_fd);
1405 m_timeshift_enabled = 1;
1407 updateTimeshiftPids();
1413 RESULT eDVBServicePlay::stopTimeshift()
1415 if (!m_timeshift_enabled)
1420 m_timeshift_enabled = 0;
1425 close(m_timeshift_fd);
1426 eDebug("remove timeshift file");
1427 remove(m_timeshift_file.c_str());
1432 int eDVBServicePlay::isTimeshiftActive()
1434 return m_timeshift_enabled && m_timeshift_active;
1437 RESULT eDVBServicePlay::activateTimeshift()
1439 if (!m_timeshift_enabled)
1442 if (!m_timeshift_active)
1444 switchToTimeshift();
1451 PyObject *eDVBServicePlay::getCutList()
1453 PyObject *list = PyList_New(0);
1455 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1457 PyObject *tuple = PyTuple_New(2);
1458 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1459 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1460 PyList_Append(list, tuple);
1467 void eDVBServicePlay::setCutList(PyObject *list)
1469 if (!PyList_Check(list))
1471 int size = PyList_Size(list);
1474 m_cue_entries.clear();
1476 for (i=0; i<size; ++i)
1478 PyObject *tuple = PyList_GetItem(list, i);
1479 if (!PyTuple_Check(tuple))
1481 eDebug("non-tuple in cutlist");
1484 if (PyTuple_Size(tuple) != 2)
1486 eDebug("cutlist entries need to be a 2-tuple");
1489 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1490 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1492 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1495 pts_t pts = PyLong_AsLongLong(ppts);
1496 int type = PyInt_AsLong(ptype);
1497 m_cue_entries.insert(cueEntry(pts, type));
1498 eDebug("adding %08llx, %d", pts, type);
1500 m_cuesheet_changed = 1;
1502 cutlistToCuesheet();
1503 m_event((iPlayableService*)this, evCuesheetChanged);
1506 void eDVBServicePlay::setCutListEnable(int enable)
1508 m_cutlist_enabled = enable;
1509 cutlistToCuesheet();
1512 void eDVBServicePlay::updateTimeshiftPids()
1517 eDVBServicePMTHandler::program program;
1518 if (m_service_handler.getProgramInfo(program))
1522 std::set<int> pids_to_record;
1523 pids_to_record.insert(0); // PAT
1524 if (program.pmtPid != -1)
1525 pids_to_record.insert(program.pmtPid); // PMT
1527 if (program.textPid != -1)
1528 pids_to_record.insert(program.textPid); // Videotext
1530 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1531 i(program.videoStreams.begin());
1532 i != program.videoStreams.end(); ++i)
1533 pids_to_record.insert(i->pid);
1535 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1536 i(program.audioStreams.begin());
1537 i != program.audioStreams.end(); ++i)
1538 pids_to_record.insert(i->pid);
1540 std::set<int> new_pids, obsolete_pids;
1542 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1543 m_pids_active.begin(), m_pids_active.end(),
1544 std::inserter(new_pids, new_pids.begin()));
1546 std::set_difference(
1547 m_pids_active.begin(), m_pids_active.end(),
1548 pids_to_record.begin(), pids_to_record.end(),
1549 std::inserter(new_pids, new_pids.begin())
1552 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1553 m_record->addPID(*i);
1555 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1556 m_record->removePID(*i);
1560 void eDVBServicePlay::switchToLive()
1562 if (!m_timeshift_active)
1568 m_teletext_parser = 0;
1570 /* free the timeshift service handler, we need the resources */
1571 m_service_handler_timeshift.free();
1572 m_timeshift_active = 0;
1574 m_event((iPlayableService*)this, evSeekableStatusChanged);
1579 void eDVBServicePlay::switchToTimeshift()
1581 if (m_timeshift_active)
1586 m_teletext_parser = 0;
1588 m_timeshift_active = 1;
1590 m_event((iPlayableService*)this, evSeekableStatusChanged);
1592 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1593 r.path = m_timeshift_file;
1595 m_cue = new eCueSheet();
1596 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1597 updateDecoder(); /* mainly to switch off PCR */
1600 void eDVBServicePlay::updateDecoder()
1602 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1;
1603 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1605 bool defaultac3=false;
1606 std::string default_ac3;
1608 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1609 defaultac3 = default_ac3 == "enable";
1611 eDVBServicePMTHandler::program program;
1612 if (h.getProgramInfo(program))
1613 eDebug("getting program info failed.");
1616 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1617 if (!program.videoStreams.empty())
1619 eDebugNoNewLine(" (");
1620 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1621 i(program.videoStreams.begin());
1622 i != program.videoStreams.end(); ++i)
1629 if (i != program.videoStreams.begin())
1630 eDebugNoNewLine(", ");
1631 eDebugNoNewLine("%04x", i->pid);
1633 eDebugNoNewLine(")");
1635 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1636 if (!program.audioStreams.empty())
1638 eDebugNoNewLine(" (");
1639 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1640 i(program.audioStreams.begin());
1641 i != program.audioStreams.end(); ++i)
1643 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1645 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1651 if (i != program.audioStreams.begin())
1652 eDebugNoNewLine(", ");
1653 eDebugNoNewLine("%04x", i->pid);
1655 eDebugNoNewLine(")");
1657 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1658 pcrpid = program.pcrPid;
1659 eDebug(", and the text pid is %04x", program.textPid);
1660 tpid = program.textPid;
1661 achannel = program.audioChannel;
1666 h.getDecodeDemux(m_decode_demux);
1668 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1670 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1671 #ifdef INTERNAL_TELETEXT
1672 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1673 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1679 m_decoder->setVideoPID(vpid, vpidtype);
1680 m_current_audio_stream = 0;
1681 m_decoder->setAudioPID(apid, apidtype);
1682 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1683 m_decoder->setSyncPCR(pcrpid);
1685 m_decoder->setSyncPCR(-1);
1686 #ifndef INTERNAL_TELETEXT
1687 m_decoder->setTextPID(tpid);
1689 if (m_teletext_parser)
1690 m_teletext_parser->start(tpid);
1694 m_decoder->setTrickmode(1);
1698 m_decoder->setAudioChannel(achannel);
1700 // how we can do this better?
1701 // update cache pid when the user changed the audio track or video track
1702 // TODO handling of difference audio types.. default audio types..
1704 /* don't worry about non-existing services, nor pvr services */
1705 if (m_dvb_service && !m_is_pvr)
1707 if (apidtype == eDVBAudio::aMPEG)
1709 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1710 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1714 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1715 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1717 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1718 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1719 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1720 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1725 void eDVBServicePlay::loadCuesheet()
1727 std::string filename = m_reference.path + ".cuts";
1729 m_cue_entries.clear();
1731 FILE *f = fopen(filename.c_str(), "rb");
1735 eDebug("loading cuts..");
1738 unsigned long long where;
1741 if (!fread(&where, sizeof(where), 1, f))
1743 if (!fread(&what, sizeof(what), 1, f))
1746 #if BYTE_ORDER == LITTLE_ENDIAN
1747 where = bswap_64(where);
1754 m_cue_entries.insert(cueEntry(where, what));
1757 eDebug("%d entries", m_cue_entries.size());
1759 eDebug("cutfile not found!");
1761 m_cuesheet_changed = 0;
1762 cutlistToCuesheet();
1763 m_event((iPlayableService*)this, evCuesheetChanged);
1766 void eDVBServicePlay::saveCuesheet()
1768 std::string filename = m_reference.path + ".cuts";
1770 FILE *f = fopen(filename.c_str(), "wb");
1774 unsigned long long where;
1777 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1779 #if BYTE_ORDER == BIG_ENDIAN
1782 where = bswap_64(i->where);
1784 what = htonl(i->what);
1785 fwrite(&where, sizeof(where), 1, f);
1786 fwrite(&what, sizeof(what), 1, f);
1792 m_cuesheet_changed = 0;
1795 void eDVBServicePlay::cutlistToCuesheet()
1799 eDebug("no cue sheet");
1804 if (!m_cutlist_enabled)
1806 m_cue->commitSpans();
1807 eDebug("cutlists where disabled");
1811 pts_t in = 0, out = 0, length = 0;
1815 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1819 if (i == m_cue_entries.end())
1822 if (i->what == 0) /* in */
1826 } else if (i->what == 1) /* out */
1836 m_cue->addSourceSpan(in, out);
1840 if (i == m_cue_entries.end())
1843 m_cue->commitSpans();
1846 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1848 if (m_subtitle_widget)
1849 disableSubtitles(parent);
1851 m_subtitle_widget = new eSubtitleWidget(parent);
1852 m_subtitle_widget->resize(parent->size()); /* full size */
1857 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
1859 delete m_subtitle_widget;
1860 m_subtitle_widget = 0;
1864 PyObject *eDVBServicePlay::getSubtitleList()
1866 if (!m_teletext_parser)
1872 PyObject *l = PyList_New(0);
1874 for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
1876 PyObject *tuple = PyTuple_New(2);
1878 sprintf(desc, "Page %x", *i);
1879 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
1880 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
1881 PyList_Append(l, tuple);
1887 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
1889 eDebug("new subtitle page received!");
1890 if (m_subtitle_widget)
1891 m_subtitle_widget->addPage(page);
1894 DEFINE_REF(eDVBServicePlay)
1896 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");