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))
1181 int perc = play_position * 100LL / length;
1183 /* only store last play position when between 5% and 95% */
1184 if ((5 < perc) && (perc < 95))
1185 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1186 m_cuesheet_changed = 1;
1190 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1192 m_service_handler_timeshift.free();
1193 m_service_handler.free();
1195 if (m_is_pvr && m_cuesheet_changed)
1198 /* save cuesheet only when main file is accessible. */
1199 if (!::stat(m_reference.path.c_str(), &s))
1202 m_event((iPlayableService*)this, evStopped);
1206 RESULT eDVBServicePlay::setTarget(int target)
1208 m_is_primary = !target;
1212 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1214 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1218 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1220 /* note: we check for timeshift to be enabled,
1221 not neccessary active. if you pause when timeshift
1222 is not active, you should activate it when unpausing */
1223 if ((!m_is_pvr) && (!m_timeshift_enabled))
1233 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1236 return m_decoder->setSlowMotion(ratio);
1241 RESULT eDVBServicePlay::setFastForward(int ratio)
1243 int skipmode, ffratio;
1249 } else if (ratio > 0)
1257 } else // if (ratio < 0)
1263 if (m_skipmode != skipmode)
1265 eDebug("setting cue skipmode to %d", skipmode);
1267 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1270 m_skipmode = skipmode;
1275 return m_decoder->setFastForward(ffratio);
1278 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1280 if (m_is_pvr || m_timeshift_enabled)
1290 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1291 RESULT eDVBServicePlay::getLength(pts_t &len)
1293 ePtr<iDVBPVRChannel> pvr_channel;
1295 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1298 return pvr_channel->getLength(len);
1301 RESULT eDVBServicePlay::pause()
1303 if (!m_is_paused && m_decoder)
1306 return m_decoder->freeze(0);
1311 RESULT eDVBServicePlay::unpause()
1313 if (m_is_paused && m_decoder)
1316 return m_decoder->unfreeze();
1321 RESULT eDVBServicePlay::seekTo(pts_t to)
1323 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1325 if (!m_decode_demux)
1328 ePtr<iDVBPVRChannel> pvr_channel;
1330 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1336 m_cue->seekTo(0, to);
1340 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1342 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1344 if (!m_decode_demux)
1347 ePtr<iDVBPVRChannel> pvr_channel;
1349 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1354 /* HACK until we have skip-AP api */
1355 if ((to > 0) && (to < 100))
1363 m_cue->seekTo(mode, to);
1367 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1369 ePtr<iDVBPVRChannel> pvr_channel;
1371 if (!m_decode_demux)
1374 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1379 /* if there is a decoder, use audio or video PTS */
1382 r = m_decoder->getPTS(0, pos);
1388 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1391 RESULT eDVBServicePlay::setTrickmode(int trick)
1394 m_decoder->setTrickmode(trick);
1398 RESULT eDVBServicePlay::isCurrentlySeekable()
1400 return m_is_pvr || m_timeshift_active;
1403 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1409 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1415 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1421 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1427 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1433 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1436 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1437 (m_timeshift_enabled || !m_is_pvr))
1439 if (!m_timeshift_enabled)
1441 /* we need enough diskspace */
1443 if (statfs(TSPATH "/.", &fs) < 0)
1445 eDebug("statfs failed!");
1449 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1451 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1461 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1472 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1478 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1484 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1490 RESULT eDVBServicePlay::getName(std::string &name)
1494 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1495 return i->getName(m_reference, name);
1499 m_dvb_service->getName(m_reference, name);
1503 else if (!m_reference.name.empty())
1504 eStaticServiceDVBInformation().getName(m_reference, name);
1506 name = "DVB service";
1510 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1512 return m_event_handler.getEvent(evt, nownext);
1515 int eDVBServicePlay::getInfo(int w)
1517 eDVBServicePMTHandler::program program;
1520 return resIsPyObject;
1522 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1524 int no_program_info = 0;
1526 if (h.getProgramInfo(program))
1527 no_program_info = 1;
1531 #if HAVE_DVB_API_VERSION >= 3
1533 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1534 return m_videoEventData.height;
1537 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1538 return m_videoEventData.width;
1541 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1544 #if HAVE_DVB_API_VERSION >= 3
1545 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1546 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1549 #warning "FIXMEE implement sAspect for old DVB API"
1551 if (no_program_info)
1553 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1555 ePtr<eServiceEvent> evt;
1556 if (!m_event_handler.getEvent(evt, 0))
1558 ePtr<eComponentData> data;
1559 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1561 if ( data->getStreamContent() == 1 )
1563 switch(data->getComponentType())
1566 case 1: // 4:3 SD PAL
1568 case 3: // 16:9 SD PAL
1569 case 4: // > 16:9 PAL
1570 case 5: // 4:3 SD NTSC
1572 case 7: // 16:9 SD NTSC
1573 case 8: // > 16:9 NTSC
1576 case 9: // 4:3 HD PAL
1578 case 0xB: // 16:9 HD PAL
1579 case 0xC: // > 16:9 HD PAL
1580 case 0xD: // 4:3 HD NTSC
1582 case 0xF: // 16:9 HD NTSC
1583 case 0x10: // > 16:9 HD PAL
1584 return data->getComponentType();
1591 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1592 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1593 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1594 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1595 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1596 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1597 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1598 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1599 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1600 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1601 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1602 case sProvider: if (!m_dvb_service) return -1; return -2;
1603 case sServiceref: return resIsString;
1604 case sDVBState: return m_tune_state;
1610 std::string eDVBServicePlay::getInfoString(int w)
1615 if (!m_dvb_service) return "";
1616 return m_dvb_service->m_provider_name;
1618 return m_reference.toString();
1622 return iServiceInformation::getInfoString(w);
1625 PyObject *eDVBServicePlay::getInfoObject(int w)
1630 return m_service_handler.getCaIds();
1631 case sTransponderData:
1632 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1636 return iServiceInformation::getInfoObject(w);
1639 int eDVBServicePlay::getNumberOfTracks()
1641 eDVBServicePMTHandler::program program;
1642 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1643 if (h.getProgramInfo(program))
1645 return program.audioStreams.size();
1648 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1650 int ret = selectAudioStream(i);
1652 if (m_decoder->start())
1658 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1660 eDVBServicePMTHandler::program program;
1661 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1663 if (h.getProgramInfo(program))
1666 if (i >= program.audioStreams.size())
1669 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1670 info.m_description = "MPEG";
1671 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1672 info.m_description = "AC3";
1673 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1674 info.m_description = "AAC";
1675 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1676 info.m_description = "DTS";
1678 info.m_description = "???";
1680 if (program.audioStreams[i].component_tag != -1)
1682 ePtr<eServiceEvent> evt;
1683 if (!m_event_handler.getEvent(evt, 0))
1685 ePtr<eComponentData> data;
1686 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1687 info.m_language = data->getText();
1691 if (info.m_language.empty())
1692 info.m_language = program.audioStreams[i].language_code;
1697 int eDVBServicePlay::selectAudioStream(int i)
1699 eDVBServicePMTHandler::program program;
1700 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1702 if (h.getProgramInfo(program))
1705 if ((unsigned int)i >= program.audioStreams.size())
1711 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1715 m_rds_decoder->start(program.audioStreams[i].pid);
1717 if (m_dvb_service && !m_is_pvr)
1719 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1721 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1722 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1726 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1727 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1731 h.resetCachedProgram();
1736 int eDVBServicePlay::getCurrentChannel()
1738 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1741 RESULT eDVBServicePlay::selectChannel(int i)
1743 if (i < LEFT || i > RIGHT || i == STEREO)
1746 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1748 m_decoder->setAudioChannel(i);
1752 std::string eDVBServicePlay::getText(int x)
1758 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1760 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1765 void eDVBServicePlay::rdsDecoderEvent(int what)
1769 case eDVBRdsDecoder::RadioTextChanged:
1770 m_event((iPlayableService*)this, evUpdatedRadioText);
1772 case eDVBRdsDecoder::RtpTextChanged:
1773 m_event((iPlayableService*)this, evUpdatedRtpText);
1775 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1776 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1778 case eDVBRdsDecoder::RecvRassSlidePic:
1779 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1784 void eDVBServicePlay::showRassSlidePicture()
1790 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1791 if (rass_slide_pic.length())
1792 m_decoder->showSinglePic(rass_slide_pic.c_str());
1794 eDebug("empty filename for rass slide picture received!!");
1797 eDebug("no MPEG Decoder to show iframes avail");
1800 eDebug("showRassSlidePicture called.. but not decoder");
1803 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1809 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1810 if (rass_interactive_pic.length())
1811 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1813 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1816 eDebug("no MPEG Decoder to show iframes avail");
1819 eDebug("showRassInteractivePic called.. but not decoder");
1822 ePyObject eDVBServicePlay::getRassInteractiveMask()
1825 return m_rds_decoder->getRassPictureMask();
1829 int eDVBServiceBase::getFrontendInfo(int w)
1831 eUsePtr<iDVBChannel> channel;
1832 if(m_service_handler.getChannel(channel))
1834 ePtr<iDVBFrontend> fe;
1835 if(channel->getFrontend(fe))
1837 return fe->readFrontendData(w);
1840 PyObject *eDVBServiceBase::getFrontendData()
1842 ePyObject ret = PyDict_New();
1845 eUsePtr<iDVBChannel> channel;
1846 if(!m_service_handler.getChannel(channel))
1848 ePtr<iDVBFrontend> fe;
1849 if(!channel->getFrontend(fe))
1850 fe->getFrontendData(ret);
1858 PyObject *eDVBServiceBase::getFrontendStatus()
1860 ePyObject ret = PyDict_New();
1863 eUsePtr<iDVBChannel> channel;
1864 if(!m_service_handler.getChannel(channel))
1866 ePtr<iDVBFrontend> fe;
1867 if(!channel->getFrontend(fe))
1868 fe->getFrontendStatus(ret);
1876 PyObject *eDVBServiceBase::getTransponderData(bool original)
1878 ePyObject ret = PyDict_New();
1881 eUsePtr<iDVBChannel> channel;
1882 if(!m_service_handler.getChannel(channel))
1884 ePtr<iDVBFrontend> fe;
1885 if(!channel->getFrontend(fe))
1887 fe->getTransponderData(ret, original);
1888 ePtr<iDVBFrontendParameters> feparm;
1889 channel->getCurrentFrontendParameters(feparm);
1892 eDVBFrontendParametersSatellite osat;
1893 if (!feparm->getDVBS(osat))
1895 void PutToDict(ePyObject &, const char*, long);
1896 void PutToDict(ePyObject &, const char*, const char*);
1897 PutToDict(ret, "orbital_position", osat.orbital_position);
1898 const char *tmp = "UNKNOWN";
1899 switch(osat.polarisation)
1901 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1902 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1903 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1904 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1907 PutToDict(ret, "polarization", tmp);
1918 PyObject *eDVBServiceBase::getAll(bool original)
1920 ePyObject ret = getTransponderData(original);
1923 eUsePtr<iDVBChannel> channel;
1924 if(!m_service_handler.getChannel(channel))
1926 ePtr<iDVBFrontend> fe;
1927 if(!channel->getFrontend(fe))
1929 fe->getFrontendData(ret);
1930 fe->getFrontendStatus(ret);
1937 int eDVBServicePlay::getNumberOfSubservices()
1939 ePtr<eServiceEvent> evt;
1940 if (!m_event_handler.getEvent(evt, 0))
1941 return evt->getNumOfLinkageServices();
1945 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1947 ePtr<eServiceEvent> evt;
1948 if (!m_event_handler.getEvent(evt, 0))
1950 if (!evt->getLinkageService(sub, m_reference, n))
1953 sub.type=eServiceReference::idInvalid;
1957 RESULT eDVBServicePlay::startTimeshift()
1959 ePtr<iDVBDemux> demux;
1961 eDebug("Start timeshift!");
1963 if (m_timeshift_enabled)
1966 /* start recording with the data demux. */
1967 if (m_service_handler.getDataDemux(demux))
1970 demux->createTSRecorder(m_record);
1974 char templ[]=TSPATH "/timeshift.XXXXXX";
1975 m_timeshift_fd = mkstemp(templ);
1976 m_timeshift_file = templ;
1978 eDebug("recording to %s", templ);
1980 if (m_timeshift_fd < 0)
1986 m_record->setTargetFD(m_timeshift_fd);
1988 m_timeshift_enabled = 1;
1990 updateTimeshiftPids();
1996 RESULT eDVBServicePlay::stopTimeshift()
1998 if (!m_timeshift_enabled)
2003 m_timeshift_enabled = 0;
2008 close(m_timeshift_fd);
2009 eDebug("remove timeshift file");
2010 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2015 int eDVBServicePlay::isTimeshiftActive()
2017 return m_timeshift_enabled && m_timeshift_active;
2020 RESULT eDVBServicePlay::activateTimeshift()
2022 if (!m_timeshift_enabled)
2025 if (!m_timeshift_active)
2027 switchToTimeshift();
2034 PyObject *eDVBServicePlay::getCutList()
2036 ePyObject list = PyList_New(0);
2038 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2040 ePyObject tuple = PyTuple_New(2);
2041 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2042 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2043 PyList_Append(list, tuple);
2050 void eDVBServicePlay::setCutList(ePyObject list)
2052 if (!PyList_Check(list))
2054 int size = PyList_Size(list);
2057 m_cue_entries.clear();
2059 for (i=0; i<size; ++i)
2061 ePyObject tuple = PyList_GET_ITEM(list, i);
2062 if (!PyTuple_Check(tuple))
2064 eDebug("non-tuple in cutlist");
2067 if (PyTuple_Size(tuple) != 2)
2069 eDebug("cutlist entries need to be a 2-tuple");
2072 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2073 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2075 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2078 pts_t pts = PyLong_AsLongLong(ppts);
2079 int type = PyInt_AsLong(ptype);
2080 m_cue_entries.insert(cueEntry(pts, type));
2081 eDebug("adding %08llx, %d", pts, type);
2083 m_cuesheet_changed = 1;
2085 cutlistToCuesheet();
2086 m_event((iPlayableService*)this, evCuesheetChanged);
2089 void eDVBServicePlay::setCutListEnable(int enable)
2091 m_cutlist_enabled = enable;
2092 cutlistToCuesheet();
2095 void eDVBServicePlay::updateTimeshiftPids()
2100 eDVBServicePMTHandler::program program;
2101 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2103 if (h.getProgramInfo(program))
2107 std::set<int> pids_to_record;
2108 pids_to_record.insert(0); // PAT
2109 if (program.pmtPid != -1)
2110 pids_to_record.insert(program.pmtPid); // PMT
2112 if (program.textPid != -1)
2113 pids_to_record.insert(program.textPid); // Videotext
2115 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2116 i(program.videoStreams.begin());
2117 i != program.videoStreams.end(); ++i)
2118 pids_to_record.insert(i->pid);
2120 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2121 i(program.audioStreams.begin());
2122 i != program.audioStreams.end(); ++i)
2123 pids_to_record.insert(i->pid);
2125 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2126 i(program.subtitleStreams.begin());
2127 i != program.subtitleStreams.end(); ++i)
2128 pids_to_record.insert(i->pid);
2130 std::set<int> new_pids, obsolete_pids;
2132 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2133 m_pids_active.begin(), m_pids_active.end(),
2134 std::inserter(new_pids, new_pids.begin()));
2136 std::set_difference(
2137 m_pids_active.begin(), m_pids_active.end(),
2138 pids_to_record.begin(), pids_to_record.end(),
2139 std::inserter(new_pids, new_pids.begin())
2142 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2143 m_record->addPID(*i);
2145 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2146 m_record->removePID(*i);
2150 void eDVBServicePlay::switchToLive()
2152 if (!m_timeshift_active)
2158 m_teletext_parser = 0;
2160 m_subtitle_parser = 0;
2161 m_new_dvb_subtitle_page_connection = 0;
2162 m_new_subtitle_page_connection = 0;
2163 m_rds_decoder_event_connection = 0;
2164 m_video_event_connection = 0;
2166 /* free the timeshift service handler, we need the resources */
2167 m_service_handler_timeshift.free();
2168 m_timeshift_active = 0;
2170 m_event((iPlayableService*)this, evSeekableStatusChanged);
2175 void eDVBServicePlay::switchToTimeshift()
2177 if (m_timeshift_active)
2182 m_teletext_parser = 0;
2184 m_subtitle_parser = 0;
2185 m_new_subtitle_page_connection = 0;
2186 m_new_dvb_subtitle_page_connection = 0;
2187 m_rds_decoder_event_connection = 0;
2188 m_video_event_connection = 0;
2190 m_timeshift_active = 1;
2192 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2193 r.path = m_timeshift_file;
2195 m_cue = new eCueSheet();
2196 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2198 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2200 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2202 m_event((iPlayableService*)this, evSeekableStatusChanged);
2205 void eDVBServicePlay::updateDecoder()
2207 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2209 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2211 bool defaultac3=false;
2212 std::string default_ac3;
2214 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2215 defaultac3 = default_ac3 == "True";
2217 eDVBServicePMTHandler::program program;
2218 if (h.getProgramInfo(program))
2219 eDebug("getting program info failed.");
2222 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2223 if (!program.videoStreams.empty())
2225 eDebugNoNewLine(" (");
2226 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2227 i(program.videoStreams.begin());
2228 i != program.videoStreams.end(); ++i)
2235 if (i != program.videoStreams.begin())
2236 eDebugNoNewLine(", ");
2237 eDebugNoNewLine("%04x", i->pid);
2239 eDebugNoNewLine(")");
2241 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2242 if (!program.audioStreams.empty())
2244 eDebugNoNewLine(" (");
2245 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2246 i(program.audioStreams.begin());
2247 i != program.audioStreams.end(); ++i)
2249 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2251 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2257 if (i != program.audioStreams.begin())
2258 eDebugNoNewLine(", ");
2259 eDebugNoNewLine("%04x", i->pid);
2261 eDebugNoNewLine(")");
2263 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2264 pcrpid = program.pcrPid;
2265 eDebug(", and the text pid is %04x", program.textPid);
2266 tpid = program.textPid;
2271 h.getDecodeDemux(m_decode_demux);
2274 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2276 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2279 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2280 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2281 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2282 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2283 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2290 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2291 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2292 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2294 else // subservice or recording
2296 eServiceReferenceDVB ref;
2297 m_service_handler.getServiceReference(ref);
2298 eServiceReferenceDVB parent = ref.getParentServiceReference();
2303 ePtr<eDVBResourceManager> res_mgr;
2304 if (!eDVBResourceManager::getInstance(res_mgr))
2306 ePtr<iDVBChannelList> db;
2307 if (!res_mgr->getChannelList(db))
2309 ePtr<eDVBService> origService;
2310 if (!db->getService(parent, origService))
2312 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2313 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2319 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2320 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2322 m_decoder->setVideoPID(vpid, vpidtype);
2323 m_decoder->setAudioPID(apid, apidtype);
2324 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2326 m_decoder->setSyncPCR(pcrpid);
2329 ePtr<iDVBDemux> data_demux;
2330 if (!h.getDataDemux(data_demux))
2332 m_rds_decoder = new eDVBRdsDecoder(data_demux);
2333 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
2334 m_rds_decoder->start(apid);
2339 m_decoder->setSyncPCR(-1);
2341 m_decoder->setTextPID(tpid);
2343 m_teletext_parser->start(program.textPid);
2346 m_decoder->setTrickmode(1);
2349 m_decoder->preroll();
2353 if (vpid > 0 && vpid < 0x2000)
2357 std::string radio_pic;
2358 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2359 m_decoder->setRadioPic(radio_pic);
2362 m_decoder->setAudioChannel(achannel);
2364 // how we can do this better?
2365 // update cache pid when the user changed the audio track or video track
2366 // TODO handling of difference audio types.. default audio types..
2368 /* don't worry about non-existing services, nor pvr services */
2369 if (m_dvb_service && !m_is_pvr)
2371 if (apidtype == eDVBAudio::aMPEG)
2373 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2374 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2378 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2379 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2381 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2382 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2383 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2384 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2387 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2390 void eDVBServicePlay::loadCuesheet()
2392 std::string filename = m_reference.path + ".cuts";
2394 m_cue_entries.clear();
2396 FILE *f = fopen(filename.c_str(), "rb");
2400 eDebug("loading cuts..");
2403 unsigned long long where;
2406 if (!fread(&where, sizeof(where), 1, f))
2408 if (!fread(&what, sizeof(what), 1, f))
2411 #if BYTE_ORDER == LITTLE_ENDIAN
2412 where = bswap_64(where);
2419 m_cue_entries.insert(cueEntry(where, what));
2422 eDebug("%d entries", m_cue_entries.size());
2424 eDebug("cutfile not found!");
2426 m_cuesheet_changed = 0;
2427 cutlistToCuesheet();
2428 m_event((iPlayableService*)this, evCuesheetChanged);
2431 void eDVBServicePlay::saveCuesheet()
2433 std::string filename = m_reference.path + ".cuts";
2435 FILE *f = fopen(filename.c_str(), "wb");
2439 unsigned long long where;
2442 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2444 #if BYTE_ORDER == BIG_ENDIAN
2447 where = bswap_64(i->where);
2449 what = htonl(i->what);
2450 fwrite(&where, sizeof(where), 1, f);
2451 fwrite(&what, sizeof(what), 1, f);
2457 m_cuesheet_changed = 0;
2460 void eDVBServicePlay::cutlistToCuesheet()
2464 eDebug("no cue sheet");
2469 if (!m_cutlist_enabled)
2471 m_cue->commitSpans();
2472 eDebug("cutlists were disabled");
2476 pts_t in = 0, out = 0, length = 0;
2480 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2484 if (i == m_cue_entries.end())
2487 if (i->what == 0) /* in */
2491 } else if (i->what == 1) /* out */
2493 else /* mark (2) or last play position (3) */
2501 m_cue->addSourceSpan(in, out);
2505 if (i == m_cue_entries.end())
2508 m_cue->commitSpans();
2511 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2513 if (m_subtitle_widget)
2514 disableSubtitles(parent);
2517 int tuplesize = PyTuple_Size(tuple);
2520 if (!PyTuple_Check(tuple))
2526 entry = PyTuple_GET_ITEM(tuple, 0);
2528 if (!PyInt_Check(entry))
2531 type = PyInt_AsLong(entry);
2533 if (type == 1) // teletext subtitles
2535 int page, magazine, pid;
2539 if (!m_teletext_parser)
2541 eDebug("enable teletext subtitles.. no parser !!!");
2545 entry = PyTuple_GET_ITEM(tuple, 1);
2546 if (!PyInt_Check(entry))
2548 pid = PyInt_AsLong(entry);
2550 entry = PyTuple_GET_ITEM(tuple, 2);
2551 if (!PyInt_Check(entry))
2553 page = PyInt_AsLong(entry);
2555 entry = PyTuple_GET_ITEM(tuple, 3);
2556 if (!PyInt_Check(entry))
2558 magazine = PyInt_AsLong(entry);
2560 m_subtitle_widget = new eSubtitleWidget(parent);
2561 m_subtitle_widget->resize(parent->size()); /* full size */
2562 m_teletext_parser->setPageAndMagazine(page, magazine);
2564 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2568 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2569 if (!m_subtitle_parser)
2571 eDebug("enable dvb subtitles.. no parser !!!");
2577 entry = PyTuple_GET_ITEM(tuple, 1);
2578 if (!PyInt_Check(entry))
2580 pid = PyInt_AsLong(entry);
2582 entry = PyTuple_GET_ITEM(tuple, 2);
2583 if (!PyInt_Check(entry))
2585 composition_page_id = PyInt_AsLong(entry);
2587 entry = PyTuple_GET_ITEM(tuple, 3);
2588 if (!PyInt_Check(entry))
2590 ancillary_page_id = PyInt_AsLong(entry);
2592 m_subtitle_widget = new eSubtitleWidget(parent);
2593 m_subtitle_widget->resize(parent->size()); /* full size */
2594 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2596 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2602 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2603 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2604 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2608 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2610 delete m_subtitle_widget;
2611 m_subtitle_widget = 0;
2612 if (m_subtitle_parser)
2614 m_subtitle_parser->stop();
2615 m_dvb_subtitle_pages.clear();
2617 if (m_teletext_parser)
2619 m_teletext_parser->setPageAndMagazine(-1, -1);
2620 m_subtitle_pages.clear();
2623 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2627 PyObject *eDVBServicePlay::getCachedSubtitle()
2631 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2634 unsigned int data = (unsigned int)tmp;
2635 int pid = (data&0xFFFF0000)>>16;
2636 ePyObject tuple = PyTuple_New(4);
2637 eDVBServicePMTHandler::program program;
2638 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2639 if (!h.getProgramInfo(program))
2641 if (program.textPid==pid) // teletext
2642 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2644 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2645 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2646 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2647 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2655 PyObject *eDVBServicePlay::getSubtitleList()
2657 if (!m_teletext_parser)
2660 ePyObject l = PyList_New(0);
2661 std::set<int> added_ttx_pages;
2663 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2664 m_teletext_parser->m_found_subtitle_pages;
2666 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2667 eDVBServicePMTHandler::program program;
2668 if (h.getProgramInfo(program))
2669 eDebug("getting program info failed.");
2672 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2673 it != program.subtitleStreams.end(); ++it)
2675 switch(it->subtitling_type)
2677 case 0x01: // ebu teletext subtitles
2679 int page_number = it->teletext_page_number & 0xFF;
2680 int magazine_number = it->teletext_magazine_number & 7;
2681 int hash = magazine_number << 8 | page_number;
2682 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2684 ePyObject tuple = PyTuple_New(5);
2685 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2686 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2687 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2688 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2689 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2690 PyList_Append(l, tuple);
2692 added_ttx_pages.insert(hash);
2697 case 0x20 ... 0x23: // dvb subtitles
2699 ePyObject tuple = PyTuple_New(5);
2700 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2701 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2702 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2703 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2704 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2705 PyList_Insert(l, 0, tuple);
2713 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2714 it != subs.end(); ++it)
2716 int page_number = it->teletext_page_number & 0xFF;
2717 int magazine_number = it->teletext_magazine_number & 7;
2718 int hash = magazine_number << 8 | page_number;
2719 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2721 ePyObject tuple = PyTuple_New(5);
2722 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2723 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2724 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2725 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2726 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2727 PyList_Append(l, tuple);
2735 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2737 if (m_subtitle_widget)
2739 m_subtitle_pages.push_back(page);
2740 checkSubtitleTiming();
2744 void eDVBServicePlay::checkSubtitleTiming()
2746 // eDebug("checkSubtitleTiming");
2747 if (!m_subtitle_widget)
2751 enum { TELETEXT, DVB } type;
2752 eDVBTeletextSubtitlePage page;
2753 eDVBSubtitlePage dvb_page;
2755 if (!m_subtitle_pages.empty())
2757 page = m_subtitle_pages.front();
2759 show_time = page.m_pts;
2761 else if (!m_dvb_subtitle_pages.empty())
2763 dvb_page = m_dvb_subtitle_pages.front();
2765 show_time = dvb_page.m_show_time;
2773 m_decoder->getPTS(0, pos);
2775 // eDebug("%lld %lld", pos, show_time);
2776 int diff = show_time - pos;
2779 eDebug("[late (%d ms)]", -diff / 90);
2784 eDebug("[invalid]");
2790 if (type == TELETEXT)
2792 eDebug("display teletext subtitle page");
2793 m_subtitle_widget->setPage(page);
2794 m_subtitle_pages.pop_front();
2798 eDebug("display dvb subtitle Page");
2799 m_subtitle_widget->setPage(dvb_page);
2800 m_dvb_subtitle_pages.pop_front();
2804 // eDebug("start subtitle delay %d", diff / 90);
2805 m_subtitle_sync_timer.start(diff / 90, 1);
2811 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2813 if (m_subtitle_widget)
2815 m_dvb_subtitle_pages.push_back(p);
2816 checkSubtitleTiming();
2820 int eDVBServicePlay::getAC3Delay()
2823 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2825 return m_decoder->getAC3Delay();
2830 int eDVBServicePlay::getPCMDelay()
2833 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2835 return m_decoder->getPCMDelay();
2840 void eDVBServicePlay::setAC3Delay(int delay)
2843 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2845 m_decoder->setAC3Delay(delay);
2848 void eDVBServicePlay::setPCMDelay(int delay)
2851 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2853 m_decoder->setPCMDelay(delay);
2856 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2858 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2859 m_event((iPlayableService*)this, evVideoSizeChanged);
2862 DEFINE_REF(eDVBServicePlay)
2864 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2868 case iServiceInformation::sTransponderData:
2869 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2873 return iStaticServiceInformation::getInfoObject(ref, w);
2876 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");