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::rdsDecoder(ePtr<iRdsDecoder> &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))
1709 m_rds_decoder->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::getText(int x)
1752 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1754 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1759 void eDVBServicePlay::rdsDecoderEvent(int what)
1763 case eDVBRdsDecoder::RadioTextChanged:
1764 m_event((iPlayableService*)this, evUpdatedRadioText);
1766 case eDVBRdsDecoder::RtpTextChanged:
1767 m_event((iPlayableService*)this, evUpdatedRtpText);
1769 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1770 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1772 case eDVBRdsDecoder::RecvRassSlidePic:
1773 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1778 void eDVBServicePlay::showRassSlidePicture()
1784 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1785 if (rass_slide_pic.length())
1786 m_decoder->showSinglePic(rass_slide_pic.c_str());
1788 eDebug("empty filename for rass slide picture received!!");
1791 eDebug("no MPEG Decoder to show iframes avail");
1794 eDebug("showRassSlidePicture called.. but not decoder");
1797 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1803 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1804 if (rass_interactive_pic.length())
1805 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1807 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1810 eDebug("no MPEG Decoder to show iframes avail");
1813 eDebug("showRassInteractivePic called.. but not decoder");
1816 ePyObject eDVBServicePlay::getRassInteractiveMask()
1819 return m_rds_decoder->getRassPictureMask();
1823 int eDVBServiceBase::getFrontendInfo(int w)
1825 eUsePtr<iDVBChannel> channel;
1826 if(m_service_handler.getChannel(channel))
1828 ePtr<iDVBFrontend> fe;
1829 if(channel->getFrontend(fe))
1831 return fe->readFrontendData(w);
1834 PyObject *eDVBServiceBase::getFrontendData()
1836 ePyObject ret = PyDict_New();
1839 eUsePtr<iDVBChannel> channel;
1840 if(!m_service_handler.getChannel(channel))
1842 ePtr<iDVBFrontend> fe;
1843 if(!channel->getFrontend(fe))
1844 fe->getFrontendData(ret);
1852 PyObject *eDVBServiceBase::getFrontendStatus()
1854 ePyObject ret = PyDict_New();
1857 eUsePtr<iDVBChannel> channel;
1858 if(!m_service_handler.getChannel(channel))
1860 ePtr<iDVBFrontend> fe;
1861 if(!channel->getFrontend(fe))
1862 fe->getFrontendStatus(ret);
1870 PyObject *eDVBServiceBase::getTransponderData(bool original)
1872 ePyObject ret = PyDict_New();
1875 eUsePtr<iDVBChannel> channel;
1876 if(!m_service_handler.getChannel(channel))
1878 ePtr<iDVBFrontend> fe;
1879 if(!channel->getFrontend(fe))
1881 fe->getTransponderData(ret, original);
1882 ePtr<iDVBFrontendParameters> feparm;
1883 channel->getCurrentFrontendParameters(feparm);
1886 eDVBFrontendParametersSatellite osat;
1887 if (!feparm->getDVBS(osat))
1889 void PutToDict(ePyObject &, const char*, long);
1890 void PutToDict(ePyObject &, const char*, const char*);
1891 PutToDict(ret, "orbital_position", osat.orbital_position);
1892 const char *tmp = "UNKNOWN";
1893 switch(osat.polarisation)
1895 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1896 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1897 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1898 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1901 PutToDict(ret, "polarization", tmp);
1912 PyObject *eDVBServiceBase::getAll(bool original)
1914 ePyObject ret = getTransponderData(original);
1917 eUsePtr<iDVBChannel> channel;
1918 if(!m_service_handler.getChannel(channel))
1920 ePtr<iDVBFrontend> fe;
1921 if(!channel->getFrontend(fe))
1923 fe->getFrontendData(ret);
1924 fe->getFrontendStatus(ret);
1931 int eDVBServicePlay::getNumberOfSubservices()
1933 ePtr<eServiceEvent> evt;
1934 if (!m_event_handler.getEvent(evt, 0))
1935 return evt->getNumOfLinkageServices();
1939 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1941 ePtr<eServiceEvent> evt;
1942 if (!m_event_handler.getEvent(evt, 0))
1944 if (!evt->getLinkageService(sub, m_reference, n))
1947 sub.type=eServiceReference::idInvalid;
1951 RESULT eDVBServicePlay::startTimeshift()
1953 ePtr<iDVBDemux> demux;
1955 eDebug("Start timeshift!");
1957 if (m_timeshift_enabled)
1960 /* start recording with the data demux. */
1961 if (m_service_handler.getDataDemux(demux))
1964 demux->createTSRecorder(m_record);
1968 char templ[]=TSPATH "/timeshift.XXXXXX";
1969 m_timeshift_fd = mkstemp(templ);
1970 m_timeshift_file = templ;
1972 eDebug("recording to %s", templ);
1974 if (m_timeshift_fd < 0)
1980 m_record->setTargetFD(m_timeshift_fd);
1982 m_timeshift_enabled = 1;
1984 updateTimeshiftPids();
1990 RESULT eDVBServicePlay::stopTimeshift()
1992 if (!m_timeshift_enabled)
1997 m_timeshift_enabled = 0;
2002 close(m_timeshift_fd);
2003 eDebug("remove timeshift file");
2004 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2009 int eDVBServicePlay::isTimeshiftActive()
2011 return m_timeshift_enabled && m_timeshift_active;
2014 RESULT eDVBServicePlay::activateTimeshift()
2016 if (!m_timeshift_enabled)
2019 if (!m_timeshift_active)
2021 switchToTimeshift();
2028 PyObject *eDVBServicePlay::getCutList()
2030 ePyObject list = PyList_New(0);
2032 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2034 ePyObject tuple = PyTuple_New(2);
2035 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2036 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2037 PyList_Append(list, tuple);
2044 void eDVBServicePlay::setCutList(ePyObject list)
2046 if (!PyList_Check(list))
2048 int size = PyList_Size(list);
2051 m_cue_entries.clear();
2053 for (i=0; i<size; ++i)
2055 ePyObject tuple = PyList_GET_ITEM(list, i);
2056 if (!PyTuple_Check(tuple))
2058 eDebug("non-tuple in cutlist");
2061 if (PyTuple_Size(tuple) != 2)
2063 eDebug("cutlist entries need to be a 2-tuple");
2066 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2067 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2069 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2072 pts_t pts = PyLong_AsLongLong(ppts);
2073 int type = PyInt_AsLong(ptype);
2074 m_cue_entries.insert(cueEntry(pts, type));
2075 eDebug("adding %08llx, %d", pts, type);
2077 m_cuesheet_changed = 1;
2079 cutlistToCuesheet();
2080 m_event((iPlayableService*)this, evCuesheetChanged);
2083 void eDVBServicePlay::setCutListEnable(int enable)
2085 m_cutlist_enabled = enable;
2086 cutlistToCuesheet();
2089 void eDVBServicePlay::updateTimeshiftPids()
2094 eDVBServicePMTHandler::program program;
2095 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2097 if (h.getProgramInfo(program))
2101 std::set<int> pids_to_record;
2102 pids_to_record.insert(0); // PAT
2103 if (program.pmtPid != -1)
2104 pids_to_record.insert(program.pmtPid); // PMT
2106 if (program.textPid != -1)
2107 pids_to_record.insert(program.textPid); // Videotext
2109 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2110 i(program.videoStreams.begin());
2111 i != program.videoStreams.end(); ++i)
2112 pids_to_record.insert(i->pid);
2114 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2115 i(program.audioStreams.begin());
2116 i != program.audioStreams.end(); ++i)
2117 pids_to_record.insert(i->pid);
2119 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2120 i(program.subtitleStreams.begin());
2121 i != program.subtitleStreams.end(); ++i)
2122 pids_to_record.insert(i->pid);
2124 std::set<int> new_pids, obsolete_pids;
2126 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2127 m_pids_active.begin(), m_pids_active.end(),
2128 std::inserter(new_pids, new_pids.begin()));
2130 std::set_difference(
2131 m_pids_active.begin(), m_pids_active.end(),
2132 pids_to_record.begin(), pids_to_record.end(),
2133 std::inserter(new_pids, new_pids.begin())
2136 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2137 m_record->addPID(*i);
2139 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2140 m_record->removePID(*i);
2144 void eDVBServicePlay::switchToLive()
2146 if (!m_timeshift_active)
2152 m_teletext_parser = 0;
2154 m_subtitle_parser = 0;
2155 m_new_dvb_subtitle_page_connection = 0;
2156 m_new_subtitle_page_connection = 0;
2157 m_rds_decoder_event_connection = 0;
2158 m_video_event_connection = 0;
2160 /* free the timeshift service handler, we need the resources */
2161 m_service_handler_timeshift.free();
2162 m_timeshift_active = 0;
2164 m_event((iPlayableService*)this, evSeekableStatusChanged);
2169 void eDVBServicePlay::switchToTimeshift()
2171 if (m_timeshift_active)
2176 m_teletext_parser = 0;
2178 m_subtitle_parser = 0;
2179 m_new_subtitle_page_connection = 0;
2180 m_new_dvb_subtitle_page_connection = 0;
2181 m_rds_decoder_event_connection = 0;
2182 m_video_event_connection = 0;
2184 m_timeshift_active = 1;
2186 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2187 r.path = m_timeshift_file;
2189 m_cue = new eCueSheet();
2190 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2191 updateDecoder(); /* mainly to switch off PCR */
2193 m_event((iPlayableService*)this, evSeekableStatusChanged);
2196 void eDVBServicePlay::updateDecoder()
2198 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2200 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2202 bool defaultac3=false;
2203 std::string default_ac3;
2205 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2206 defaultac3 = default_ac3 == "True";
2208 eDVBServicePMTHandler::program program;
2209 if (h.getProgramInfo(program))
2210 eDebug("getting program info failed.");
2213 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2214 if (!program.videoStreams.empty())
2216 eDebugNoNewLine(" (");
2217 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2218 i(program.videoStreams.begin());
2219 i != program.videoStreams.end(); ++i)
2226 if (i != program.videoStreams.begin())
2227 eDebugNoNewLine(", ");
2228 eDebugNoNewLine("%04x", i->pid);
2230 eDebugNoNewLine(")");
2232 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2233 if (!program.audioStreams.empty())
2235 eDebugNoNewLine(" (");
2236 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2237 i(program.audioStreams.begin());
2238 i != program.audioStreams.end(); ++i)
2240 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2242 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2248 if (i != program.audioStreams.begin())
2249 eDebugNoNewLine(", ");
2250 eDebugNoNewLine("%04x", i->pid);
2252 eDebugNoNewLine(")");
2254 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2255 pcrpid = program.pcrPid;
2256 eDebug(", and the text pid is %04x", program.textPid);
2257 tpid = program.textPid;
2262 h.getDecodeDemux(m_decode_demux);
2265 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2267 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2270 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2271 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2272 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2273 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2274 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2281 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2282 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2283 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2285 else // subservice or recording
2287 eServiceReferenceDVB ref;
2288 m_service_handler.getServiceReference(ref);
2289 eServiceReferenceDVB parent = ref.getParentServiceReference();
2294 ePtr<eDVBResourceManager> res_mgr;
2295 if (!eDVBResourceManager::getInstance(res_mgr))
2297 ePtr<iDVBChannelList> db;
2298 if (!res_mgr->getChannelList(db))
2300 ePtr<eDVBService> origService;
2301 if (!db->getService(parent, origService))
2303 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2304 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2310 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2311 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2313 m_decoder->setVideoPID(vpid, vpidtype);
2314 m_decoder->setAudioPID(apid, apidtype);
2315 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2317 m_decoder->setSyncPCR(pcrpid);
2320 ePtr<iDVBDemux> data_demux;
2321 if (!h.getDataDemux(data_demux))
2323 m_rds_decoder = new eDVBRdsDecoder(data_demux);
2324 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
2325 m_rds_decoder->start(apid);
2330 m_decoder->setSyncPCR(-1);
2332 m_decoder->setTextPID(tpid);
2334 m_teletext_parser->start(program.textPid);
2337 m_decoder->setTrickmode(1);
2341 if (vpid > 0 && vpid < 0x2000)
2345 std::string radio_pic;
2346 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2347 m_decoder->setRadioPic(radio_pic);
2350 m_decoder->setAudioChannel(achannel);
2352 // how we can do this better?
2353 // update cache pid when the user changed the audio track or video track
2354 // TODO handling of difference audio types.. default audio types..
2356 /* don't worry about non-existing services, nor pvr services */
2357 if (m_dvb_service && !m_is_pvr)
2359 if (apidtype == eDVBAudio::aMPEG)
2361 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2362 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2366 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2367 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2369 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2370 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2371 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2372 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2375 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2378 void eDVBServicePlay::loadCuesheet()
2380 std::string filename = m_reference.path + ".cuts";
2382 m_cue_entries.clear();
2384 FILE *f = fopen(filename.c_str(), "rb");
2388 eDebug("loading cuts..");
2391 unsigned long long where;
2394 if (!fread(&where, sizeof(where), 1, f))
2396 if (!fread(&what, sizeof(what), 1, f))
2399 #if BYTE_ORDER == LITTLE_ENDIAN
2400 where = bswap_64(where);
2407 m_cue_entries.insert(cueEntry(where, what));
2410 eDebug("%d entries", m_cue_entries.size());
2412 eDebug("cutfile not found!");
2414 m_cuesheet_changed = 0;
2415 cutlistToCuesheet();
2416 m_event((iPlayableService*)this, evCuesheetChanged);
2419 void eDVBServicePlay::saveCuesheet()
2421 std::string filename = m_reference.path + ".cuts";
2423 FILE *f = fopen(filename.c_str(), "wb");
2427 unsigned long long where;
2430 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2432 #if BYTE_ORDER == BIG_ENDIAN
2435 where = bswap_64(i->where);
2437 what = htonl(i->what);
2438 fwrite(&where, sizeof(where), 1, f);
2439 fwrite(&what, sizeof(what), 1, f);
2445 m_cuesheet_changed = 0;
2448 void eDVBServicePlay::cutlistToCuesheet()
2452 eDebug("no cue sheet");
2457 if (!m_cutlist_enabled)
2459 m_cue->commitSpans();
2460 eDebug("cutlists were disabled");
2464 pts_t in = 0, out = 0, length = 0;
2468 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2472 if (i == m_cue_entries.end())
2475 if (i->what == 0) /* in */
2479 } else if (i->what == 1) /* out */
2481 else /* mark (2) or last play position (3) */
2489 m_cue->addSourceSpan(in, out);
2493 if (i == m_cue_entries.end())
2496 m_cue->commitSpans();
2499 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2501 if (m_subtitle_widget)
2502 disableSubtitles(parent);
2505 int tuplesize = PyTuple_Size(tuple);
2508 if (!PyTuple_Check(tuple))
2514 entry = PyTuple_GET_ITEM(tuple, 0);
2516 if (!PyInt_Check(entry))
2519 type = PyInt_AsLong(entry);
2521 if (type == 1) // teletext subtitles
2523 int page, magazine, pid;
2527 if (!m_teletext_parser)
2529 eDebug("enable teletext subtitles.. no parser !!!");
2533 entry = PyTuple_GET_ITEM(tuple, 1);
2534 if (!PyInt_Check(entry))
2536 pid = PyInt_AsLong(entry);
2538 entry = PyTuple_GET_ITEM(tuple, 2);
2539 if (!PyInt_Check(entry))
2541 page = PyInt_AsLong(entry);
2543 entry = PyTuple_GET_ITEM(tuple, 3);
2544 if (!PyInt_Check(entry))
2546 magazine = PyInt_AsLong(entry);
2548 m_subtitle_widget = new eSubtitleWidget(parent);
2549 m_subtitle_widget->resize(parent->size()); /* full size */
2550 m_teletext_parser->setPageAndMagazine(page, magazine);
2552 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2556 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2557 if (!m_subtitle_parser)
2559 eDebug("enable dvb subtitles.. no parser !!!");
2565 entry = PyTuple_GET_ITEM(tuple, 1);
2566 if (!PyInt_Check(entry))
2568 pid = PyInt_AsLong(entry);
2570 entry = PyTuple_GET_ITEM(tuple, 2);
2571 if (!PyInt_Check(entry))
2573 composition_page_id = PyInt_AsLong(entry);
2575 entry = PyTuple_GET_ITEM(tuple, 3);
2576 if (!PyInt_Check(entry))
2578 ancillary_page_id = PyInt_AsLong(entry);
2580 m_subtitle_widget = new eSubtitleWidget(parent);
2581 m_subtitle_widget->resize(parent->size()); /* full size */
2582 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2584 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2590 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2591 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2592 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2596 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2598 delete m_subtitle_widget;
2599 m_subtitle_widget = 0;
2600 if (m_subtitle_parser)
2602 m_subtitle_parser->stop();
2603 m_dvb_subtitle_pages.clear();
2605 if (m_teletext_parser)
2607 m_teletext_parser->setPageAndMagazine(-1, -1);
2608 m_subtitle_pages.clear();
2611 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2615 PyObject *eDVBServicePlay::getCachedSubtitle()
2619 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2622 unsigned int data = (unsigned int)tmp;
2623 int pid = (data&0xFFFF0000)>>16;
2624 ePyObject tuple = PyTuple_New(4);
2625 eDVBServicePMTHandler::program program;
2626 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2627 if (!h.getProgramInfo(program))
2629 if (program.textPid==pid) // teletext
2630 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2632 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2633 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2634 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2635 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2643 PyObject *eDVBServicePlay::getSubtitleList()
2645 if (!m_teletext_parser)
2648 ePyObject l = PyList_New(0);
2649 std::set<int> added_ttx_pages;
2651 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2652 m_teletext_parser->m_found_subtitle_pages;
2654 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2655 eDVBServicePMTHandler::program program;
2656 if (h.getProgramInfo(program))
2657 eDebug("getting program info failed.");
2660 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2661 it != program.subtitleStreams.end(); ++it)
2663 switch(it->subtitling_type)
2665 case 0x01: // ebu teletext subtitles
2667 int page_number = it->teletext_page_number & 0xFF;
2668 int magazine_number = it->teletext_magazine_number & 7;
2669 int hash = magazine_number << 8 | page_number;
2670 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2672 ePyObject tuple = PyTuple_New(5);
2673 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2674 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2675 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2676 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2677 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2678 PyList_Append(l, tuple);
2680 added_ttx_pages.insert(hash);
2685 case 0x20 ... 0x23: // dvb subtitles
2687 ePyObject tuple = PyTuple_New(5);
2688 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2689 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2690 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2691 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2692 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2693 PyList_Insert(l, 0, tuple);
2701 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2702 it != subs.end(); ++it)
2704 int page_number = it->teletext_page_number & 0xFF;
2705 int magazine_number = it->teletext_magazine_number & 7;
2706 int hash = magazine_number << 8 | page_number;
2707 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2709 ePyObject tuple = PyTuple_New(5);
2710 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2711 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2712 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2713 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2714 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2715 PyList_Append(l, tuple);
2723 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2725 if (m_subtitle_widget)
2727 m_subtitle_pages.push_back(page);
2728 checkSubtitleTiming();
2732 void eDVBServicePlay::checkSubtitleTiming()
2734 // eDebug("checkSubtitleTiming");
2735 if (!m_subtitle_widget)
2739 enum { TELETEXT, DVB } type;
2740 eDVBTeletextSubtitlePage page;
2741 eDVBSubtitlePage dvb_page;
2743 if (!m_subtitle_pages.empty())
2745 page = m_subtitle_pages.front();
2747 show_time = page.m_pts;
2749 else if (!m_dvb_subtitle_pages.empty())
2751 dvb_page = m_dvb_subtitle_pages.front();
2753 show_time = dvb_page.m_show_time;
2761 m_decoder->getPTS(0, pos);
2763 // eDebug("%lld %lld", pos, show_time);
2764 int diff = show_time - pos;
2767 eDebug("[late (%d ms)]", -diff / 90);
2772 eDebug("[invalid]");
2778 if (type == TELETEXT)
2780 eDebug("display teletext subtitle page");
2781 m_subtitle_widget->setPage(page);
2782 m_subtitle_pages.pop_front();
2786 eDebug("display dvb subtitle Page");
2787 m_subtitle_widget->setPage(dvb_page);
2788 m_dvb_subtitle_pages.pop_front();
2792 // eDebug("start subtitle delay %d", diff / 90);
2793 m_subtitle_sync_timer.start(diff / 90, 1);
2799 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2801 if (m_subtitle_widget)
2803 m_dvb_subtitle_pages.push_back(p);
2804 checkSubtitleTiming();
2808 int eDVBServicePlay::getAC3Delay()
2811 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2813 return m_decoder->getAC3Delay();
2818 int eDVBServicePlay::getPCMDelay()
2821 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2823 return m_decoder->getPCMDelay();
2828 void eDVBServicePlay::setAC3Delay(int delay)
2831 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2833 m_decoder->setAC3Delay(delay);
2836 void eDVBServicePlay::setPCMDelay(int delay)
2839 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2841 m_decoder->setPCMDelay(delay);
2844 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2846 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2847 m_event((iPlayableService*)this, evVideoSizeChanged);
2850 DEFINE_REF(eDVBServicePlay)
2852 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2856 case iServiceInformation::sTransponderData:
2857 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2861 return iStaticServiceInformation::getInfoObject(ref, w);
2864 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");