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);
1155 m_event((iPlayableService*)this, evSeekableStatusChanged);
1159 RESULT eDVBServicePlay::stop()
1161 /* add bookmark for last play position */
1164 pts_t play_position;
1165 if (!getPlayPosition(play_position))
1167 /* remove last position */
1168 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1170 if (i->what == 3) /* current play position */
1172 m_cue_entries.erase(i);
1173 i = m_cue_entries.begin();
1179 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1180 m_cuesheet_changed = 1;
1184 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1186 m_service_handler_timeshift.free();
1187 m_service_handler.free();
1189 if (m_is_pvr && m_cuesheet_changed)
1192 /* save cuesheet only when main file is accessible. */
1193 if (!::stat(m_reference.path.c_str(), &s))
1196 m_event((iPlayableService*)this, evStopped);
1200 RESULT eDVBServicePlay::setTarget(int target)
1202 m_is_primary = !target;
1206 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1208 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1212 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1214 /* note: we check for timeshift to be enabled,
1215 not neccessary active. if you pause when timeshift
1216 is not active, you should activate it when unpausing */
1217 if ((!m_is_pvr) && (!m_timeshift_enabled))
1227 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1230 return m_decoder->setSlowMotion(ratio);
1235 RESULT eDVBServicePlay::setFastForward(int ratio)
1237 int skipmode, ffratio;
1243 } else if (ratio > 0)
1251 } else // if (ratio < 0)
1257 if (m_skipmode != skipmode)
1259 eDebug("setting cue skipmode to %d", skipmode);
1261 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1264 m_skipmode = skipmode;
1269 return m_decoder->setFastForward(ffratio);
1272 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1274 if (m_is_pvr || m_timeshift_enabled)
1284 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1285 RESULT eDVBServicePlay::getLength(pts_t &len)
1287 ePtr<iDVBPVRChannel> pvr_channel;
1289 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1292 return pvr_channel->getLength(len);
1295 RESULT eDVBServicePlay::pause()
1297 if (!m_is_paused && m_decoder)
1300 return m_decoder->freeze(0);
1305 RESULT eDVBServicePlay::unpause()
1307 if (m_is_paused && m_decoder)
1310 return m_decoder->unfreeze();
1315 RESULT eDVBServicePlay::seekTo(pts_t to)
1317 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1319 if (!m_decode_demux)
1322 ePtr<iDVBPVRChannel> pvr_channel;
1324 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1330 m_cue->seekTo(0, to);
1334 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1336 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1338 if (!m_decode_demux)
1341 ePtr<iDVBPVRChannel> pvr_channel;
1343 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1348 /* HACK until we have skip-AP api */
1349 if ((to > 0) && (to < 100))
1357 m_cue->seekTo(mode, to);
1361 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1363 ePtr<iDVBPVRChannel> pvr_channel;
1365 if (!m_decode_demux)
1368 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1373 /* if there is a decoder, use audio or video PTS */
1376 r = m_decoder->getPTS(0, pos);
1382 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1385 RESULT eDVBServicePlay::setTrickmode(int trick)
1388 m_decoder->setTrickmode(trick);
1392 RESULT eDVBServicePlay::isCurrentlySeekable()
1394 return m_is_pvr || m_timeshift_active;
1397 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1403 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1409 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1415 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1421 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1427 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1430 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1431 (m_timeshift_enabled || !m_is_pvr))
1433 if (!m_timeshift_enabled)
1435 /* we need enough diskspace */
1437 if (statfs(TSPATH "/.", &fs) < 0)
1439 eDebug("statfs failed!");
1443 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1445 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1455 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1466 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1472 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1478 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1484 RESULT eDVBServicePlay::getName(std::string &name)
1488 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1489 return i->getName(m_reference, name);
1493 m_dvb_service->getName(m_reference, name);
1497 else if (!m_reference.name.empty())
1498 eStaticServiceDVBInformation().getName(m_reference, name);
1500 name = "DVB service";
1504 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1506 return m_event_handler.getEvent(evt, nownext);
1509 int eDVBServicePlay::getInfo(int w)
1511 eDVBServicePMTHandler::program program;
1514 return resIsPyObject;
1516 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1518 int no_program_info = 0;
1520 if (h.getProgramInfo(program))
1521 no_program_info = 1;
1525 #if HAVE_DVB_API_VERSION >= 3
1527 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1528 return m_videoEventData.height;
1531 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1532 return m_videoEventData.width;
1535 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1538 #if HAVE_DVB_API_VERSION >= 3
1539 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1540 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1543 #warning "FIXMEE implement sAspect for old DVB API"
1545 if (no_program_info)
1547 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1549 ePtr<eServiceEvent> evt;
1550 if (!m_event_handler.getEvent(evt, 0))
1552 ePtr<eComponentData> data;
1553 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1555 if ( data->getStreamContent() == 1 )
1557 switch(data->getComponentType())
1560 case 1: // 4:3 SD PAL
1562 case 3: // 16:9 SD PAL
1563 case 4: // > 16:9 PAL
1564 case 5: // 4:3 SD NTSC
1566 case 7: // 16:9 SD NTSC
1567 case 8: // > 16:9 NTSC
1570 case 9: // 4:3 HD PAL
1572 case 0xB: // 16:9 HD PAL
1573 case 0xC: // > 16:9 HD PAL
1574 case 0xD: // 4:3 HD NTSC
1576 case 0xF: // 16:9 HD NTSC
1577 case 0x10: // > 16:9 HD PAL
1578 return data->getComponentType();
1585 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1586 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1587 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1588 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1589 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1590 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1591 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1592 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1593 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1594 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1595 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1596 case sProvider: if (!m_dvb_service) return -1; return -2;
1597 case sServiceref: return resIsString;
1598 case sDVBState: return m_tune_state;
1604 std::string eDVBServicePlay::getInfoString(int w)
1609 if (!m_dvb_service) return "";
1610 return m_dvb_service->m_provider_name;
1612 return m_reference.toString();
1616 return iServiceInformation::getInfoString(w);
1619 PyObject *eDVBServicePlay::getInfoObject(int w)
1624 return m_service_handler.getCaIds();
1625 case sTransponderData:
1626 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1630 return iServiceInformation::getInfoObject(w);
1633 int eDVBServicePlay::getNumberOfTracks()
1635 eDVBServicePMTHandler::program program;
1636 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1637 if (h.getProgramInfo(program))
1639 return program.audioStreams.size();
1642 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1644 int ret = selectAudioStream(i);
1646 if (m_decoder->start())
1652 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1654 eDVBServicePMTHandler::program program;
1655 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1657 if (h.getProgramInfo(program))
1660 if (i >= program.audioStreams.size())
1663 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1664 info.m_description = "MPEG";
1665 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1666 info.m_description = "AC3";
1667 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1668 info.m_description = "AAC";
1669 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1670 info.m_description = "DTS";
1672 info.m_description = "???";
1674 if (program.audioStreams[i].component_tag != -1)
1676 ePtr<eServiceEvent> evt;
1677 if (!m_event_handler.getEvent(evt, 0))
1679 ePtr<eComponentData> data;
1680 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1681 info.m_language = data->getText();
1685 if (info.m_language.empty())
1686 info.m_language = program.audioStreams[i].language_code;
1691 int eDVBServicePlay::selectAudioStream(int i)
1693 eDVBServicePMTHandler::program program;
1694 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1696 if (h.getProgramInfo(program))
1699 if ((unsigned int)i >= program.audioStreams.size())
1705 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1708 if (m_radiotext_parser)
1709 m_radiotext_parser->start(program.audioStreams[i].pid);
1711 if (m_dvb_service && !m_is_pvr)
1713 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1715 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1716 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1720 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1721 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1725 h.resetCachedProgram();
1730 int eDVBServicePlay::getCurrentChannel()
1732 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1735 RESULT eDVBServicePlay::selectChannel(int i)
1737 if (i < LEFT || i > RIGHT || i == STEREO)
1740 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1742 m_decoder->setAudioChannel(i);
1746 std::string eDVBServicePlay::getRadioText(int x)
1748 if (m_radiotext_parser)
1752 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1757 void eDVBServicePlay::radioTextUpdated()
1759 m_event((iPlayableService*)this, evUpdatedRadioText);
1762 int eDVBServiceBase::getFrontendInfo(int w)
1764 eUsePtr<iDVBChannel> channel;
1765 if(m_service_handler.getChannel(channel))
1767 ePtr<iDVBFrontend> fe;
1768 if(channel->getFrontend(fe))
1770 return fe->readFrontendData(w);
1773 PyObject *eDVBServiceBase::getFrontendData()
1775 ePyObject ret = PyDict_New();
1778 eUsePtr<iDVBChannel> channel;
1779 if(!m_service_handler.getChannel(channel))
1781 ePtr<iDVBFrontend> fe;
1782 if(!channel->getFrontend(fe))
1783 fe->getFrontendData(ret);
1791 PyObject *eDVBServiceBase::getFrontendStatus()
1793 ePyObject ret = PyDict_New();
1796 eUsePtr<iDVBChannel> channel;
1797 if(!m_service_handler.getChannel(channel))
1799 ePtr<iDVBFrontend> fe;
1800 if(!channel->getFrontend(fe))
1801 fe->getFrontendStatus(ret);
1809 PyObject *eDVBServiceBase::getTransponderData(bool original)
1811 ePyObject ret = PyDict_New();
1814 eUsePtr<iDVBChannel> channel;
1815 if(!m_service_handler.getChannel(channel))
1817 ePtr<iDVBFrontend> fe;
1818 if(!channel->getFrontend(fe))
1820 fe->getTransponderData(ret, original);
1821 ePtr<iDVBFrontendParameters> feparm;
1822 channel->getCurrentFrontendParameters(feparm);
1825 eDVBFrontendParametersSatellite osat;
1826 if (!feparm->getDVBS(osat))
1828 void PutToDict(ePyObject &, const char*, long);
1829 void PutToDict(ePyObject &, const char*, const char*);
1830 PutToDict(ret, "orbital_position", osat.orbital_position);
1831 const char *tmp = "UNKNOWN";
1832 switch(osat.polarisation)
1834 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1835 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1836 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1837 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1840 PutToDict(ret, "polarization", tmp);
1851 PyObject *eDVBServiceBase::getAll(bool original)
1853 ePyObject ret = getTransponderData(original);
1856 eUsePtr<iDVBChannel> channel;
1857 if(!m_service_handler.getChannel(channel))
1859 ePtr<iDVBFrontend> fe;
1860 if(!channel->getFrontend(fe))
1862 fe->getFrontendData(ret);
1863 fe->getFrontendStatus(ret);
1870 int eDVBServicePlay::getNumberOfSubservices()
1872 ePtr<eServiceEvent> evt;
1873 if (!m_event_handler.getEvent(evt, 0))
1874 return evt->getNumOfLinkageServices();
1878 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1880 ePtr<eServiceEvent> evt;
1881 if (!m_event_handler.getEvent(evt, 0))
1883 if (!evt->getLinkageService(sub, m_reference, n))
1886 sub.type=eServiceReference::idInvalid;
1890 RESULT eDVBServicePlay::startTimeshift()
1892 ePtr<iDVBDemux> demux;
1894 eDebug("Start timeshift!");
1896 if (m_timeshift_enabled)
1899 /* start recording with the data demux. */
1900 if (m_service_handler.getDataDemux(demux))
1903 demux->createTSRecorder(m_record);
1907 char templ[]=TSPATH "/timeshift.XXXXXX";
1908 m_timeshift_fd = mkstemp(templ);
1909 m_timeshift_file = templ;
1911 eDebug("recording to %s", templ);
1913 if (m_timeshift_fd < 0)
1919 m_record->setTargetFD(m_timeshift_fd);
1921 m_timeshift_enabled = 1;
1923 updateTimeshiftPids();
1929 RESULT eDVBServicePlay::stopTimeshift()
1931 if (!m_timeshift_enabled)
1936 m_timeshift_enabled = 0;
1941 close(m_timeshift_fd);
1942 eDebug("remove timeshift file");
1943 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
1948 int eDVBServicePlay::isTimeshiftActive()
1950 return m_timeshift_enabled && m_timeshift_active;
1953 RESULT eDVBServicePlay::activateTimeshift()
1955 if (!m_timeshift_enabled)
1958 if (!m_timeshift_active)
1960 switchToTimeshift();
1967 PyObject *eDVBServicePlay::getCutList()
1969 ePyObject list = PyList_New(0);
1971 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1973 ePyObject tuple = PyTuple_New(2);
1974 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1975 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1976 PyList_Append(list, tuple);
1983 void eDVBServicePlay::setCutList(ePyObject list)
1985 if (!PyList_Check(list))
1987 int size = PyList_Size(list);
1990 m_cue_entries.clear();
1992 for (i=0; i<size; ++i)
1994 ePyObject tuple = PyList_GET_ITEM(list, i);
1995 if (!PyTuple_Check(tuple))
1997 eDebug("non-tuple in cutlist");
2000 if (PyTuple_Size(tuple) != 2)
2002 eDebug("cutlist entries need to be a 2-tuple");
2005 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2006 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2008 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2011 pts_t pts = PyLong_AsLongLong(ppts);
2012 int type = PyInt_AsLong(ptype);
2013 m_cue_entries.insert(cueEntry(pts, type));
2014 eDebug("adding %08llx, %d", pts, type);
2016 m_cuesheet_changed = 1;
2018 cutlistToCuesheet();
2019 m_event((iPlayableService*)this, evCuesheetChanged);
2022 void eDVBServicePlay::setCutListEnable(int enable)
2024 m_cutlist_enabled = enable;
2025 cutlistToCuesheet();
2028 void eDVBServicePlay::updateTimeshiftPids()
2033 eDVBServicePMTHandler::program program;
2034 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2036 if (h.getProgramInfo(program))
2040 std::set<int> pids_to_record;
2041 pids_to_record.insert(0); // PAT
2042 if (program.pmtPid != -1)
2043 pids_to_record.insert(program.pmtPid); // PMT
2045 if (program.textPid != -1)
2046 pids_to_record.insert(program.textPid); // Videotext
2048 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2049 i(program.videoStreams.begin());
2050 i != program.videoStreams.end(); ++i)
2051 pids_to_record.insert(i->pid);
2053 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2054 i(program.audioStreams.begin());
2055 i != program.audioStreams.end(); ++i)
2056 pids_to_record.insert(i->pid);
2058 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2059 i(program.subtitleStreams.begin());
2060 i != program.subtitleStreams.end(); ++i)
2061 pids_to_record.insert(i->pid);
2063 std::set<int> new_pids, obsolete_pids;
2065 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2066 m_pids_active.begin(), m_pids_active.end(),
2067 std::inserter(new_pids, new_pids.begin()));
2069 std::set_difference(
2070 m_pids_active.begin(), m_pids_active.end(),
2071 pids_to_record.begin(), pids_to_record.end(),
2072 std::inserter(new_pids, new_pids.begin())
2075 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2076 m_record->addPID(*i);
2078 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2079 m_record->removePID(*i);
2083 void eDVBServicePlay::switchToLive()
2085 if (!m_timeshift_active)
2091 m_teletext_parser = 0;
2092 m_radiotext_parser = 0;
2093 m_subtitle_parser = 0;
2094 m_new_dvb_subtitle_page_connection = 0;
2095 m_new_subtitle_page_connection = 0;
2096 m_radiotext_updated_connection = 0;
2097 m_video_event_connection = 0;
2099 /* free the timeshift service handler, we need the resources */
2100 m_service_handler_timeshift.free();
2101 m_timeshift_active = 0;
2103 m_event((iPlayableService*)this, evSeekableStatusChanged);
2108 void eDVBServicePlay::switchToTimeshift()
2110 if (m_timeshift_active)
2115 m_teletext_parser = 0;
2116 m_radiotext_parser = 0;
2117 m_subtitle_parser = 0;
2118 m_new_subtitle_page_connection = 0;
2119 m_new_dvb_subtitle_page_connection = 0;
2120 m_radiotext_updated_connection = 0;
2121 m_video_event_connection = 0;
2123 m_timeshift_active = 1;
2125 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2126 r.path = m_timeshift_file;
2128 m_cue = new eCueSheet();
2129 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2130 updateDecoder(); /* mainly to switch off PCR */
2132 m_event((iPlayableService*)this, evSeekableStatusChanged);
2135 void eDVBServicePlay::updateDecoder()
2137 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2139 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2141 bool defaultac3=false;
2142 std::string default_ac3;
2144 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2145 defaultac3 = default_ac3 == "True";
2147 eDVBServicePMTHandler::program program;
2148 if (h.getProgramInfo(program))
2149 eDebug("getting program info failed.");
2152 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2153 if (!program.videoStreams.empty())
2155 eDebugNoNewLine(" (");
2156 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2157 i(program.videoStreams.begin());
2158 i != program.videoStreams.end(); ++i)
2165 if (i != program.videoStreams.begin())
2166 eDebugNoNewLine(", ");
2167 eDebugNoNewLine("%04x", i->pid);
2169 eDebugNoNewLine(")");
2171 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2172 if (!program.audioStreams.empty())
2174 eDebugNoNewLine(" (");
2175 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2176 i(program.audioStreams.begin());
2177 i != program.audioStreams.end(); ++i)
2179 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2181 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2187 if (i != program.audioStreams.begin())
2188 eDebugNoNewLine(", ");
2189 eDebugNoNewLine("%04x", i->pid);
2191 eDebugNoNewLine(")");
2193 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2194 pcrpid = program.pcrPid;
2195 eDebug(", and the text pid is %04x", program.textPid);
2196 tpid = program.textPid;
2201 h.getDecodeDemux(m_decode_demux);
2204 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2206 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2209 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2210 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2211 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2212 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2213 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2220 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2221 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2222 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2224 else // subservice or recording
2226 eServiceReferenceDVB ref;
2227 m_service_handler.getServiceReference(ref);
2228 eServiceReferenceDVB parent = ref.getParentServiceReference();
2233 ePtr<eDVBResourceManager> res_mgr;
2234 if (!eDVBResourceManager::getInstance(res_mgr))
2236 ePtr<iDVBChannelList> db;
2237 if (!res_mgr->getChannelList(db))
2239 ePtr<eDVBService> origService;
2240 if (!db->getService(parent, origService))
2242 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2243 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2249 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2250 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2252 m_decoder->setVideoPID(vpid, vpidtype);
2253 m_decoder->setAudioPID(apid, apidtype);
2254 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2256 m_decoder->setSyncPCR(pcrpid);
2259 ePtr<iDVBDemux> data_demux;
2260 if (!h.getDataDemux(data_demux))
2262 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
2263 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
2264 m_radiotext_parser->start(apid);
2269 m_decoder->setSyncPCR(-1);
2271 m_decoder->setTextPID(tpid);
2273 m_teletext_parser->start(program.textPid);
2276 m_decoder->setTrickmode(1);
2280 if (vpid > 0 && vpid < 0x2000)
2284 std::string radio_pic;
2285 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2286 m_decoder->setRadioPic(radio_pic);
2289 m_decoder->setAudioChannel(achannel);
2291 // how we can do this better?
2292 // update cache pid when the user changed the audio track or video track
2293 // TODO handling of difference audio types.. default audio types..
2295 /* don't worry about non-existing services, nor pvr services */
2296 if (m_dvb_service && !m_is_pvr)
2298 if (apidtype == eDVBAudio::aMPEG)
2300 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2301 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2305 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2306 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2308 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2309 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2310 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2311 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2314 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2317 void eDVBServicePlay::loadCuesheet()
2319 std::string filename = m_reference.path + ".cuts";
2321 m_cue_entries.clear();
2323 FILE *f = fopen(filename.c_str(), "rb");
2327 eDebug("loading cuts..");
2330 unsigned long long where;
2333 if (!fread(&where, sizeof(where), 1, f))
2335 if (!fread(&what, sizeof(what), 1, f))
2338 #if BYTE_ORDER == LITTLE_ENDIAN
2339 where = bswap_64(where);
2346 m_cue_entries.insert(cueEntry(where, what));
2349 eDebug("%d entries", m_cue_entries.size());
2351 eDebug("cutfile not found!");
2353 m_cuesheet_changed = 0;
2354 cutlistToCuesheet();
2355 m_event((iPlayableService*)this, evCuesheetChanged);
2358 void eDVBServicePlay::saveCuesheet()
2360 std::string filename = m_reference.path + ".cuts";
2362 FILE *f = fopen(filename.c_str(), "wb");
2366 unsigned long long where;
2369 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2371 #if BYTE_ORDER == BIG_ENDIAN
2374 where = bswap_64(i->where);
2376 what = htonl(i->what);
2377 fwrite(&where, sizeof(where), 1, f);
2378 fwrite(&what, sizeof(what), 1, f);
2384 m_cuesheet_changed = 0;
2387 void eDVBServicePlay::cutlistToCuesheet()
2391 eDebug("no cue sheet");
2396 if (!m_cutlist_enabled)
2398 m_cue->commitSpans();
2399 eDebug("cutlists were disabled");
2403 pts_t in = 0, out = 0, length = 0;
2407 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2411 if (i == m_cue_entries.end())
2414 if (i->what == 0) /* in */
2418 } else if (i->what == 1) /* out */
2420 else /* mark (2) or last play position (3) */
2428 m_cue->addSourceSpan(in, out);
2432 if (i == m_cue_entries.end())
2435 m_cue->commitSpans();
2438 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2440 if (m_subtitle_widget)
2441 disableSubtitles(parent);
2444 int tuplesize = PyTuple_Size(tuple);
2447 if (!PyTuple_Check(tuple))
2453 entry = PyTuple_GET_ITEM(tuple, 0);
2455 if (!PyInt_Check(entry))
2458 type = PyInt_AsLong(entry);
2460 if (type == 1) // teletext subtitles
2462 int page, magazine, pid;
2466 if (!m_teletext_parser)
2468 eDebug("enable teletext subtitles.. no parser !!!");
2472 entry = PyTuple_GET_ITEM(tuple, 1);
2473 if (!PyInt_Check(entry))
2475 pid = PyInt_AsLong(entry);
2477 entry = PyTuple_GET_ITEM(tuple, 2);
2478 if (!PyInt_Check(entry))
2480 page = PyInt_AsLong(entry);
2482 entry = PyTuple_GET_ITEM(tuple, 3);
2483 if (!PyInt_Check(entry))
2485 magazine = PyInt_AsLong(entry);
2487 m_subtitle_widget = new eSubtitleWidget(parent);
2488 m_subtitle_widget->resize(parent->size()); /* full size */
2489 m_teletext_parser->setPageAndMagazine(page, magazine);
2491 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2495 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2496 if (!m_subtitle_parser)
2498 eDebug("enable dvb subtitles.. no parser !!!");
2504 entry = PyTuple_GET_ITEM(tuple, 1);
2505 if (!PyInt_Check(entry))
2507 pid = PyInt_AsLong(entry);
2509 entry = PyTuple_GET_ITEM(tuple, 2);
2510 if (!PyInt_Check(entry))
2512 composition_page_id = PyInt_AsLong(entry);
2514 entry = PyTuple_GET_ITEM(tuple, 3);
2515 if (!PyInt_Check(entry))
2517 ancillary_page_id = PyInt_AsLong(entry);
2519 m_subtitle_widget = new eSubtitleWidget(parent);
2520 m_subtitle_widget->resize(parent->size()); /* full size */
2521 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2523 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2529 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2530 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2531 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2535 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2537 delete m_subtitle_widget;
2538 m_subtitle_widget = 0;
2539 if (m_subtitle_parser)
2541 m_subtitle_parser->stop();
2542 m_dvb_subtitle_pages.clear();
2544 if (m_teletext_parser)
2546 m_teletext_parser->setPageAndMagazine(-1, -1);
2547 m_subtitle_pages.clear();
2550 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2554 PyObject *eDVBServicePlay::getCachedSubtitle()
2558 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2561 unsigned int data = (unsigned int)tmp;
2562 int pid = (data&0xFFFF0000)>>16;
2563 ePyObject tuple = PyTuple_New(4);
2564 eDVBServicePMTHandler::program program;
2565 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2566 if (!h.getProgramInfo(program))
2568 if (program.textPid==pid) // teletext
2569 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2571 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2572 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2573 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2574 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2582 PyObject *eDVBServicePlay::getSubtitleList()
2584 if (!m_teletext_parser)
2587 ePyObject l = PyList_New(0);
2588 std::set<int> added_ttx_pages;
2590 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2591 m_teletext_parser->m_found_subtitle_pages;
2593 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2594 eDVBServicePMTHandler::program program;
2595 if (h.getProgramInfo(program))
2596 eDebug("getting program info failed.");
2599 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2600 it != program.subtitleStreams.end(); ++it)
2602 switch(it->subtitling_type)
2604 case 0x01: // ebu teletext subtitles
2606 int page_number = it->teletext_page_number & 0xFF;
2607 int magazine_number = it->teletext_magazine_number & 7;
2608 int hash = magazine_number << 8 | page_number;
2609 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2611 ePyObject tuple = PyTuple_New(5);
2612 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2613 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2614 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2615 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2616 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2617 PyList_Append(l, tuple);
2619 added_ttx_pages.insert(hash);
2624 case 0x20 ... 0x23: // dvb subtitles
2626 ePyObject tuple = PyTuple_New(5);
2627 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2628 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2629 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2630 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2631 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2632 PyList_Insert(l, 0, tuple);
2640 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2641 it != subs.end(); ++it)
2643 int page_number = it->teletext_page_number & 0xFF;
2644 int magazine_number = it->teletext_magazine_number & 7;
2645 int hash = magazine_number << 8 | page_number;
2646 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2648 ePyObject tuple = PyTuple_New(5);
2649 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2650 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2651 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2652 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2653 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2654 PyList_Append(l, tuple);
2662 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2664 if (m_subtitle_widget)
2666 m_subtitle_pages.push_back(page);
2667 checkSubtitleTiming();
2671 void eDVBServicePlay::checkSubtitleTiming()
2673 // eDebug("checkSubtitleTiming");
2674 if (!m_subtitle_widget)
2678 enum { TELETEXT, DVB } type;
2679 eDVBTeletextSubtitlePage page;
2680 eDVBSubtitlePage dvb_page;
2682 if (!m_subtitle_pages.empty())
2684 page = m_subtitle_pages.front();
2686 show_time = page.m_pts;
2688 else if (!m_dvb_subtitle_pages.empty())
2690 dvb_page = m_dvb_subtitle_pages.front();
2692 show_time = dvb_page.m_show_time;
2700 m_decoder->getPTS(0, pos);
2702 // eDebug("%lld %lld", pos, show_time);
2703 int diff = show_time - pos;
2706 eDebug("[late (%d ms)]", -diff / 90);
2711 eDebug("[invalid]");
2717 if (type == TELETEXT)
2719 eDebug("display teletext subtitle page");
2720 m_subtitle_widget->setPage(page);
2721 m_subtitle_pages.pop_front();
2725 eDebug("display dvb subtitle Page");
2726 m_subtitle_widget->setPage(dvb_page);
2727 m_dvb_subtitle_pages.pop_front();
2731 // eDebug("start subtitle delay %d", diff / 90);
2732 m_subtitle_sync_timer.start(diff / 90, 1);
2738 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2740 if (m_subtitle_widget)
2742 m_dvb_subtitle_pages.push_back(p);
2743 checkSubtitleTiming();
2747 int eDVBServicePlay::getAC3Delay()
2750 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2752 return m_decoder->getAC3Delay();
2757 int eDVBServicePlay::getPCMDelay()
2760 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2762 return m_decoder->getPCMDelay();
2767 void eDVBServicePlay::setAC3Delay(int delay)
2770 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2772 m_decoder->setAC3Delay(delay);
2775 void eDVBServicePlay::setPCMDelay(int delay)
2778 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2780 m_decoder->setPCMDelay(delay);
2783 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2785 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2786 m_event((iPlayableService*)this, evVideoSizeChanged);
2789 DEFINE_REF(eDVBServicePlay)
2791 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2795 case iServiceInformation::sTransponderData:
2796 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2800 return iStaticServiceInformation::getInfoObject(ref, w);
2803 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");