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(bool original)
1777 eUsePtr<iDVBChannel> channel;
1778 if(!m_service_handler.getChannel(channel))
1780 ePtr<iDVBFrontend> fe;
1781 if(!channel->getFrontend(fe))
1783 ret = fe->readTransponderData(original);
1786 ePtr<iDVBFrontendParameters> feparm;
1787 channel->getCurrentFrontendParameters(feparm);
1790 eDVBFrontendParametersSatellite osat;
1791 if (!feparm->getDVBS(osat))
1793 void PutToDict(ePyObject &, const char*, long);
1794 void PutToDict(ePyObject &, const char*, const char*);
1795 PutToDict(ret, "orbital_position", osat.orbital_position);
1796 const char *tmp = "UNKNOWN";
1797 switch(osat.polarisation)
1799 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1800 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1801 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1802 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1805 PutToDict(ret, "polarization", tmp);
1816 int eDVBServicePlay::getNumberOfSubservices()
1818 ePtr<eServiceEvent> evt;
1819 if (!m_event_handler.getEvent(evt, 0))
1820 return evt->getNumOfLinkageServices();
1824 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1826 ePtr<eServiceEvent> evt;
1827 if (!m_event_handler.getEvent(evt, 0))
1829 if (!evt->getLinkageService(sub, m_reference, n))
1832 sub.type=eServiceReference::idInvalid;
1836 RESULT eDVBServicePlay::startTimeshift()
1838 ePtr<iDVBDemux> demux;
1840 eDebug("Start timeshift!");
1842 if (m_timeshift_enabled)
1845 /* start recording with the data demux. */
1846 if (m_service_handler.getDataDemux(demux))
1849 demux->createTSRecorder(m_record);
1853 char templ[]=TSPATH "/timeshift.XXXXXX";
1854 m_timeshift_fd = mkstemp(templ);
1855 m_timeshift_file = templ;
1857 eDebug("recording to %s", templ);
1859 if (m_timeshift_fd < 0)
1865 m_record->setTargetFD(m_timeshift_fd);
1867 m_timeshift_enabled = 1;
1869 updateTimeshiftPids();
1875 RESULT eDVBServicePlay::stopTimeshift()
1877 if (!m_timeshift_enabled)
1882 m_timeshift_enabled = 0;
1887 close(m_timeshift_fd);
1888 eDebug("remove timeshift file");
1889 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
1894 int eDVBServicePlay::isTimeshiftActive()
1896 return m_timeshift_enabled && m_timeshift_active;
1899 RESULT eDVBServicePlay::activateTimeshift()
1901 if (!m_timeshift_enabled)
1904 if (!m_timeshift_active)
1906 switchToTimeshift();
1913 PyObject *eDVBServicePlay::getCutList()
1915 ePyObject list = PyList_New(0);
1917 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1919 ePyObject tuple = PyTuple_New(2);
1920 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1921 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1922 PyList_Append(list, tuple);
1929 void eDVBServicePlay::setCutList(ePyObject list)
1931 if (!PyList_Check(list))
1933 int size = PyList_Size(list);
1936 m_cue_entries.clear();
1938 for (i=0; i<size; ++i)
1940 ePyObject tuple = PyList_GET_ITEM(list, i);
1941 if (!PyTuple_Check(tuple))
1943 eDebug("non-tuple in cutlist");
1946 if (PyTuple_Size(tuple) != 2)
1948 eDebug("cutlist entries need to be a 2-tuple");
1951 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1952 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1954 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1957 pts_t pts = PyLong_AsLongLong(ppts);
1958 int type = PyInt_AsLong(ptype);
1959 m_cue_entries.insert(cueEntry(pts, type));
1960 eDebug("adding %08llx, %d", pts, type);
1962 m_cuesheet_changed = 1;
1964 cutlistToCuesheet();
1965 m_event((iPlayableService*)this, evCuesheetChanged);
1968 void eDVBServicePlay::setCutListEnable(int enable)
1970 m_cutlist_enabled = enable;
1971 cutlistToCuesheet();
1974 void eDVBServicePlay::updateTimeshiftPids()
1979 eDVBServicePMTHandler::program program;
1980 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1982 if (h.getProgramInfo(program))
1986 std::set<int> pids_to_record;
1987 pids_to_record.insert(0); // PAT
1988 if (program.pmtPid != -1)
1989 pids_to_record.insert(program.pmtPid); // PMT
1991 if (program.textPid != -1)
1992 pids_to_record.insert(program.textPid); // Videotext
1994 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1995 i(program.videoStreams.begin());
1996 i != program.videoStreams.end(); ++i)
1997 pids_to_record.insert(i->pid);
1999 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2000 i(program.audioStreams.begin());
2001 i != program.audioStreams.end(); ++i)
2002 pids_to_record.insert(i->pid);
2004 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2005 i(program.subtitleStreams.begin());
2006 i != program.subtitleStreams.end(); ++i)
2007 pids_to_record.insert(i->pid);
2009 std::set<int> new_pids, obsolete_pids;
2011 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2012 m_pids_active.begin(), m_pids_active.end(),
2013 std::inserter(new_pids, new_pids.begin()));
2015 std::set_difference(
2016 m_pids_active.begin(), m_pids_active.end(),
2017 pids_to_record.begin(), pids_to_record.end(),
2018 std::inserter(new_pids, new_pids.begin())
2021 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2022 m_record->addPID(*i);
2024 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2025 m_record->removePID(*i);
2029 void eDVBServicePlay::switchToLive()
2031 if (!m_timeshift_active)
2037 m_teletext_parser = 0;
2038 m_radiotext_parser = 0;
2039 m_subtitle_parser = 0;
2040 m_new_dvb_subtitle_page_connection = 0;
2041 m_new_subtitle_page_connection = 0;
2042 m_radiotext_updated_connection = 0;
2043 m_video_event_connection = 0;
2045 /* free the timeshift service handler, we need the resources */
2046 m_service_handler_timeshift.free();
2047 m_timeshift_active = 0;
2049 m_event((iPlayableService*)this, evSeekableStatusChanged);
2054 void eDVBServicePlay::switchToTimeshift()
2056 if (m_timeshift_active)
2061 m_teletext_parser = 0;
2062 m_radiotext_parser = 0;
2063 m_subtitle_parser = 0;
2064 m_new_subtitle_page_connection = 0;
2065 m_new_dvb_subtitle_page_connection = 0;
2066 m_radiotext_updated_connection = 0;
2067 m_video_event_connection = 0;
2069 m_timeshift_active = 1;
2071 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2072 r.path = m_timeshift_file;
2074 m_cue = new eCueSheet();
2075 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2076 updateDecoder(); /* mainly to switch off PCR */
2078 m_event((iPlayableService*)this, evSeekableStatusChanged);
2081 void eDVBServicePlay::updateDecoder()
2083 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2085 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2087 bool defaultac3=false;
2088 std::string default_ac3;
2090 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2091 defaultac3 = default_ac3 == "True";
2093 eDVBServicePMTHandler::program program;
2094 if (h.getProgramInfo(program))
2095 eDebug("getting program info failed.");
2098 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2099 if (!program.videoStreams.empty())
2101 eDebugNoNewLine(" (");
2102 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2103 i(program.videoStreams.begin());
2104 i != program.videoStreams.end(); ++i)
2111 if (i != program.videoStreams.begin())
2112 eDebugNoNewLine(", ");
2113 eDebugNoNewLine("%04x", i->pid);
2115 eDebugNoNewLine(")");
2117 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2118 if (!program.audioStreams.empty())
2120 eDebugNoNewLine(" (");
2121 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2122 i(program.audioStreams.begin());
2123 i != program.audioStreams.end(); ++i)
2125 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2127 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2133 if (i != program.audioStreams.begin())
2134 eDebugNoNewLine(", ");
2135 eDebugNoNewLine("%04x", i->pid);
2137 eDebugNoNewLine(")");
2139 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2140 pcrpid = program.pcrPid;
2141 eDebug(", and the text pid is %04x", program.textPid);
2142 tpid = program.textPid;
2147 h.getDecodeDemux(m_decode_demux);
2150 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2152 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2155 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2156 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2157 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2158 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2159 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2166 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2167 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2168 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2170 else // subservice or recording
2172 eServiceReferenceDVB ref;
2173 m_service_handler.getServiceReference(ref);
2174 eServiceReferenceDVB parent = ref.getParentServiceReference();
2179 ePtr<eDVBResourceManager> res_mgr;
2180 if (!eDVBResourceManager::getInstance(res_mgr))
2182 ePtr<iDVBChannelList> db;
2183 if (!res_mgr->getChannelList(db))
2185 ePtr<eDVBService> origService;
2186 if (!db->getService(parent, origService))
2188 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2189 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2195 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2196 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2198 m_decoder->setVideoPID(vpid, vpidtype);
2199 m_decoder->setAudioPID(apid, apidtype);
2200 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2202 m_decoder->setSyncPCR(pcrpid);
2205 ePtr<iDVBDemux> data_demux;
2206 if (!h.getDataDemux(data_demux))
2208 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
2209 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
2210 m_radiotext_parser->start(apid);
2215 m_decoder->setSyncPCR(-1);
2217 m_decoder->setTextPID(tpid);
2219 m_teletext_parser->start(program.textPid);
2222 m_decoder->setTrickmode(1);
2226 if (vpid > 0 && vpid < 0x2000)
2230 std::string radio_pic;
2231 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2232 m_decoder->setRadioPic(radio_pic);
2235 m_decoder->setAudioChannel(achannel);
2237 // how we can do this better?
2238 // update cache pid when the user changed the audio track or video track
2239 // TODO handling of difference audio types.. default audio types..
2241 /* don't worry about non-existing services, nor pvr services */
2242 if (m_dvb_service && !m_is_pvr)
2244 if (apidtype == eDVBAudio::aMPEG)
2246 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2247 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2251 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2252 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2254 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2255 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2256 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2257 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2260 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2263 void eDVBServicePlay::loadCuesheet()
2265 std::string filename = m_reference.path + ".cuts";
2267 m_cue_entries.clear();
2269 FILE *f = fopen(filename.c_str(), "rb");
2273 eDebug("loading cuts..");
2276 unsigned long long where;
2279 if (!fread(&where, sizeof(where), 1, f))
2281 if (!fread(&what, sizeof(what), 1, f))
2284 #if BYTE_ORDER == LITTLE_ENDIAN
2285 where = bswap_64(where);
2292 m_cue_entries.insert(cueEntry(where, what));
2295 eDebug("%d entries", m_cue_entries.size());
2297 eDebug("cutfile not found!");
2299 m_cuesheet_changed = 0;
2300 cutlistToCuesheet();
2301 m_event((iPlayableService*)this, evCuesheetChanged);
2304 void eDVBServicePlay::saveCuesheet()
2306 std::string filename = m_reference.path + ".cuts";
2308 FILE *f = fopen(filename.c_str(), "wb");
2312 unsigned long long where;
2315 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2317 #if BYTE_ORDER == BIG_ENDIAN
2320 where = bswap_64(i->where);
2322 what = htonl(i->what);
2323 fwrite(&where, sizeof(where), 1, f);
2324 fwrite(&what, sizeof(what), 1, f);
2330 m_cuesheet_changed = 0;
2333 void eDVBServicePlay::cutlistToCuesheet()
2337 eDebug("no cue sheet");
2342 if (!m_cutlist_enabled)
2344 m_cue->commitSpans();
2345 eDebug("cutlists were disabled");
2349 pts_t in = 0, out = 0, length = 0;
2353 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2357 if (i == m_cue_entries.end())
2360 if (i->what == 0) /* in */
2364 } else if (i->what == 1) /* out */
2366 else /* mark (2) or last play position (3) */
2374 m_cue->addSourceSpan(in, out);
2378 if (i == m_cue_entries.end())
2381 m_cue->commitSpans();
2384 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2386 if (m_subtitle_widget)
2387 disableSubtitles(parent);
2390 int tuplesize = PyTuple_Size(tuple);
2393 if (!PyTuple_Check(tuple))
2399 entry = PyTuple_GET_ITEM(tuple, 0);
2401 if (!PyInt_Check(entry))
2404 type = PyInt_AsLong(entry);
2406 if (type == 1) // teletext subtitles
2408 int page, magazine, pid;
2412 if (!m_teletext_parser)
2414 eDebug("enable teletext subtitles.. no parser !!!");
2418 entry = PyTuple_GET_ITEM(tuple, 1);
2419 if (!PyInt_Check(entry))
2421 pid = PyInt_AsLong(entry);
2423 entry = PyTuple_GET_ITEM(tuple, 2);
2424 if (!PyInt_Check(entry))
2426 page = PyInt_AsLong(entry);
2428 entry = PyTuple_GET_ITEM(tuple, 3);
2429 if (!PyInt_Check(entry))
2431 magazine = PyInt_AsLong(entry);
2433 m_subtitle_widget = new eSubtitleWidget(parent);
2434 m_subtitle_widget->resize(parent->size()); /* full size */
2435 m_teletext_parser->setPageAndMagazine(page, magazine);
2437 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2441 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2442 if (!m_subtitle_parser)
2444 eDebug("enable dvb subtitles.. no parser !!!");
2450 entry = PyTuple_GET_ITEM(tuple, 1);
2451 if (!PyInt_Check(entry))
2453 pid = PyInt_AsLong(entry);
2455 entry = PyTuple_GET_ITEM(tuple, 2);
2456 if (!PyInt_Check(entry))
2458 composition_page_id = PyInt_AsLong(entry);
2460 entry = PyTuple_GET_ITEM(tuple, 3);
2461 if (!PyInt_Check(entry))
2463 ancillary_page_id = PyInt_AsLong(entry);
2465 m_subtitle_widget = new eSubtitleWidget(parent);
2466 m_subtitle_widget->resize(parent->size()); /* full size */
2467 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2469 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2475 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2476 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2477 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2481 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2483 delete m_subtitle_widget;
2484 m_subtitle_widget = 0;
2485 if (m_subtitle_parser)
2487 m_subtitle_parser->stop();
2488 m_dvb_subtitle_pages.clear();
2490 if (m_teletext_parser)
2492 m_teletext_parser->setPageAndMagazine(-1, -1);
2493 m_subtitle_pages.clear();
2496 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2500 PyObject *eDVBServicePlay::getCachedSubtitle()
2504 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2507 unsigned int data = (unsigned int)tmp;
2508 int pid = (data&0xFFFF0000)>>16;
2509 ePyObject tuple = PyTuple_New(4);
2510 eDVBServicePMTHandler::program program;
2511 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2512 if (!h.getProgramInfo(program))
2514 if (program.textPid==pid) // teletext
2515 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2517 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2518 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2519 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2520 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2528 PyObject *eDVBServicePlay::getSubtitleList()
2530 if (!m_teletext_parser)
2533 ePyObject l = PyList_New(0);
2534 std::set<int> added_ttx_pages;
2536 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2537 m_teletext_parser->m_found_subtitle_pages;
2539 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2540 eDVBServicePMTHandler::program program;
2541 if (h.getProgramInfo(program))
2542 eDebug("getting program info failed.");
2545 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2546 it != program.subtitleStreams.end(); ++it)
2548 switch(it->subtitling_type)
2550 case 0x01: // ebu teletext subtitles
2552 int page_number = it->teletext_page_number & 0xFF;
2553 int magazine_number = it->teletext_magazine_number & 7;
2554 int hash = magazine_number << 8 | page_number;
2555 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2557 ePyObject tuple = PyTuple_New(5);
2558 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2559 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2560 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2561 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2562 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2563 PyList_Append(l, tuple);
2565 added_ttx_pages.insert(hash);
2570 case 0x20 ... 0x23: // dvb subtitles
2572 ePyObject tuple = PyTuple_New(5);
2573 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2574 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2575 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2576 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2577 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2578 PyList_Insert(l, 0, tuple);
2586 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2587 it != subs.end(); ++it)
2589 int page_number = it->teletext_page_number & 0xFF;
2590 int magazine_number = it->teletext_magazine_number & 7;
2591 int hash = magazine_number << 8 | page_number;
2592 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2594 ePyObject tuple = PyTuple_New(5);
2595 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2596 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2597 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2598 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2599 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2600 PyList_Append(l, tuple);
2608 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2610 if (m_subtitle_widget)
2612 m_subtitle_pages.push_back(page);
2613 checkSubtitleTiming();
2617 void eDVBServicePlay::checkSubtitleTiming()
2619 // eDebug("checkSubtitleTiming");
2620 if (!m_subtitle_widget)
2624 enum { TELETEXT, DVB } type;
2625 eDVBTeletextSubtitlePage page;
2626 eDVBSubtitlePage dvb_page;
2628 if (!m_subtitle_pages.empty())
2630 page = m_subtitle_pages.front();
2632 show_time = page.m_pts;
2634 else if (!m_dvb_subtitle_pages.empty())
2636 dvb_page = m_dvb_subtitle_pages.front();
2638 show_time = dvb_page.m_show_time;
2646 m_decoder->getPTS(0, pos);
2648 // eDebug("%lld %lld", pos, show_time);
2649 int diff = show_time - pos;
2652 eDebug("[late (%d ms)]", -diff / 90);
2657 eDebug("[invalid]");
2663 if (type == TELETEXT)
2665 eDebug("display teletext subtitle page");
2666 m_subtitle_widget->setPage(page);
2667 m_subtitle_pages.pop_front();
2671 eDebug("display dvb subtitle Page");
2672 m_subtitle_widget->setPage(dvb_page);
2673 m_dvb_subtitle_pages.pop_front();
2677 // eDebug("start subtitle delay %d", diff / 90);
2678 m_subtitle_sync_timer.start(diff / 90, 1);
2684 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2686 if (m_subtitle_widget)
2688 m_dvb_subtitle_pages.push_back(p);
2689 checkSubtitleTiming();
2693 int eDVBServicePlay::getAC3Delay()
2696 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2698 return m_decoder->getAC3Delay();
2703 int eDVBServicePlay::getPCMDelay()
2706 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2708 return m_decoder->getPCMDelay();
2713 void eDVBServicePlay::setAC3Delay(int delay)
2716 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2718 m_decoder->setAC3Delay(delay);
2721 void eDVBServicePlay::setPCMDelay(int delay)
2724 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2726 m_decoder->setPCMDelay(delay);
2729 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2731 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2732 m_event((iPlayableService*)this, evVideoSizeChanged);
2735 DEFINE_REF(eDVBServicePlay)
2737 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2741 case iServiceInformation::sTransponderData:
2742 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2746 return iStaticServiceInformation::getInfoObject(ref, w);
2749 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");