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/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/base/nconfig.h> // access to python config
10 #include <lib/dvb/dvb.h>
11 #include <lib/dvb/db.h>
12 #include <lib/dvb/decoder.h>
14 #include <lib/components/file_eraser.h>
15 #include <lib/service/servicedvbrecord.h>
16 #include <lib/service/event.h>
17 #include <lib/dvb/metaparser.h>
18 #include <lib/dvb/tstools.h>
19 #include <lib/python/python.h>
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 #define TSPATH "/media/hdd"
36 class eStaticServiceDVBInformation: public iStaticServiceInformation
38 DECLARE_REF(eStaticServiceDVBInformation);
40 RESULT getName(const eServiceReference &ref, std::string &name);
41 int getLength(const eServiceReference &ref);
42 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
43 PyObject *getInfoObject(const eServiceReference &ref, int);
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))
68 name=buildShortName(name) + " - ";
81 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
86 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
88 ePtr<eDVBResourceManager> res_mgr;
89 if ( eDVBResourceManager::getInstance( res_mgr ) )
90 eDebug("isPlayable... no res manager!!");
93 eDVBChannelID chid, chid_ignore;
94 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
95 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
96 return res_mgr->canAllocateChannel(chid, chid_ignore);
101 static void PutToDict(ePyObject &dict, const char*key, long value)
103 ePyObject item = PyString_FromFormat("%d", value);
106 if (PyDict_SetItemString(dict, key, item))
107 eDebug("put %s to dict failed", key);
111 eDebug("could not create PyObject for %s", key);
114 extern void PutToDict(ePyObject &dict, const char*key, const char *value);
116 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
119 PutToDict(dict, "type", "Satellite");
120 PutToDict(dict, "frequency", feparm.frequency);
121 PutToDict(dict, "symbolrate", feparm.symbol_rate);
122 PutToDict(dict, "orbital position", feparm.orbital_position);
123 switch (feparm.inversion)
125 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
126 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
128 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
130 PutToDict(dict, "inversion", tmp);
133 case eDVBFrontendParametersSatellite::FEC::fNone: tmp="NONE"; break;
134 case eDVBFrontendParametersSatellite::FEC::f1_2: tmp="1/2"; break;
135 case eDVBFrontendParametersSatellite::FEC::f2_3: tmp="2/3"; break;
136 case eDVBFrontendParametersSatellite::FEC::f3_4: tmp="3/4"; break;
137 case eDVBFrontendParametersSatellite::FEC::f5_6: tmp="5/6"; break;
138 case eDVBFrontendParametersSatellite::FEC::f7_8: tmp="7/8"; break;
139 case eDVBFrontendParametersSatellite::FEC::f3_5: tmp="3/5"; break;
140 case eDVBFrontendParametersSatellite::FEC::f4_5: tmp="4/5"; break;
141 case eDVBFrontendParametersSatellite::FEC::f8_9: tmp="8/9"; break;
142 case eDVBFrontendParametersSatellite::FEC::f9_10: tmp="9/10"; break;
144 case eDVBFrontendParametersSatellite::FEC::fAuto: tmp="AUTO"; break;
146 PutToDict(dict, "fec inner", tmp);
147 switch (feparm.modulation)
149 case eDVBFrontendParametersSatellite::Modulation::Auto: tmp="AUTO"; break;
150 case eDVBFrontendParametersSatellite::Modulation::QPSK: tmp="QPSK"; break;
151 case eDVBFrontendParametersSatellite::Modulation::M8PSK: tmp="8PSK"; break;
152 case eDVBFrontendParametersSatellite::Modulation::QAM_16: tmp="QAM16"; break;
154 PutToDict(dict, "modulation", tmp);
155 switch(feparm.polarisation)
157 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
158 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
159 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR LEFT"; break;
161 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR RIGHT"; break;
163 PutToDict(dict, "polarization", tmp);
164 switch(feparm.system)
167 case eDVBFrontendParametersSatellite::System::DVB_S: tmp="DVB-S"; break;
168 case eDVBFrontendParametersSatellite::System::DVB_S2:
169 switch(feparm.roll_off)
171 case eDVBFrontendParametersSatellite::RollOff::alpha_0_35: tmp="0.35"; break;
172 case eDVBFrontendParametersSatellite::RollOff::alpha_0_25: tmp="0.25"; break;
173 case eDVBFrontendParametersSatellite::RollOff::alpha_0_20: tmp="0.20"; break;
175 case eDVBFrontendParametersSatellite::RollOff::alpha_auto: tmp="AUTO"; break;
177 PutToDict(dict, "roll off", tmp);
181 PutToDict(dict, "system", tmp);
184 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
186 PutToDict(dict, "type", "Terrestrial");
187 PutToDict(dict, "frequency", feparm.frequency);
189 switch (feparm.bandwidth)
191 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz: tmp="8 MHz"; break;
192 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz: tmp="7 MHz"; break;
193 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz: tmp="6 MHz"; break;
195 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto: tmp="AUTO"; break;
197 PutToDict(dict, "bandwidth", tmp);
198 switch (feparm.code_rate_LP)
200 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
201 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
202 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
203 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
204 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
206 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
208 PutToDict(dict, "code rate lp", tmp);
209 switch (feparm.code_rate_HP)
211 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
212 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
213 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
214 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
215 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
217 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
219 PutToDict(dict, "code rate hp", tmp);
220 switch (feparm.modulation)
222 case eDVBFrontendParametersTerrestrial::Modulation::QPSK: tmp="QPSK"; break;
223 case eDVBFrontendParametersTerrestrial::Modulation::QAM16: tmp="QAM16"; break;
224 case eDVBFrontendParametersTerrestrial::Modulation::QAM64: tmp="QAM64"; break;
226 case eDVBFrontendParametersTerrestrial::Modulation::Auto: tmp="AUTO"; break;
228 PutToDict(dict, "constellation", tmp);
229 switch (feparm.transmission_mode)
231 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k: tmp="2k"; break;
232 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k: tmp="8k"; break;
234 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto: tmp="AUTO"; break;
236 PutToDict(dict, "transmission mode", tmp);
237 switch (feparm.guard_interval)
239 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32: tmp="1/32"; break;
240 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16: tmp="1/16"; break;
241 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8: tmp="1/8"; break;
242 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4: tmp="1/4"; break;
244 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto: tmp="AUTO"; break;
246 PutToDict(dict, "guard interval", tmp);
247 switch (feparm.hierarchy)
249 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone: tmp="NONE"; break;
250 case eDVBFrontendParametersTerrestrial::Hierarchy::H1: tmp="1"; break;
251 case eDVBFrontendParametersTerrestrial::Hierarchy::H2: tmp="2"; break;
252 case eDVBFrontendParametersTerrestrial::Hierarchy::H4: tmp="4"; break;
254 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto: tmp="AUTO"; break;
256 PutToDict(dict, "hierarchy", tmp);
257 switch (feparm.inversion)
259 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
260 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
262 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
264 PutToDict(dict, "inversion", tmp);
267 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
270 PutToDict(dict, "type", "Cable");
271 PutToDict(dict, "frequency", feparm.frequency);
272 PutToDict(dict, "symbolrate", feparm.symbol_rate);
273 switch (feparm.modulation)
275 case eDVBFrontendParametersCable::Modulation::QAM16: tmp="QAM16"; break;
276 case eDVBFrontendParametersCable::Modulation::QAM32: tmp="QAM32"; break;
277 case eDVBFrontendParametersCable::Modulation::QAM64: tmp="QAM64"; break;
278 case eDVBFrontendParametersCable::Modulation::QAM128: tmp="QAM128"; break;
279 case eDVBFrontendParametersCable::Modulation::QAM256: tmp="QAM256"; break;
281 case eDVBFrontendParametersCable::Modulation::Auto: tmp="AUTO"; break;
283 PutToDict(dict, "modulation", tmp);
284 switch (feparm.inversion)
286 case eDVBFrontendParametersCable::Inversion::On: tmp="ON"; break;
287 case eDVBFrontendParametersCable::Inversion::Off: tmp="OFF"; break;
289 case eDVBFrontendParametersCable::Inversion::Unknown: tmp="AUTO"; break;
291 PutToDict(dict, "inversion", tmp);
292 switch (feparm.fec_inner)
294 case eDVBFrontendParametersCable::FEC::fNone: tmp="NONE"; break;
295 case eDVBFrontendParametersCable::FEC::f1_2: tmp="1/2"; break;
296 case eDVBFrontendParametersCable::FEC::f2_3: tmp="2/3"; break;
297 case eDVBFrontendParametersCable::FEC::f3_4: tmp="3/4"; break;
298 case eDVBFrontendParametersCable::FEC::f5_6: tmp="5/6"; break;
299 case eDVBFrontendParametersCable::FEC::f7_8: tmp="7/8"; break;
300 case eDVBFrontendParametersCable::FEC::f8_9: tmp="8/9"; break;
302 case eDVBFrontendParametersCable::FEC::fAuto: tmp="AUTO"; break;
304 PutToDict(dict, "fec inner", tmp);
307 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
309 if (r.type == eServiceReference::idDVB)
311 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
314 case iServiceInformation::sTransponderData:
316 ePtr<eDVBResourceManager> res;
317 if (!eDVBResourceManager::getInstance(res))
319 ePtr<iDVBChannelList> db;
320 if (!res->getChannelList(db))
323 ref.getChannelID(chid);
324 ePtr<iDVBFrontendParameters> feparm;
325 if (!db->getChannelFrontendData(chid, feparm))
328 if (!feparm->getSystem(system))
330 ePyObject dict = PyDict_New();
333 case iDVBFrontend::feSatellite:
335 eDVBFrontendParametersSatellite s;
337 PutSatelliteDataToDict(dict, s);
340 case iDVBFrontend::feTerrestrial:
342 eDVBFrontendParametersTerrestrial t;
344 PutTerrestrialDataToDict(dict, t);
347 case iDVBFrontend::feCable:
349 eDVBFrontendParametersCable c;
351 PutCableDataToDict(dict, c);
355 eDebug("unknown frontend type %d", system);
370 DEFINE_REF(eStaticServiceDVBBouquetInformation);
372 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
374 ePtr<iDVBChannelList> db;
375 ePtr<eDVBResourceManager> res;
378 if ((err = eDVBResourceManager::getInstance(res)) != 0)
380 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
383 if ((err = res->getChannelList(db)) != 0)
385 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
390 if ((err = db->getBouquet(ref, bouquet)) != 0)
392 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
396 if ( bouquet && bouquet->m_bouquet_name.length() )
398 name = bouquet->m_bouquet_name;
405 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
407 if (ref.flags & eServiceReference::isGroup)
409 ePtr<iDVBChannelList> db;
410 ePtr<eDVBResourceManager> res;
412 if (eDVBResourceManager::getInstance(res))
414 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
418 if (res->getChannelList(db))
420 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
425 if (db->getBouquet(ref, bouquet))
427 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
432 eDVBChannelID chid, chid_ignore;
433 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
434 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
436 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
437 int tmp=res->canAllocateChannel(chid, chid_ignore);
440 m_playable_service = *it;
447 m_playable_service = eServiceReference();
451 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
456 #include <lib/dvb/epgcache.h>
458 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
460 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
463 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
465 DECLARE_REF(eStaticServiceDVBPVRInformation);
466 eServiceReference m_ref;
467 eDVBMetaParser m_parser;
469 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
470 RESULT getName(const eServiceReference &ref, std::string &name);
471 int getLength(const eServiceReference &ref);
472 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
473 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
474 int getInfo(const eServiceReference &ref, int w);
475 std::string getInfoString(const eServiceReference &ref,int w);
478 DEFINE_REF(eStaticServiceDVBPVRInformation);
480 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
483 m_parser.parseFile(ref.path);
486 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
488 ASSERT(ref == m_ref);
489 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
493 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
495 ASSERT(ref == m_ref);
499 if (tstools.openFile(ref.path.c_str()))
503 if (tstools.calcLen(len))
509 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
513 case iServiceInformation::sDescription:
514 return iServiceInformation::resIsString;
515 case iServiceInformation::sServiceref:
516 return iServiceInformation::resIsString;
517 case iServiceInformation::sTimeCreate:
518 if (m_parser.m_time_create)
519 return m_parser.m_time_create;
521 return iServiceInformation::resNA;
523 return iServiceInformation::resNA;
527 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
531 case iServiceInformation::sDescription:
532 return m_parser.m_description;
533 case iServiceInformation::sServiceref:
534 return m_parser.m_ref.toString();
535 case iServiceInformation::sTags:
536 return m_parser.m_tags;
542 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
544 if (!ref.path.empty())
546 ePtr<eServiceEvent> event = new eServiceEvent;
547 std::string filename = ref.path;
548 filename.erase(filename.length()-2, 2);
550 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
560 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
562 DECLARE_REF(eDVBPVRServiceOfflineOperations);
563 eServiceReferenceDVB m_ref;
565 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
567 RESULT deleteFromDisk(int simulate);
568 RESULT getListOfFilenames(std::list<std::string> &);
571 DEFINE_REF(eDVBPVRServiceOfflineOperations);
573 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
577 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
583 std::list<std::string> res;
584 if (getListOfFilenames(res))
587 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
589 eDebug("FATAL !! can't get background file eraser");
591 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
593 eDebug("Removing %s...", i->c_str());
595 eraser->erase(i->c_str());
597 ::unlink(i->c_str());
604 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
607 res.push_back(m_ref.path);
609 // handling for old splitted recordings (enigma 1)
614 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
616 if (stat(buf, &s) < 0)
621 res.push_back(m_ref.path + ".meta");
622 res.push_back(m_ref.path + ".ap");
623 res.push_back(m_ref.path + ".cuts");
624 std::string tmp = m_ref.path;
625 tmp.erase(m_ref.path.length()-3);
626 res.push_back(tmp + ".eit");
630 DEFINE_REF(eServiceFactoryDVB)
632 eServiceFactoryDVB::eServiceFactoryDVB()
634 ePtr<eServiceCenter> sc;
636 eServiceCenter::getPrivInstance(sc);
638 sc->addServiceFactory(eServiceFactoryDVB::id, this);
640 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
641 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
644 eServiceFactoryDVB::~eServiceFactoryDVB()
646 ePtr<eServiceCenter> sc;
648 eServiceCenter::getPrivInstance(sc);
650 sc->removeServiceFactory(eServiceFactoryDVB::id);
653 DEFINE_REF(eDVBServiceList);
655 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
659 eDVBServiceList::~eDVBServiceList()
663 RESULT eDVBServiceList::startQuery()
665 ePtr<iDVBChannelList> db;
666 ePtr<eDVBResourceManager> res;
669 if ((err = eDVBResourceManager::getInstance(res)) != 0)
671 eDebug("no resource manager");
674 if ((err = res->getChannelList(db)) != 0)
676 eDebug("no channel list");
680 ePtr<eDVBChannelQuery> q;
682 if (!m_parent.path.empty())
684 eDVBChannelQuery::compile(q, m_parent.path);
687 eDebug("compile query failed");
692 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
694 eDebug("startQuery failed");
701 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
703 eServiceReferenceDVB ref;
708 while (!m_query->getNextResult(ref))
712 list.sort(iListableServiceCompare(this));
717 // The first argument of this function is a format string to specify the order and
718 // the content of the returned list
719 // useable format options are
720 // R = Service Reference (as swig object .. this is very slow)
721 // S = Service Reference (as python string object .. same as ref.toString())
722 // C = Service Reference (as python string object .. same as ref.toCompareString())
723 // N = Service Name (as python string object)
724 // n = Short Service Name (short name brakets used) (as python string object)
725 // when exactly one return value per service is selected in the format string,
726 // then each value is directly a list entry
727 // when more than one value is returned per service, then the list is a list of
729 // unknown format string chars are returned as python None values !
730 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
733 std::list<eServiceReference> tmplist;
736 if (!format || !(retcount=strlen(format)))
737 format = "R"; // just return service reference swig object ...
739 if (!getContent(tmplist, sorted))
741 int services=tmplist.size();
742 ePtr<iStaticServiceInformation> sptr;
743 eServiceCenterPtr service_center;
745 if (strchr(format, 'N') || strchr(format, 'n'))
746 eServiceCenter::getPrivInstance(service_center);
748 ret = PyList_New(services);
749 std::list<eServiceReference>::iterator it(tmplist.begin());
751 for (int cnt=0; cnt < services; ++cnt)
753 eServiceReference &ref=*it++;
754 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
755 for (int i=0; i < retcount; ++i)
760 case 'R': // service reference (swig)object
761 tmp = NEW_eServiceReference(ref);
763 case 'C': // service reference compare string
764 tmp = PyString_FromString(ref.toCompareString().c_str());
766 case 'S': // service reference string
767 tmp = PyString_FromString(ref.toString().c_str());
769 case 'N': // service name
772 service_center->info(ref, sptr);
776 sptr->getName(ref, name);
778 // filter short name brakets
780 while((pos = name.find("\xc2\x86")) != std::string::npos)
782 while((pos = name.find("\xc2\x87")) != std::string::npos)
786 tmp = PyString_FromString(name.c_str());
790 tmp = PyString_FromString("<n/a>");
792 case 'n': // short service name
795 service_center->info(ref, sptr);
799 sptr->getName(ref, name);
800 name = buildShortName(name);
802 tmp = PyString_FromString(name.c_str());
806 tmp = PyString_FromString("<n/a>");
819 PyTuple_SET_ITEM(tuple, i, tmp);
821 PyList_SET_ITEM(ret, cnt, tmp);
825 PyList_SET_ITEM(ret, cnt, tuple);
828 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
831 RESULT eDVBServiceList::getNext(eServiceReference &ref)
836 return m_query->getNextResult((eServiceReferenceDVB&)ref);
839 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
841 if (m_parent.flags & eServiceReference::canDescent) // bouquet
843 ePtr<iDVBChannelList> db;
844 ePtr<eDVBResourceManager> resm;
846 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
849 if (db->getBouquet(m_parent, m_bouquet) != 0)
860 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
864 return m_bouquet->addService(ref, before);
867 RESULT eDVBServiceList::removeService(eServiceReference &ref)
871 return m_bouquet->removeService(ref);
874 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
878 return m_bouquet->moveService(ref, pos);
881 RESULT eDVBServiceList::flushChanges()
885 return m_bouquet->flushChanges();
888 RESULT eDVBServiceList::setListName(const std::string &name)
892 return m_bouquet->setListName(name);
895 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
897 ePtr<eDVBService> service;
898 int r = lookupService(service, ref);
901 // check resources...
902 ptr = new eDVBServicePlay(ref, service);
906 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
908 if (ref.path.empty())
910 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
919 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
921 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
922 if (list->startQuery())
932 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
934 /* is a listable service? */
935 if (ref.flags & eServiceReference::canDescent) // bouquet
937 if ( !ref.name.empty() ) // satellites or providers list
938 ptr = m_StaticServiceDVBInfo;
939 else // a dvb bouquet
940 ptr = m_StaticServiceDVBBouquetInfo;
942 else if (!ref.path.empty()) /* do we have a PVR service? */
943 ptr = new eStaticServiceDVBPVRInformation(ref);
944 else // normal dvb service
946 ePtr<eDVBService> service;
947 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
948 ptr = m_StaticServiceDVBInfo;
950 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
956 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
958 if (ref.path.empty())
964 ptr = new eDVBPVRServiceOfflineOperations(ref);
969 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
971 // TODO: handle the listing itself
972 // if (ref.... == -1) .. return "... bouquets ...";
973 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
975 ePtr<iDVBChannelList> db;
976 ePtr<eDVBResourceManager> res;
979 if ((err = eDVBResourceManager::getInstance(res)) != 0)
981 eDebug("no resource manager");
984 if ((err = res->getChannelList(db)) != 0)
986 eDebug("no channel list");
990 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
991 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
993 eDebug("getService failed!");
1000 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
1001 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
1003 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
1005 m_is_pvr = !m_reference.path.empty();
1007 m_timeshift_enabled = m_timeshift_active = 0;
1010 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
1011 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
1012 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
1014 m_cuesheet_changed = 0;
1015 m_cutlist_enabled = 1;
1017 m_subtitle_widget = 0;
1021 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
1024 eDVBServicePlay::~eDVBServicePlay()
1026 delete m_subtitle_widget;
1029 void eDVBServicePlay::gotNewEvent()
1033 ePtr<eServiceEvent> m_event_now, m_event_next;
1034 getEvent(m_event_now, 0);
1035 getEvent(m_event_next, 1);
1038 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1040 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1042 m_event((iPlayableService*)this, evUpdatedEventInfo);
1045 void eDVBServicePlay::serviceEvent(int event)
1047 m_tune_state = event;
1051 case eDVBServicePMTHandler::eventTuned:
1053 ePtr<iDVBDemux> m_demux;
1054 if (!m_service_handler.getDataDemux(m_demux))
1056 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1057 int sid = ref.getParentServiceID().get();
1059 sid = ref.getServiceID().get();
1060 if ( ref.getParentTransportStreamID().get() &&
1061 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1062 m_event_handler.startOther(m_demux, sid);
1064 m_event_handler.start(m_demux, sid);
1068 case eDVBServicePMTHandler::eventNoResources:
1069 case eDVBServicePMTHandler::eventNoPAT:
1070 case eDVBServicePMTHandler::eventNoPATEntry:
1071 case eDVBServicePMTHandler::eventNoPMT:
1072 case eDVBServicePMTHandler::eventTuneFailed:
1074 eDebug("DVB service failed to tune - error %d", event);
1075 m_event((iPlayableService*)this, evTuneFailed);
1078 case eDVBServicePMTHandler::eventNewProgramInfo:
1080 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1081 if (m_timeshift_enabled)
1082 updateTimeshiftPids();
1083 if (!m_timeshift_active)
1085 if (m_first_program_info && m_is_pvr)
1087 m_first_program_info = 0;
1090 m_event((iPlayableService*)this, evUpdatedInfo);
1093 case eDVBServicePMTHandler::eventEOF:
1094 m_event((iPlayableService*)this, evEOF);
1096 case eDVBServicePMTHandler::eventSOF:
1097 m_event((iPlayableService*)this, evSOF);
1102 void eDVBServicePlay::serviceEventTimeshift(int event)
1106 case eDVBServicePMTHandler::eventNewProgramInfo:
1107 if (m_timeshift_active)
1110 case eDVBServicePMTHandler::eventSOF:
1111 m_event((iPlayableService*)this, evSOF);
1113 case eDVBServicePMTHandler::eventEOF:
1119 RESULT eDVBServicePlay::start()
1122 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1123 two (one for decoding, one for data source), as we must be prepared
1124 to start recording from the data demux. */
1126 m_cue = new eCueSheet();
1128 m_event(this, evStart);
1130 m_first_program_info = 1;
1131 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1132 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1134 /* inject EIT if there is a stored one */
1137 std::string filename = service.path;
1138 filename.erase(filename.length()-2, 2);
1140 ePtr<eServiceEvent> event = new eServiceEvent;
1141 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1143 ePtr<eServiceEvent> empty;
1144 m_event_handler.inject(event, 0);
1145 m_event_handler.inject(empty, 1);
1152 m_event(this, evStart);
1157 RESULT eDVBServicePlay::stop()
1159 /* add bookmark for last play position */
1162 pts_t play_position;
1163 if (!getPlayPosition(play_position))
1165 /* remove last position */
1166 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1168 if (i->what == 3) /* current play position */
1170 m_cue_entries.erase(i);
1171 i = m_cue_entries.begin();
1177 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1178 m_cuesheet_changed = 1;
1182 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1184 m_service_handler_timeshift.free();
1185 m_service_handler.free();
1187 if (m_is_pvr && m_cuesheet_changed)
1190 /* save cuesheet only when main file is accessible. */
1191 if (!::stat(m_reference.path.c_str(), &s))
1194 m_event((iPlayableService*)this, evStopped);
1198 RESULT eDVBServicePlay::setTarget(int target)
1200 m_is_primary = !target;
1204 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1206 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1210 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1212 /* note: we check for timeshift to be enabled,
1213 not neccessary active. if you pause when timeshift
1214 is not active, you should activate it when unpausing */
1215 if ((!m_is_pvr) && (!m_timeshift_enabled))
1225 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1228 return m_decoder->setSlowMotion(ratio);
1233 RESULT eDVBServicePlay::setFastForward(int ratio)
1235 int skipmode, ffratio;
1241 } else if (ratio > 0)
1249 } else // if (ratio < 0)
1255 if (m_skipmode != skipmode)
1257 eDebug("setting cue skipmode to %d", skipmode);
1259 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1262 m_skipmode = skipmode;
1267 return m_decoder->setFastForward(ffratio);
1270 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1272 if (m_is_pvr || m_timeshift_enabled)
1282 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1283 RESULT eDVBServicePlay::getLength(pts_t &len)
1285 ePtr<iDVBPVRChannel> pvr_channel;
1287 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1290 return pvr_channel->getLength(len);
1293 RESULT eDVBServicePlay::pause()
1295 if (!m_is_paused && m_decoder)
1298 return m_decoder->freeze(0);
1303 RESULT eDVBServicePlay::unpause()
1305 if (m_is_paused && m_decoder)
1308 return m_decoder->unfreeze();
1313 RESULT eDVBServicePlay::seekTo(pts_t to)
1315 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1317 if (!m_decode_demux)
1320 ePtr<iDVBPVRChannel> pvr_channel;
1322 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1328 m_cue->seekTo(0, to);
1332 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1334 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1336 if (!m_decode_demux)
1339 ePtr<iDVBPVRChannel> pvr_channel;
1341 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1346 /* HACK until we have skip-AP api */
1347 if ((to > 0) && (to < 100))
1355 m_cue->seekTo(mode, to);
1359 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1361 ePtr<iDVBPVRChannel> pvr_channel;
1363 if (!m_decode_demux)
1366 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1371 /* if there is a decoder, use audio or video PTS */
1374 r = m_decoder->getPTS(0, pos);
1380 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1383 RESULT eDVBServicePlay::setTrickmode(int trick)
1386 m_decoder->setTrickmode(trick);
1390 RESULT eDVBServicePlay::isCurrentlySeekable()
1392 return m_is_pvr || m_timeshift_active;
1395 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1401 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1407 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1413 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1419 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1425 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1428 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1429 (m_timeshift_enabled || !m_is_pvr))
1431 if (!m_timeshift_enabled)
1433 /* we need enough diskspace */
1435 if (statfs(TSPATH "/.", &fs) < 0)
1437 eDebug("statfs failed!");
1441 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1443 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1453 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1464 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1470 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1476 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1482 RESULT eDVBServicePlay::getName(std::string &name)
1486 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1487 return i->getName(m_reference, name);
1491 m_dvb_service->getName(m_reference, name);
1495 else if (!m_reference.name.empty())
1496 eStaticServiceDVBInformation().getName(m_reference, name);
1498 name = "DVB service";
1502 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1504 return m_event_handler.getEvent(evt, nownext);
1507 int eDVBServicePlay::getInfo(int w)
1509 eDVBServicePMTHandler::program program;
1512 return resIsPyObject;
1514 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1516 int no_program_info = 0;
1518 if (h.getProgramInfo(program))
1519 no_program_info = 1;
1523 #if HAVE_DVB_API_VERSION >= 3
1525 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1526 return m_videoEventData.height;
1529 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1530 return m_videoEventData.width;
1533 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1536 #if HAVE_DVB_API_VERSION >= 3
1537 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1538 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1541 #warning "FIXMEE implement sAspect for old DVB API"
1543 if (no_program_info)
1545 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1547 ePtr<eServiceEvent> evt;
1548 if (!m_event_handler.getEvent(evt, 0))
1550 ePtr<eComponentData> data;
1551 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1553 if ( data->getStreamContent() == 1 )
1555 switch(data->getComponentType())
1558 case 1: // 4:3 SD PAL
1560 case 3: // 16:9 SD PAL
1561 case 4: // > 16:9 PAL
1562 case 5: // 4:3 SD NTSC
1564 case 7: // 16:9 SD NTSC
1565 case 8: // > 16:9 NTSC
1568 case 9: // 4:3 HD PAL
1570 case 0xB: // 16:9 HD PAL
1571 case 0xC: // > 16:9 HD PAL
1572 case 0xD: // 4:3 HD NTSC
1574 case 0xF: // 16:9 HD NTSC
1575 case 0x10: // > 16:9 HD PAL
1576 return data->getComponentType();
1583 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1584 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1585 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1586 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1587 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1588 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1589 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1590 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1591 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1592 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1593 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1594 case sProvider: if (!m_dvb_service) return -1; return -2;
1595 case sServiceref: return resIsString;
1596 case sDVBState: return m_tune_state;
1602 std::string eDVBServicePlay::getInfoString(int w)
1607 if (!m_dvb_service) return "";
1608 return m_dvb_service->m_provider_name;
1610 return m_reference.toString();
1614 return iServiceInformation::getInfoString(w);
1617 PyObject *eDVBServicePlay::getInfoObject(int w)
1622 return m_service_handler.getCaIds();
1623 case sTransponderData:
1624 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1628 return iServiceInformation::getInfoObject(w);
1631 int eDVBServicePlay::getNumberOfTracks()
1633 eDVBServicePMTHandler::program program;
1634 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1635 if (h.getProgramInfo(program))
1637 return program.audioStreams.size();
1640 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1642 int ret = selectAudioStream(i);
1644 if (m_decoder->start())
1650 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1652 eDVBServicePMTHandler::program program;
1653 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1655 if (h.getProgramInfo(program))
1658 if (i >= program.audioStreams.size())
1661 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1662 info.m_description = "MPEG";
1663 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1664 info.m_description = "AC3";
1665 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1666 info.m_description = "AAC";
1667 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1668 info.m_description = "DTS";
1670 info.m_description = "???";
1672 if (program.audioStreams[i].component_tag != -1)
1674 ePtr<eServiceEvent> evt;
1675 if (!m_event_handler.getEvent(evt, 0))
1677 ePtr<eComponentData> data;
1678 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1679 info.m_language = data->getText();
1683 if (info.m_language.empty())
1684 info.m_language = program.audioStreams[i].language_code;
1689 int eDVBServicePlay::selectAudioStream(int i)
1691 eDVBServicePMTHandler::program program;
1692 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1694 if (h.getProgramInfo(program))
1697 if ((unsigned int)i >= program.audioStreams.size())
1703 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1707 m_rds_decoder->start(program.audioStreams[i].pid);
1709 if (m_dvb_service && !m_is_pvr)
1711 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1713 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1714 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1718 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1719 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1723 h.resetCachedProgram();
1728 int eDVBServicePlay::getCurrentChannel()
1730 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1733 RESULT eDVBServicePlay::selectChannel(int i)
1735 if (i < LEFT || i > RIGHT || i == STEREO)
1738 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1740 m_decoder->setAudioChannel(i);
1744 std::string eDVBServicePlay::getText(int x)
1750 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1752 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1757 void eDVBServicePlay::rdsDecoderEvent(int what)
1761 case eDVBRdsDecoder::RadioTextChanged:
1762 m_event((iPlayableService*)this, evUpdatedRadioText);
1764 case eDVBRdsDecoder::RtpTextChanged:
1765 m_event((iPlayableService*)this, evUpdatedRtpText);
1767 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1768 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1770 case eDVBRdsDecoder::RecvRassSlidePic:
1771 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1776 void eDVBServicePlay::showRassSlidePicture()
1782 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1783 if (rass_slide_pic.length())
1784 m_decoder->showSinglePic(rass_slide_pic.c_str());
1786 eDebug("empty filename for rass slide picture received!!");
1789 eDebug("no MPEG Decoder to show iframes avail");
1792 eDebug("showRassSlidePicture called.. but not decoder");
1795 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1801 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1802 if (rass_interactive_pic.length())
1803 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1805 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1808 eDebug("no MPEG Decoder to show iframes avail");
1811 eDebug("showRassInteractivePic called.. but not decoder");
1814 ePyObject eDVBServicePlay::getRassInteractiveMask()
1817 return m_rds_decoder->getRassPictureMask();
1821 int eDVBServiceBase::getFrontendInfo(int w)
1823 eUsePtr<iDVBChannel> channel;
1824 if(m_service_handler.getChannel(channel))
1826 ePtr<iDVBFrontend> fe;
1827 if(channel->getFrontend(fe))
1829 return fe->readFrontendData(w);
1832 PyObject *eDVBServiceBase::getFrontendData()
1834 ePyObject ret = PyDict_New();
1837 eUsePtr<iDVBChannel> channel;
1838 if(!m_service_handler.getChannel(channel))
1840 ePtr<iDVBFrontend> fe;
1841 if(!channel->getFrontend(fe))
1842 fe->getFrontendData(ret);
1850 PyObject *eDVBServiceBase::getFrontendStatus()
1852 ePyObject ret = PyDict_New();
1855 eUsePtr<iDVBChannel> channel;
1856 if(!m_service_handler.getChannel(channel))
1858 ePtr<iDVBFrontend> fe;
1859 if(!channel->getFrontend(fe))
1860 fe->getFrontendStatus(ret);
1868 PyObject *eDVBServiceBase::getTransponderData(bool original)
1870 ePyObject ret = PyDict_New();
1873 eUsePtr<iDVBChannel> channel;
1874 if(!m_service_handler.getChannel(channel))
1876 ePtr<iDVBFrontend> fe;
1877 if(!channel->getFrontend(fe))
1879 fe->getTransponderData(ret, original);
1880 ePtr<iDVBFrontendParameters> feparm;
1881 channel->getCurrentFrontendParameters(feparm);
1884 eDVBFrontendParametersSatellite osat;
1885 if (!feparm->getDVBS(osat))
1887 void PutToDict(ePyObject &, const char*, long);
1888 void PutToDict(ePyObject &, const char*, const char*);
1889 PutToDict(ret, "orbital_position", osat.orbital_position);
1890 const char *tmp = "UNKNOWN";
1891 switch(osat.polarisation)
1893 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1894 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1895 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1896 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1899 PutToDict(ret, "polarization", tmp);
1910 PyObject *eDVBServiceBase::getAll(bool original)
1912 ePyObject ret = getTransponderData(original);
1915 eUsePtr<iDVBChannel> channel;
1916 if(!m_service_handler.getChannel(channel))
1918 ePtr<iDVBFrontend> fe;
1919 if(!channel->getFrontend(fe))
1921 fe->getFrontendData(ret);
1922 fe->getFrontendStatus(ret);
1929 int eDVBServicePlay::getNumberOfSubservices()
1931 ePtr<eServiceEvent> evt;
1932 if (!m_event_handler.getEvent(evt, 0))
1933 return evt->getNumOfLinkageServices();
1937 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1939 ePtr<eServiceEvent> evt;
1940 if (!m_event_handler.getEvent(evt, 0))
1942 if (!evt->getLinkageService(sub, m_reference, n))
1945 sub.type=eServiceReference::idInvalid;
1949 RESULT eDVBServicePlay::startTimeshift()
1951 ePtr<iDVBDemux> demux;
1953 eDebug("Start timeshift!");
1955 if (m_timeshift_enabled)
1958 /* start recording with the data demux. */
1959 if (m_service_handler.getDataDemux(demux))
1962 demux->createTSRecorder(m_record);
1966 char templ[]=TSPATH "/timeshift.XXXXXX";
1967 m_timeshift_fd = mkstemp(templ);
1968 m_timeshift_file = templ;
1970 eDebug("recording to %s", templ);
1972 if (m_timeshift_fd < 0)
1978 m_record->setTargetFD(m_timeshift_fd);
1980 m_timeshift_enabled = 1;
1982 updateTimeshiftPids();
1988 RESULT eDVBServicePlay::stopTimeshift()
1990 if (!m_timeshift_enabled)
1995 m_timeshift_enabled = 0;
2000 close(m_timeshift_fd);
2001 eDebug("remove timeshift file");
2002 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2007 int eDVBServicePlay::isTimeshiftActive()
2009 return m_timeshift_enabled && m_timeshift_active;
2012 RESULT eDVBServicePlay::activateTimeshift()
2014 if (!m_timeshift_enabled)
2017 if (!m_timeshift_active)
2019 switchToTimeshift();
2026 PyObject *eDVBServicePlay::getCutList()
2028 ePyObject list = PyList_New(0);
2030 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2032 ePyObject tuple = PyTuple_New(2);
2033 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2034 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2035 PyList_Append(list, tuple);
2042 void eDVBServicePlay::setCutList(ePyObject list)
2044 if (!PyList_Check(list))
2046 int size = PyList_Size(list);
2049 m_cue_entries.clear();
2051 for (i=0; i<size; ++i)
2053 ePyObject tuple = PyList_GET_ITEM(list, i);
2054 if (!PyTuple_Check(tuple))
2056 eDebug("non-tuple in cutlist");
2059 if (PyTuple_Size(tuple) != 2)
2061 eDebug("cutlist entries need to be a 2-tuple");
2064 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2065 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2067 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2070 pts_t pts = PyLong_AsLongLong(ppts);
2071 int type = PyInt_AsLong(ptype);
2072 m_cue_entries.insert(cueEntry(pts, type));
2073 eDebug("adding %08llx, %d", pts, type);
2075 m_cuesheet_changed = 1;
2077 cutlistToCuesheet();
2078 m_event((iPlayableService*)this, evCuesheetChanged);
2081 void eDVBServicePlay::setCutListEnable(int enable)
2083 m_cutlist_enabled = enable;
2084 cutlistToCuesheet();
2087 void eDVBServicePlay::updateTimeshiftPids()
2092 eDVBServicePMTHandler::program program;
2093 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2095 if (h.getProgramInfo(program))
2099 std::set<int> pids_to_record;
2100 pids_to_record.insert(0); // PAT
2101 if (program.pmtPid != -1)
2102 pids_to_record.insert(program.pmtPid); // PMT
2104 if (program.textPid != -1)
2105 pids_to_record.insert(program.textPid); // Videotext
2107 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2108 i(program.videoStreams.begin());
2109 i != program.videoStreams.end(); ++i)
2110 pids_to_record.insert(i->pid);
2112 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2113 i(program.audioStreams.begin());
2114 i != program.audioStreams.end(); ++i)
2115 pids_to_record.insert(i->pid);
2117 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2118 i(program.subtitleStreams.begin());
2119 i != program.subtitleStreams.end(); ++i)
2120 pids_to_record.insert(i->pid);
2122 std::set<int> new_pids, obsolete_pids;
2124 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2125 m_pids_active.begin(), m_pids_active.end(),
2126 std::inserter(new_pids, new_pids.begin()));
2128 std::set_difference(
2129 m_pids_active.begin(), m_pids_active.end(),
2130 pids_to_record.begin(), pids_to_record.end(),
2131 std::inserter(new_pids, new_pids.begin())
2134 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2135 m_record->addPID(*i);
2137 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2138 m_record->removePID(*i);
2142 void eDVBServicePlay::switchToLive()
2144 if (!m_timeshift_active)
2150 m_teletext_parser = 0;
2152 m_subtitle_parser = 0;
2153 m_new_dvb_subtitle_page_connection = 0;
2154 m_new_subtitle_page_connection = 0;
2155 m_rds_decoder_event_connection = 0;
2156 m_video_event_connection = 0;
2158 /* free the timeshift service handler, we need the resources */
2159 m_service_handler_timeshift.free();
2160 m_timeshift_active = 0;
2162 m_event((iPlayableService*)this, evSeekableStatusChanged);
2167 void eDVBServicePlay::switchToTimeshift()
2169 if (m_timeshift_active)
2174 m_teletext_parser = 0;
2176 m_subtitle_parser = 0;
2177 m_new_subtitle_page_connection = 0;
2178 m_new_dvb_subtitle_page_connection = 0;
2179 m_rds_decoder_event_connection = 0;
2180 m_video_event_connection = 0;
2182 m_timeshift_active = 1;
2184 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2185 r.path = m_timeshift_file;
2187 m_cue = new eCueSheet();
2188 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2189 updateDecoder(1); /* mainly to switch off PCR, and to set pause */
2191 m_event((iPlayableService*)this, evSeekableStatusChanged);
2194 void eDVBServicePlay::updateDecoder(int intopause)
2196 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2198 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2200 bool defaultac3=false;
2201 std::string default_ac3;
2203 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2204 defaultac3 = default_ac3 == "True";
2206 eDVBServicePMTHandler::program program;
2207 if (h.getProgramInfo(program))
2208 eDebug("getting program info failed.");
2211 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2212 if (!program.videoStreams.empty())
2214 eDebugNoNewLine(" (");
2215 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2216 i(program.videoStreams.begin());
2217 i != program.videoStreams.end(); ++i)
2224 if (i != program.videoStreams.begin())
2225 eDebugNoNewLine(", ");
2226 eDebugNoNewLine("%04x", i->pid);
2228 eDebugNoNewLine(")");
2230 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2231 if (!program.audioStreams.empty())
2233 eDebugNoNewLine(" (");
2234 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2235 i(program.audioStreams.begin());
2236 i != program.audioStreams.end(); ++i)
2238 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2240 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2246 if (i != program.audioStreams.begin())
2247 eDebugNoNewLine(", ");
2248 eDebugNoNewLine("%04x", i->pid);
2250 eDebugNoNewLine(")");
2252 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2253 pcrpid = program.pcrPid;
2254 eDebug(", and the text pid is %04x", program.textPid);
2255 tpid = program.textPid;
2260 h.getDecodeDemux(m_decode_demux);
2263 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2265 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2268 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2269 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2270 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2271 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2272 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2279 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2280 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2281 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2283 else // subservice or recording
2285 eServiceReferenceDVB ref;
2286 m_service_handler.getServiceReference(ref);
2287 eServiceReferenceDVB parent = ref.getParentServiceReference();
2292 ePtr<eDVBResourceManager> res_mgr;
2293 if (!eDVBResourceManager::getInstance(res_mgr))
2295 ePtr<iDVBChannelList> db;
2296 if (!res_mgr->getChannelList(db))
2298 ePtr<eDVBService> origService;
2299 if (!db->getService(parent, origService))
2301 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2302 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2308 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2309 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2311 m_decoder->setVideoPID(vpid, vpidtype);
2312 m_decoder->setAudioPID(apid, apidtype);
2313 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2315 m_decoder->setSyncPCR(pcrpid);
2318 ePtr<iDVBDemux> data_demux;
2319 if (!h.getDataDemux(data_demux))
2321 m_rds_decoder = new eDVBRdsDecoder(data_demux);
2322 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
2323 m_rds_decoder->start(apid);
2328 m_decoder->setSyncPCR(-1);
2330 m_decoder->setTextPID(tpid);
2332 m_teletext_parser->start(program.textPid);
2335 m_decoder->setTrickmode(1);
2339 if (vpid > 0 && vpid < 0x2000)
2343 std::string radio_pic;
2344 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2345 m_decoder->setRadioPic(radio_pic);
2348 m_decoder->setAudioChannel(achannel);
2350 // how we can do this better?
2351 // update cache pid when the user changed the audio track or video track
2352 // TODO handling of difference audio types.. default audio types..
2354 /* don't worry about non-existing services, nor pvr services */
2355 if (m_dvb_service && !m_is_pvr)
2357 if (apidtype == eDVBAudio::aMPEG)
2359 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2360 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2364 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2365 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2367 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2368 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2369 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2370 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2373 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2376 void eDVBServicePlay::loadCuesheet()
2378 std::string filename = m_reference.path + ".cuts";
2380 m_cue_entries.clear();
2382 FILE *f = fopen(filename.c_str(), "rb");
2386 eDebug("loading cuts..");
2389 unsigned long long where;
2392 if (!fread(&where, sizeof(where), 1, f))
2394 if (!fread(&what, sizeof(what), 1, f))
2397 #if BYTE_ORDER == LITTLE_ENDIAN
2398 where = bswap_64(where);
2405 m_cue_entries.insert(cueEntry(where, what));
2408 eDebug("%d entries", m_cue_entries.size());
2410 eDebug("cutfile not found!");
2412 m_cuesheet_changed = 0;
2413 cutlistToCuesheet();
2414 m_event((iPlayableService*)this, evCuesheetChanged);
2417 void eDVBServicePlay::saveCuesheet()
2419 std::string filename = m_reference.path + ".cuts";
2421 FILE *f = fopen(filename.c_str(), "wb");
2425 unsigned long long where;
2428 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2430 #if BYTE_ORDER == BIG_ENDIAN
2433 where = bswap_64(i->where);
2435 what = htonl(i->what);
2436 fwrite(&where, sizeof(where), 1, f);
2437 fwrite(&what, sizeof(what), 1, f);
2443 m_cuesheet_changed = 0;
2446 void eDVBServicePlay::cutlistToCuesheet()
2450 eDebug("no cue sheet");
2455 if (!m_cutlist_enabled)
2457 m_cue->commitSpans();
2458 eDebug("cutlists were disabled");
2462 pts_t in = 0, out = 0, length = 0;
2466 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2470 if (i == m_cue_entries.end())
2473 if (i->what == 0) /* in */
2477 } else if (i->what == 1) /* out */
2479 else /* mark (2) or last play position (3) */
2487 m_cue->addSourceSpan(in, out);
2491 if (i == m_cue_entries.end())
2494 m_cue->commitSpans();
2497 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2499 if (m_subtitle_widget)
2500 disableSubtitles(parent);
2503 int tuplesize = PyTuple_Size(tuple);
2506 if (!PyTuple_Check(tuple))
2512 entry = PyTuple_GET_ITEM(tuple, 0);
2514 if (!PyInt_Check(entry))
2517 type = PyInt_AsLong(entry);
2519 if (type == 1) // teletext subtitles
2521 int page, magazine, pid;
2525 if (!m_teletext_parser)
2527 eDebug("enable teletext subtitles.. no parser !!!");
2531 entry = PyTuple_GET_ITEM(tuple, 1);
2532 if (!PyInt_Check(entry))
2534 pid = PyInt_AsLong(entry);
2536 entry = PyTuple_GET_ITEM(tuple, 2);
2537 if (!PyInt_Check(entry))
2539 page = PyInt_AsLong(entry);
2541 entry = PyTuple_GET_ITEM(tuple, 3);
2542 if (!PyInt_Check(entry))
2544 magazine = PyInt_AsLong(entry);
2546 m_subtitle_widget = new eSubtitleWidget(parent);
2547 m_subtitle_widget->resize(parent->size()); /* full size */
2548 m_teletext_parser->setPageAndMagazine(page, magazine);
2550 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2554 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2555 if (!m_subtitle_parser)
2557 eDebug("enable dvb subtitles.. no parser !!!");
2563 entry = PyTuple_GET_ITEM(tuple, 1);
2564 if (!PyInt_Check(entry))
2566 pid = PyInt_AsLong(entry);
2568 entry = PyTuple_GET_ITEM(tuple, 2);
2569 if (!PyInt_Check(entry))
2571 composition_page_id = PyInt_AsLong(entry);
2573 entry = PyTuple_GET_ITEM(tuple, 3);
2574 if (!PyInt_Check(entry))
2576 ancillary_page_id = PyInt_AsLong(entry);
2578 m_subtitle_widget = new eSubtitleWidget(parent);
2579 m_subtitle_widget->resize(parent->size()); /* full size */
2580 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2582 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2588 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2589 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2590 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2594 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2596 delete m_subtitle_widget;
2597 m_subtitle_widget = 0;
2598 if (m_subtitle_parser)
2600 m_subtitle_parser->stop();
2601 m_dvb_subtitle_pages.clear();
2603 if (m_teletext_parser)
2605 m_teletext_parser->setPageAndMagazine(-1, -1);
2606 m_subtitle_pages.clear();
2609 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2613 PyObject *eDVBServicePlay::getCachedSubtitle()
2617 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2620 unsigned int data = (unsigned int)tmp;
2621 int pid = (data&0xFFFF0000)>>16;
2622 ePyObject tuple = PyTuple_New(4);
2623 eDVBServicePMTHandler::program program;
2624 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2625 if (!h.getProgramInfo(program))
2627 if (program.textPid==pid) // teletext
2628 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2630 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2631 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2632 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2633 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2641 PyObject *eDVBServicePlay::getSubtitleList()
2643 if (!m_teletext_parser)
2646 ePyObject l = PyList_New(0);
2647 std::set<int> added_ttx_pages;
2649 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2650 m_teletext_parser->m_found_subtitle_pages;
2652 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2653 eDVBServicePMTHandler::program program;
2654 if (h.getProgramInfo(program))
2655 eDebug("getting program info failed.");
2658 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2659 it != program.subtitleStreams.end(); ++it)
2661 switch(it->subtitling_type)
2663 case 0x01: // ebu teletext subtitles
2665 int page_number = it->teletext_page_number & 0xFF;
2666 int magazine_number = it->teletext_magazine_number & 7;
2667 int hash = magazine_number << 8 | page_number;
2668 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2670 ePyObject tuple = PyTuple_New(5);
2671 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2672 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2673 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2674 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2675 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2676 PyList_Append(l, tuple);
2678 added_ttx_pages.insert(hash);
2683 case 0x20 ... 0x23: // dvb subtitles
2685 ePyObject tuple = PyTuple_New(5);
2686 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2687 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2688 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2689 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2690 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2691 PyList_Insert(l, 0, tuple);
2699 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2700 it != subs.end(); ++it)
2702 int page_number = it->teletext_page_number & 0xFF;
2703 int magazine_number = it->teletext_magazine_number & 7;
2704 int hash = magazine_number << 8 | page_number;
2705 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2707 ePyObject tuple = PyTuple_New(5);
2708 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2709 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2710 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2711 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2712 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2713 PyList_Append(l, tuple);
2721 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2723 if (m_subtitle_widget)
2725 m_subtitle_pages.push_back(page);
2726 checkSubtitleTiming();
2730 void eDVBServicePlay::checkSubtitleTiming()
2732 // eDebug("checkSubtitleTiming");
2733 if (!m_subtitle_widget)
2737 enum { TELETEXT, DVB } type;
2738 eDVBTeletextSubtitlePage page;
2739 eDVBSubtitlePage dvb_page;
2741 if (!m_subtitle_pages.empty())
2743 page = m_subtitle_pages.front();
2745 show_time = page.m_pts;
2747 else if (!m_dvb_subtitle_pages.empty())
2749 dvb_page = m_dvb_subtitle_pages.front();
2751 show_time = dvb_page.m_show_time;
2759 m_decoder->getPTS(0, pos);
2761 // eDebug("%lld %lld", pos, show_time);
2762 int diff = show_time - pos;
2765 eDebug("[late (%d ms)]", -diff / 90);
2770 eDebug("[invalid]");
2776 if (type == TELETEXT)
2778 eDebug("display teletext subtitle page");
2779 m_subtitle_widget->setPage(page);
2780 m_subtitle_pages.pop_front();
2784 eDebug("display dvb subtitle Page");
2785 m_subtitle_widget->setPage(dvb_page);
2786 m_dvb_subtitle_pages.pop_front();
2790 // eDebug("start subtitle delay %d", diff / 90);
2791 m_subtitle_sync_timer.start(diff / 90, 1);
2797 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2799 if (m_subtitle_widget)
2801 m_dvb_subtitle_pages.push_back(p);
2802 checkSubtitleTiming();
2806 int eDVBServicePlay::getAC3Delay()
2809 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2811 return m_decoder->getAC3Delay();
2816 int eDVBServicePlay::getPCMDelay()
2819 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2821 return m_decoder->getPCMDelay();
2826 void eDVBServicePlay::setAC3Delay(int delay)
2829 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2831 m_decoder->setAC3Delay(delay);
2834 void eDVBServicePlay::setPCMDelay(int delay)
2837 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2839 m_decoder->setPCMDelay(delay);
2842 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2844 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2845 m_event((iPlayableService*)this, evVideoSizeChanged);
2848 DEFINE_REF(eDVBServicePlay)
2850 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2854 case iServiceInformation::sTransponderData:
2855 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2859 return iStaticServiceInformation::getInfoObject(ref, w);
2862 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");