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:
1114 if ((!m_is_paused) && (m_skipmode >= 0))
1120 RESULT eDVBServicePlay::start()
1123 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1124 two (one for decoding, one for data source), as we must be prepared
1125 to start recording from the data demux. */
1127 m_cue = new eCueSheet();
1129 m_event(this, evStart);
1131 m_first_program_info = 1;
1132 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1133 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1135 /* inject EIT if there is a stored one */
1138 std::string filename = service.path;
1139 filename.erase(filename.length()-2, 2);
1141 ePtr<eServiceEvent> event = new eServiceEvent;
1142 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1144 ePtr<eServiceEvent> empty;
1145 m_event_handler.inject(event, 0);
1146 m_event_handler.inject(empty, 1);
1153 m_event(this, evStart);
1158 RESULT eDVBServicePlay::stop()
1160 /* add bookmark for last play position */
1163 pts_t play_position, length;
1164 if (!getPlayPosition(play_position))
1166 /* remove last position */
1167 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1169 if (i->what == 3) /* current play position */
1171 m_cue_entries.erase(i);
1172 i = m_cue_entries.begin();
1178 if (getLength(length))
1183 int perc = play_position * 100LL / length;
1185 /* only store last play position when between 5% and 95% */
1186 if ((5 < perc) && (perc < 95))
1187 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1189 m_cuesheet_changed = 1;
1193 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1195 m_service_handler_timeshift.free();
1196 m_service_handler.free();
1198 if (m_is_pvr && m_cuesheet_changed)
1201 /* save cuesheet only when main file is accessible. */
1202 if (!::stat(m_reference.path.c_str(), &s))
1205 m_event((iPlayableService*)this, evStopped);
1209 RESULT eDVBServicePlay::setTarget(int target)
1211 m_is_primary = !target;
1215 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1217 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1221 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1223 /* note: we check for timeshift to be enabled,
1224 not neccessary active. if you pause when timeshift
1225 is not active, you should activate it when unpausing */
1226 if ((!m_is_pvr) && (!m_timeshift_enabled))
1236 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1239 return m_decoder->setSlowMotion(ratio);
1244 RESULT eDVBServicePlay::setFastForward(int ratio)
1246 int skipmode, ffratio;
1252 } else if (ratio > 0)
1260 } else // if (ratio < 0)
1266 if (m_skipmode != skipmode)
1268 eDebug("setting cue skipmode to %d", skipmode);
1270 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1273 m_skipmode = skipmode;
1278 return m_decoder->setFastForward(ffratio);
1281 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1283 if (m_is_pvr || m_timeshift_enabled)
1293 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1294 RESULT eDVBServicePlay::getLength(pts_t &len)
1296 ePtr<iDVBPVRChannel> pvr_channel;
1298 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1301 return pvr_channel->getLength(len);
1304 RESULT eDVBServicePlay::pause()
1306 if (!m_is_paused && m_decoder)
1309 return m_decoder->freeze(0);
1314 RESULT eDVBServicePlay::unpause()
1316 if (m_is_paused && m_decoder)
1319 return m_decoder->unfreeze();
1324 RESULT eDVBServicePlay::seekTo(pts_t to)
1326 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1328 if (!m_decode_demux)
1331 ePtr<iDVBPVRChannel> pvr_channel;
1333 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1339 m_cue->seekTo(0, to);
1343 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1345 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1347 if (!m_decode_demux)
1350 ePtr<iDVBPVRChannel> pvr_channel;
1352 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1357 /* HACK until we have skip-AP api */
1358 if ((to > 0) && (to < 100))
1366 m_cue->seekTo(mode, to);
1370 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1372 ePtr<iDVBPVRChannel> pvr_channel;
1374 if (!m_decode_demux)
1377 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1382 /* if there is a decoder, use audio or video PTS */
1385 r = m_decoder->getPTS(0, pos);
1391 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1394 RESULT eDVBServicePlay::setTrickmode(int trick)
1397 m_decoder->setTrickmode(trick);
1401 RESULT eDVBServicePlay::isCurrentlySeekable()
1403 return m_is_pvr || m_timeshift_active;
1406 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1412 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1418 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1424 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1430 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1436 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1439 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1440 (m_timeshift_enabled || !m_is_pvr))
1442 if (!m_timeshift_enabled)
1444 /* we need enough diskspace */
1446 if (statfs(TSPATH "/.", &fs) < 0)
1448 eDebug("statfs failed!");
1452 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1454 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1464 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1475 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1481 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1487 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1493 RESULT eDVBServicePlay::getName(std::string &name)
1497 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1498 return i->getName(m_reference, name);
1502 m_dvb_service->getName(m_reference, name);
1506 else if (!m_reference.name.empty())
1507 eStaticServiceDVBInformation().getName(m_reference, name);
1509 name = "DVB service";
1513 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1515 return m_event_handler.getEvent(evt, nownext);
1518 int eDVBServicePlay::getInfo(int w)
1520 eDVBServicePMTHandler::program program;
1523 return resIsPyObject;
1525 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1527 int no_program_info = 0;
1529 if (h.getProgramInfo(program))
1530 no_program_info = 1;
1534 #if HAVE_DVB_API_VERSION >= 3
1536 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1537 return m_videoEventData.height;
1540 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1541 return m_videoEventData.width;
1544 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1547 #if HAVE_DVB_API_VERSION >= 3
1548 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1549 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1552 #warning "FIXMEE implement sAspect for old DVB API"
1554 if (no_program_info)
1556 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1558 ePtr<eServiceEvent> evt;
1559 if (!m_event_handler.getEvent(evt, 0))
1561 ePtr<eComponentData> data;
1562 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1564 if ( data->getStreamContent() == 1 )
1566 switch(data->getComponentType())
1569 case 1: // 4:3 SD PAL
1571 case 3: // 16:9 SD PAL
1572 case 4: // > 16:9 PAL
1573 case 5: // 4:3 SD NTSC
1575 case 7: // 16:9 SD NTSC
1576 case 8: // > 16:9 NTSC
1579 case 9: // 4:3 HD PAL
1581 case 0xB: // 16:9 HD PAL
1582 case 0xC: // > 16:9 HD PAL
1583 case 0xD: // 4:3 HD NTSC
1585 case 0xF: // 16:9 HD NTSC
1586 case 0x10: // > 16:9 HD PAL
1587 return data->getComponentType();
1594 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1595 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1596 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1597 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1598 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1599 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1600 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1601 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1602 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1603 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1604 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1605 case sProvider: if (!m_dvb_service) return -1; return -2;
1606 case sServiceref: return resIsString;
1607 case sDVBState: return m_tune_state;
1613 std::string eDVBServicePlay::getInfoString(int w)
1618 if (!m_dvb_service) return "";
1619 return m_dvb_service->m_provider_name;
1621 return m_reference.toString();
1625 return iServiceInformation::getInfoString(w);
1628 PyObject *eDVBServicePlay::getInfoObject(int w)
1633 return m_service_handler.getCaIds();
1634 case sTransponderData:
1635 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1639 return iServiceInformation::getInfoObject(w);
1642 int eDVBServicePlay::getNumberOfTracks()
1644 eDVBServicePMTHandler::program program;
1645 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1646 if (h.getProgramInfo(program))
1648 return program.audioStreams.size();
1651 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1653 int ret = selectAudioStream(i);
1655 if (m_decoder->start())
1661 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1663 eDVBServicePMTHandler::program program;
1664 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1666 if (h.getProgramInfo(program))
1669 if (i >= program.audioStreams.size())
1672 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1673 info.m_description = "MPEG";
1674 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1675 info.m_description = "AC3";
1676 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1677 info.m_description = "AAC";
1678 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1679 info.m_description = "DTS";
1681 info.m_description = "???";
1683 if (program.audioStreams[i].component_tag != -1)
1685 ePtr<eServiceEvent> evt;
1686 if (!m_event_handler.getEvent(evt, 0))
1688 ePtr<eComponentData> data;
1689 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1690 info.m_language = data->getText();
1694 if (info.m_language.empty())
1695 info.m_language = program.audioStreams[i].language_code;
1700 int eDVBServicePlay::selectAudioStream(int i)
1702 eDVBServicePMTHandler::program program;
1703 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1705 if (h.getProgramInfo(program))
1708 if ((unsigned int)i >= program.audioStreams.size())
1714 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1718 m_rds_decoder->start(program.audioStreams[i].pid);
1720 if (m_dvb_service && !m_is_pvr)
1722 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1724 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1725 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1729 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1730 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1734 h.resetCachedProgram();
1739 int eDVBServicePlay::getCurrentChannel()
1741 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1744 RESULT eDVBServicePlay::selectChannel(int i)
1746 if (i < LEFT || i > RIGHT || i == STEREO)
1749 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1751 m_decoder->setAudioChannel(i);
1755 std::string eDVBServicePlay::getText(int x)
1761 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1763 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1768 void eDVBServicePlay::rdsDecoderEvent(int what)
1772 case eDVBRdsDecoder::RadioTextChanged:
1773 m_event((iPlayableService*)this, evUpdatedRadioText);
1775 case eDVBRdsDecoder::RtpTextChanged:
1776 m_event((iPlayableService*)this, evUpdatedRtpText);
1778 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1779 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1781 case eDVBRdsDecoder::RecvRassSlidePic:
1782 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1787 void eDVBServicePlay::showRassSlidePicture()
1793 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1794 if (rass_slide_pic.length())
1795 m_decoder->showSinglePic(rass_slide_pic.c_str());
1797 eDebug("empty filename for rass slide picture received!!");
1800 eDebug("no MPEG Decoder to show iframes avail");
1803 eDebug("showRassSlidePicture called.. but not decoder");
1806 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1812 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1813 if (rass_interactive_pic.length())
1814 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1816 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1819 eDebug("no MPEG Decoder to show iframes avail");
1822 eDebug("showRassInteractivePic called.. but not decoder");
1825 ePyObject eDVBServicePlay::getRassInteractiveMask()
1828 return m_rds_decoder->getRassPictureMask();
1832 int eDVBServiceBase::getFrontendInfo(int w)
1834 eUsePtr<iDVBChannel> channel;
1835 if(m_service_handler.getChannel(channel))
1837 ePtr<iDVBFrontend> fe;
1838 if(channel->getFrontend(fe))
1840 return fe->readFrontendData(w);
1843 PyObject *eDVBServiceBase::getFrontendData()
1845 ePyObject ret = PyDict_New();
1848 eUsePtr<iDVBChannel> channel;
1849 if(!m_service_handler.getChannel(channel))
1851 ePtr<iDVBFrontend> fe;
1852 if(!channel->getFrontend(fe))
1853 fe->getFrontendData(ret);
1861 PyObject *eDVBServiceBase::getFrontendStatus()
1863 ePyObject ret = PyDict_New();
1866 eUsePtr<iDVBChannel> channel;
1867 if(!m_service_handler.getChannel(channel))
1869 ePtr<iDVBFrontend> fe;
1870 if(!channel->getFrontend(fe))
1871 fe->getFrontendStatus(ret);
1879 PyObject *eDVBServiceBase::getTransponderData(bool original)
1881 ePyObject ret = PyDict_New();
1884 eUsePtr<iDVBChannel> channel;
1885 if(!m_service_handler.getChannel(channel))
1887 ePtr<iDVBFrontend> fe;
1888 if(!channel->getFrontend(fe))
1890 fe->getTransponderData(ret, original);
1891 ePtr<iDVBFrontendParameters> feparm;
1892 channel->getCurrentFrontendParameters(feparm);
1895 eDVBFrontendParametersSatellite osat;
1896 if (!feparm->getDVBS(osat))
1898 void PutToDict(ePyObject &, const char*, long);
1899 void PutToDict(ePyObject &, const char*, const char*);
1900 PutToDict(ret, "orbital_position", osat.orbital_position);
1901 const char *tmp = "UNKNOWN";
1902 switch(osat.polarisation)
1904 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1905 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1906 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1907 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1910 PutToDict(ret, "polarization", tmp);
1921 PyObject *eDVBServiceBase::getAll(bool original)
1923 ePyObject ret = getTransponderData(original);
1926 eUsePtr<iDVBChannel> channel;
1927 if(!m_service_handler.getChannel(channel))
1929 ePtr<iDVBFrontend> fe;
1930 if(!channel->getFrontend(fe))
1932 fe->getFrontendData(ret);
1933 fe->getFrontendStatus(ret);
1940 int eDVBServicePlay::getNumberOfSubservices()
1942 ePtr<eServiceEvent> evt;
1943 if (!m_event_handler.getEvent(evt, 0))
1944 return evt->getNumOfLinkageServices();
1948 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1950 ePtr<eServiceEvent> evt;
1951 if (!m_event_handler.getEvent(evt, 0))
1953 if (!evt->getLinkageService(sub, m_reference, n))
1956 sub.type=eServiceReference::idInvalid;
1960 RESULT eDVBServicePlay::startTimeshift()
1962 ePtr<iDVBDemux> demux;
1964 eDebug("Start timeshift!");
1966 if (m_timeshift_enabled)
1969 /* start recording with the data demux. */
1970 if (m_service_handler.getDataDemux(demux))
1973 demux->createTSRecorder(m_record);
1977 char templ[]=TSPATH "/timeshift.XXXXXX";
1978 m_timeshift_fd = mkstemp(templ);
1979 m_timeshift_file = templ;
1981 eDebug("recording to %s", templ);
1983 if (m_timeshift_fd < 0)
1989 m_record->setTargetFD(m_timeshift_fd);
1991 m_timeshift_enabled = 1;
1993 updateTimeshiftPids();
1999 RESULT eDVBServicePlay::stopTimeshift()
2001 if (!m_timeshift_enabled)
2006 m_timeshift_enabled = 0;
2011 close(m_timeshift_fd);
2012 eDebug("remove timeshift file");
2013 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2018 int eDVBServicePlay::isTimeshiftActive()
2020 return m_timeshift_enabled && m_timeshift_active;
2023 RESULT eDVBServicePlay::activateTimeshift()
2025 if (!m_timeshift_enabled)
2028 if (!m_timeshift_active)
2030 switchToTimeshift();
2037 PyObject *eDVBServicePlay::getCutList()
2039 ePyObject list = PyList_New(0);
2041 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2043 ePyObject tuple = PyTuple_New(2);
2044 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2045 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2046 PyList_Append(list, tuple);
2053 void eDVBServicePlay::setCutList(ePyObject list)
2055 if (!PyList_Check(list))
2057 int size = PyList_Size(list);
2060 m_cue_entries.clear();
2062 for (i=0; i<size; ++i)
2064 ePyObject tuple = PyList_GET_ITEM(list, i);
2065 if (!PyTuple_Check(tuple))
2067 eDebug("non-tuple in cutlist");
2070 if (PyTuple_Size(tuple) != 2)
2072 eDebug("cutlist entries need to be a 2-tuple");
2075 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2076 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2078 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2081 pts_t pts = PyLong_AsLongLong(ppts);
2082 int type = PyInt_AsLong(ptype);
2083 m_cue_entries.insert(cueEntry(pts, type));
2084 eDebug("adding %08llx, %d", pts, type);
2086 m_cuesheet_changed = 1;
2088 cutlistToCuesheet();
2089 m_event((iPlayableService*)this, evCuesheetChanged);
2092 void eDVBServicePlay::setCutListEnable(int enable)
2094 m_cutlist_enabled = enable;
2095 cutlistToCuesheet();
2098 void eDVBServicePlay::updateTimeshiftPids()
2103 eDVBServicePMTHandler::program program;
2104 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2106 if (h.getProgramInfo(program))
2110 std::set<int> pids_to_record;
2111 pids_to_record.insert(0); // PAT
2112 if (program.pmtPid != -1)
2113 pids_to_record.insert(program.pmtPid); // PMT
2115 if (program.textPid != -1)
2116 pids_to_record.insert(program.textPid); // Videotext
2118 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2119 i(program.videoStreams.begin());
2120 i != program.videoStreams.end(); ++i)
2121 pids_to_record.insert(i->pid);
2123 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2124 i(program.audioStreams.begin());
2125 i != program.audioStreams.end(); ++i)
2126 pids_to_record.insert(i->pid);
2128 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2129 i(program.subtitleStreams.begin());
2130 i != program.subtitleStreams.end(); ++i)
2131 pids_to_record.insert(i->pid);
2133 std::set<int> new_pids, obsolete_pids;
2135 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2136 m_pids_active.begin(), m_pids_active.end(),
2137 std::inserter(new_pids, new_pids.begin()));
2139 std::set_difference(
2140 m_pids_active.begin(), m_pids_active.end(),
2141 pids_to_record.begin(), pids_to_record.end(),
2142 std::inserter(new_pids, new_pids.begin())
2145 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2146 m_record->addPID(*i);
2148 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2149 m_record->removePID(*i);
2153 void eDVBServicePlay::switchToLive()
2155 if (!m_timeshift_active)
2161 m_teletext_parser = 0;
2163 m_subtitle_parser = 0;
2164 m_new_dvb_subtitle_page_connection = 0;
2165 m_new_subtitle_page_connection = 0;
2166 m_rds_decoder_event_connection = 0;
2167 m_video_event_connection = 0;
2169 /* free the timeshift service handler, we need the resources */
2170 m_service_handler_timeshift.free();
2171 m_timeshift_active = 0;
2173 m_event((iPlayableService*)this, evSeekableStatusChanged);
2178 void eDVBServicePlay::switchToTimeshift()
2180 if (m_timeshift_active)
2185 m_teletext_parser = 0;
2187 m_subtitle_parser = 0;
2188 m_new_subtitle_page_connection = 0;
2189 m_new_dvb_subtitle_page_connection = 0;
2190 m_rds_decoder_event_connection = 0;
2191 m_video_event_connection = 0;
2193 m_timeshift_active = 1;
2195 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2196 r.path = m_timeshift_file;
2198 m_cue = new eCueSheet();
2199 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2201 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2203 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2205 m_event((iPlayableService*)this, evSeekableStatusChanged);
2208 void eDVBServicePlay::updateDecoder()
2210 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2212 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2214 bool defaultac3=false;
2215 std::string default_ac3;
2217 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2218 defaultac3 = default_ac3 == "True";
2220 eDVBServicePMTHandler::program program;
2221 if (h.getProgramInfo(program))
2222 eDebug("getting program info failed.");
2225 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2226 if (!program.videoStreams.empty())
2228 eDebugNoNewLine(" (");
2229 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2230 i(program.videoStreams.begin());
2231 i != program.videoStreams.end(); ++i)
2238 if (i != program.videoStreams.begin())
2239 eDebugNoNewLine(", ");
2240 eDebugNoNewLine("%04x", i->pid);
2242 eDebugNoNewLine(")");
2244 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2245 if (!program.audioStreams.empty())
2247 eDebugNoNewLine(" (");
2248 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2249 i(program.audioStreams.begin());
2250 i != program.audioStreams.end(); ++i)
2252 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2254 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2260 if (i != program.audioStreams.begin())
2261 eDebugNoNewLine(", ");
2262 eDebugNoNewLine("%04x", i->pid);
2264 eDebugNoNewLine(")");
2266 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2267 pcrpid = program.pcrPid;
2268 eDebug(", and the text pid is %04x", program.textPid);
2269 tpid = program.textPid;
2274 h.getDecodeDemux(m_decode_demux);
2277 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2279 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2282 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2283 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2284 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2285 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2286 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2293 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2294 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2295 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2297 else // subservice or recording
2299 eServiceReferenceDVB ref;
2300 m_service_handler.getServiceReference(ref);
2301 eServiceReferenceDVB parent = ref.getParentServiceReference();
2306 ePtr<eDVBResourceManager> res_mgr;
2307 if (!eDVBResourceManager::getInstance(res_mgr))
2309 ePtr<iDVBChannelList> db;
2310 if (!res_mgr->getChannelList(db))
2312 ePtr<eDVBService> origService;
2313 if (!db->getService(parent, origService))
2315 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2316 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2322 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2323 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2325 m_decoder->setVideoPID(vpid, vpidtype);
2326 m_decoder->setAudioPID(apid, apidtype);
2327 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2329 m_decoder->setSyncPCR(pcrpid);
2332 ePtr<iDVBDemux> data_demux;
2333 if (!h.getDataDemux(data_demux))
2335 m_rds_decoder = new eDVBRdsDecoder(data_demux);
2336 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
2337 m_rds_decoder->start(apid);
2342 m_decoder->setSyncPCR(-1);
2344 m_decoder->setTextPID(tpid);
2346 m_teletext_parser->start(program.textPid);
2349 m_decoder->setTrickmode(1);
2352 m_decoder->preroll();
2356 if (vpid > 0 && vpid < 0x2000)
2360 std::string radio_pic;
2361 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2362 m_decoder->setRadioPic(radio_pic);
2365 m_decoder->setAudioChannel(achannel);
2367 // how we can do this better?
2368 // update cache pid when the user changed the audio track or video track
2369 // TODO handling of difference audio types.. default audio types..
2371 /* don't worry about non-existing services, nor pvr services */
2372 if (m_dvb_service && !m_is_pvr)
2374 if (apidtype == eDVBAudio::aMPEG)
2376 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2377 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2381 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2382 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2384 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2385 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2386 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2387 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2390 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2393 void eDVBServicePlay::loadCuesheet()
2395 std::string filename = m_reference.path + ".cuts";
2397 m_cue_entries.clear();
2399 FILE *f = fopen(filename.c_str(), "rb");
2403 eDebug("loading cuts..");
2406 unsigned long long where;
2409 if (!fread(&where, sizeof(where), 1, f))
2411 if (!fread(&what, sizeof(what), 1, f))
2414 #if BYTE_ORDER == LITTLE_ENDIAN
2415 where = bswap_64(where);
2422 m_cue_entries.insert(cueEntry(where, what));
2425 eDebug("%d entries", m_cue_entries.size());
2427 eDebug("cutfile not found!");
2429 m_cuesheet_changed = 0;
2430 cutlistToCuesheet();
2431 m_event((iPlayableService*)this, evCuesheetChanged);
2434 void eDVBServicePlay::saveCuesheet()
2436 std::string filename = m_reference.path + ".cuts";
2438 FILE *f = fopen(filename.c_str(), "wb");
2442 unsigned long long where;
2445 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2447 #if BYTE_ORDER == BIG_ENDIAN
2450 where = bswap_64(i->where);
2452 what = htonl(i->what);
2453 fwrite(&where, sizeof(where), 1, f);
2454 fwrite(&what, sizeof(what), 1, f);
2460 m_cuesheet_changed = 0;
2463 void eDVBServicePlay::cutlistToCuesheet()
2467 eDebug("no cue sheet");
2472 if (!m_cutlist_enabled)
2474 m_cue->commitSpans();
2475 eDebug("cutlists were disabled");
2479 pts_t in = 0, out = 0, length = 0;
2483 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2487 if (i == m_cue_entries.end())
2490 if (i->what == 0) /* in */
2494 } else if (i->what == 1) /* out */
2496 else /* mark (2) or last play position (3) */
2504 m_cue->addSourceSpan(in, out);
2508 if (i == m_cue_entries.end())
2511 m_cue->commitSpans();
2514 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2516 if (m_subtitle_widget)
2517 disableSubtitles(parent);
2520 int tuplesize = PyTuple_Size(tuple);
2523 if (!PyTuple_Check(tuple))
2529 entry = PyTuple_GET_ITEM(tuple, 0);
2531 if (!PyInt_Check(entry))
2534 type = PyInt_AsLong(entry);
2536 if (type == 1) // teletext subtitles
2538 int page, magazine, pid;
2542 if (!m_teletext_parser)
2544 eDebug("enable teletext subtitles.. no parser !!!");
2548 entry = PyTuple_GET_ITEM(tuple, 1);
2549 if (!PyInt_Check(entry))
2551 pid = PyInt_AsLong(entry);
2553 entry = PyTuple_GET_ITEM(tuple, 2);
2554 if (!PyInt_Check(entry))
2556 page = PyInt_AsLong(entry);
2558 entry = PyTuple_GET_ITEM(tuple, 3);
2559 if (!PyInt_Check(entry))
2561 magazine = PyInt_AsLong(entry);
2563 m_subtitle_widget = new eSubtitleWidget(parent);
2564 m_subtitle_widget->resize(parent->size()); /* full size */
2565 m_teletext_parser->setPageAndMagazine(page, magazine);
2567 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2571 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2572 if (!m_subtitle_parser)
2574 eDebug("enable dvb subtitles.. no parser !!!");
2580 entry = PyTuple_GET_ITEM(tuple, 1);
2581 if (!PyInt_Check(entry))
2583 pid = PyInt_AsLong(entry);
2585 entry = PyTuple_GET_ITEM(tuple, 2);
2586 if (!PyInt_Check(entry))
2588 composition_page_id = PyInt_AsLong(entry);
2590 entry = PyTuple_GET_ITEM(tuple, 3);
2591 if (!PyInt_Check(entry))
2593 ancillary_page_id = PyInt_AsLong(entry);
2595 m_subtitle_widget = new eSubtitleWidget(parent);
2596 m_subtitle_widget->resize(parent->size()); /* full size */
2597 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2599 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2605 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2606 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2607 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2611 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2613 delete m_subtitle_widget;
2614 m_subtitle_widget = 0;
2615 if (m_subtitle_parser)
2617 m_subtitle_parser->stop();
2618 m_dvb_subtitle_pages.clear();
2620 if (m_teletext_parser)
2622 m_teletext_parser->setPageAndMagazine(-1, -1);
2623 m_subtitle_pages.clear();
2626 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2630 PyObject *eDVBServicePlay::getCachedSubtitle()
2634 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2637 unsigned int data = (unsigned int)tmp;
2638 int pid = (data&0xFFFF0000)>>16;
2639 ePyObject tuple = PyTuple_New(4);
2640 eDVBServicePMTHandler::program program;
2641 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2642 if (!h.getProgramInfo(program))
2644 if (program.textPid==pid) // teletext
2645 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2647 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2648 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2649 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2650 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2658 PyObject *eDVBServicePlay::getSubtitleList()
2660 if (!m_teletext_parser)
2663 ePyObject l = PyList_New(0);
2664 std::set<int> added_ttx_pages;
2666 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2667 m_teletext_parser->m_found_subtitle_pages;
2669 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2670 eDVBServicePMTHandler::program program;
2671 if (h.getProgramInfo(program))
2672 eDebug("getting program info failed.");
2675 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2676 it != program.subtitleStreams.end(); ++it)
2678 switch(it->subtitling_type)
2680 case 0x01: // ebu teletext subtitles
2682 int page_number = it->teletext_page_number & 0xFF;
2683 int magazine_number = it->teletext_magazine_number & 7;
2684 int hash = magazine_number << 8 | page_number;
2685 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2687 ePyObject tuple = PyTuple_New(5);
2688 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2689 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2690 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2691 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2692 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2693 PyList_Append(l, tuple);
2695 added_ttx_pages.insert(hash);
2700 case 0x20 ... 0x23: // dvb subtitles
2702 ePyObject tuple = PyTuple_New(5);
2703 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2704 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2705 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2706 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2707 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2708 PyList_Insert(l, 0, tuple);
2716 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2717 it != subs.end(); ++it)
2719 int page_number = it->teletext_page_number & 0xFF;
2720 int magazine_number = it->teletext_magazine_number & 7;
2721 int hash = magazine_number << 8 | page_number;
2722 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2724 ePyObject tuple = PyTuple_New(5);
2725 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2726 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2727 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2728 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2729 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2730 PyList_Append(l, tuple);
2738 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2740 if (m_subtitle_widget)
2742 m_subtitle_pages.push_back(page);
2743 checkSubtitleTiming();
2747 void eDVBServicePlay::checkSubtitleTiming()
2749 // eDebug("checkSubtitleTiming");
2750 if (!m_subtitle_widget)
2754 enum { TELETEXT, DVB } type;
2755 eDVBTeletextSubtitlePage page;
2756 eDVBSubtitlePage dvb_page;
2758 if (!m_subtitle_pages.empty())
2760 page = m_subtitle_pages.front();
2762 show_time = page.m_pts;
2764 else if (!m_dvb_subtitle_pages.empty())
2766 dvb_page = m_dvb_subtitle_pages.front();
2768 show_time = dvb_page.m_show_time;
2776 m_decoder->getPTS(0, pos);
2778 // eDebug("%lld %lld", pos, show_time);
2779 int diff = show_time - pos;
2782 eDebug("[late (%d ms)]", -diff / 90);
2787 eDebug("[invalid]");
2793 if (type == TELETEXT)
2795 eDebug("display teletext subtitle page");
2796 m_subtitle_widget->setPage(page);
2797 m_subtitle_pages.pop_front();
2801 eDebug("display dvb subtitle Page");
2802 m_subtitle_widget->setPage(dvb_page);
2803 m_dvb_subtitle_pages.pop_front();
2807 // eDebug("start subtitle delay %d", diff / 90);
2808 m_subtitle_sync_timer.start(diff / 90, 1);
2814 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2816 if (m_subtitle_widget)
2818 m_dvb_subtitle_pages.push_back(p);
2819 checkSubtitleTiming();
2823 int eDVBServicePlay::getAC3Delay()
2826 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2828 return m_decoder->getAC3Delay();
2833 int eDVBServicePlay::getPCMDelay()
2836 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2838 return m_decoder->getPCMDelay();
2843 void eDVBServicePlay::setAC3Delay(int delay)
2846 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2848 m_decoder->setAC3Delay(delay);
2851 void eDVBServicePlay::setPCMDelay(int delay)
2854 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2856 m_decoder->setPCMDelay(delay);
2859 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2861 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2862 m_event((iPlayableService*)this, evVideoSizeChanged);
2865 DEFINE_REF(eDVBServicePlay)
2867 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2871 case iServiceInformation::sTransponderData:
2872 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2876 return iStaticServiceInformation::getInfoObject(ref, w);
2879 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");