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);
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);
2286 m_teletext_parser = 0;
2287 m_subtitle_parser = 0;
2291 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2298 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2299 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2300 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2302 else // subservice or recording
2304 eServiceReferenceDVB ref;
2305 m_service_handler.getServiceReference(ref);
2306 eServiceReferenceDVB parent = ref.getParentServiceReference();
2311 ePtr<eDVBResourceManager> res_mgr;
2312 if (!eDVBResourceManager::getInstance(res_mgr))
2314 ePtr<iDVBChannelList> db;
2315 if (!res_mgr->getChannelList(db))
2317 ePtr<eDVBService> origService;
2318 if (!db->getService(parent, origService))
2320 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2321 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2327 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2328 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2330 m_decoder->setVideoPID(vpid, vpidtype);
2331 m_decoder->setAudioPID(apid, apidtype);
2332 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2334 m_decoder->setSyncPCR(pcrpid);
2337 ePtr<iDVBDemux> data_demux;
2338 if (!h.getDataDemux(data_demux))
2340 m_rds_decoder = new eDVBRdsDecoder(data_demux);
2341 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
2342 m_rds_decoder->start(apid);
2347 m_decoder->setSyncPCR(-1);
2349 m_decoder->setTextPID(tpid);
2351 m_teletext_parser->start(program.textPid);
2354 m_decoder->setTrickmode(1);
2357 m_decoder->preroll();
2361 if (vpid > 0 && vpid < 0x2000)
2365 std::string radio_pic;
2366 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2367 m_decoder->setRadioPic(radio_pic);
2370 m_decoder->setAudioChannel(achannel);
2372 // how we can do this better?
2373 // update cache pid when the user changed the audio track or video track
2374 // TODO handling of difference audio types.. default audio types..
2376 /* don't worry about non-existing services, nor pvr services */
2377 if (m_dvb_service && !m_is_pvr)
2379 if (apidtype == eDVBAudio::aMPEG)
2381 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2382 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2386 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2387 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2389 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2390 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2391 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2392 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2395 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2398 void eDVBServicePlay::loadCuesheet()
2400 std::string filename = m_reference.path + ".cuts";
2402 m_cue_entries.clear();
2404 FILE *f = fopen(filename.c_str(), "rb");
2408 eDebug("loading cuts..");
2411 unsigned long long where;
2414 if (!fread(&where, sizeof(where), 1, f))
2416 if (!fread(&what, sizeof(what), 1, f))
2419 #if BYTE_ORDER == LITTLE_ENDIAN
2420 where = bswap_64(where);
2427 m_cue_entries.insert(cueEntry(where, what));
2430 eDebug("%d entries", m_cue_entries.size());
2432 eDebug("cutfile not found!");
2434 m_cuesheet_changed = 0;
2435 cutlistToCuesheet();
2436 m_event((iPlayableService*)this, evCuesheetChanged);
2439 void eDVBServicePlay::saveCuesheet()
2441 std::string filename = m_reference.path + ".cuts";
2443 FILE *f = fopen(filename.c_str(), "wb");
2447 unsigned long long where;
2450 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2452 #if BYTE_ORDER == BIG_ENDIAN
2455 where = bswap_64(i->where);
2457 what = htonl(i->what);
2458 fwrite(&where, sizeof(where), 1, f);
2459 fwrite(&what, sizeof(what), 1, f);
2465 m_cuesheet_changed = 0;
2468 void eDVBServicePlay::cutlistToCuesheet()
2472 eDebug("no cue sheet");
2477 if (!m_cutlist_enabled)
2479 m_cue->commitSpans();
2480 eDebug("cutlists were disabled");
2484 pts_t in = 0, out = 0, length = 0;
2488 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2492 if (i == m_cue_entries.end())
2495 if (i->what == 0) /* in */
2499 } else if (i->what == 1) /* out */
2501 else /* mark (2) or last play position (3) */
2509 m_cue->addSourceSpan(in, out);
2513 if (i == m_cue_entries.end())
2516 m_cue->commitSpans();
2519 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2521 if (m_subtitle_widget)
2522 disableSubtitles(parent);
2525 int tuplesize = PyTuple_Size(tuple);
2528 if (!PyTuple_Check(tuple))
2534 entry = PyTuple_GET_ITEM(tuple, 0);
2536 if (!PyInt_Check(entry))
2539 type = PyInt_AsLong(entry);
2541 if (type == 1) // teletext subtitles
2543 int page, magazine, pid;
2547 if (!m_teletext_parser)
2549 eDebug("enable teletext subtitles.. no parser !!!");
2553 entry = PyTuple_GET_ITEM(tuple, 1);
2554 if (!PyInt_Check(entry))
2556 pid = PyInt_AsLong(entry);
2558 entry = PyTuple_GET_ITEM(tuple, 2);
2559 if (!PyInt_Check(entry))
2561 page = PyInt_AsLong(entry);
2563 entry = PyTuple_GET_ITEM(tuple, 3);
2564 if (!PyInt_Check(entry))
2566 magazine = PyInt_AsLong(entry);
2568 m_subtitle_widget = new eSubtitleWidget(parent);
2569 m_subtitle_widget->resize(parent->size()); /* full size */
2570 m_teletext_parser->setPageAndMagazine(page, magazine);
2572 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2576 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2577 if (!m_subtitle_parser)
2579 eDebug("enable dvb subtitles.. no parser !!!");
2585 entry = PyTuple_GET_ITEM(tuple, 1);
2586 if (!PyInt_Check(entry))
2588 pid = PyInt_AsLong(entry);
2590 entry = PyTuple_GET_ITEM(tuple, 2);
2591 if (!PyInt_Check(entry))
2593 composition_page_id = PyInt_AsLong(entry);
2595 entry = PyTuple_GET_ITEM(tuple, 3);
2596 if (!PyInt_Check(entry))
2598 ancillary_page_id = PyInt_AsLong(entry);
2600 m_subtitle_widget = new eSubtitleWidget(parent);
2601 m_subtitle_widget->resize(parent->size()); /* full size */
2602 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2604 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2610 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2611 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2612 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2616 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2618 delete m_subtitle_widget;
2619 m_subtitle_widget = 0;
2620 if (m_subtitle_parser)
2622 m_subtitle_parser->stop();
2623 m_dvb_subtitle_pages.clear();
2625 if (m_teletext_parser)
2627 m_teletext_parser->setPageAndMagazine(-1, -1);
2628 m_subtitle_pages.clear();
2631 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2635 PyObject *eDVBServicePlay::getCachedSubtitle()
2639 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2642 unsigned int data = (unsigned int)tmp;
2643 int pid = (data&0xFFFF0000)>>16;
2644 ePyObject tuple = PyTuple_New(4);
2645 eDVBServicePMTHandler::program program;
2646 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2647 if (!h.getProgramInfo(program))
2649 if (program.textPid==pid) // teletext
2650 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2652 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2653 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2654 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2655 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2663 PyObject *eDVBServicePlay::getSubtitleList()
2665 if (!m_teletext_parser)
2668 ePyObject l = PyList_New(0);
2669 std::set<int> added_ttx_pages;
2671 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2672 m_teletext_parser->m_found_subtitle_pages;
2674 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2675 eDVBServicePMTHandler::program program;
2676 if (h.getProgramInfo(program))
2677 eDebug("getting program info failed.");
2680 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2681 it != program.subtitleStreams.end(); ++it)
2683 switch(it->subtitling_type)
2685 case 0x01: // ebu teletext subtitles
2687 int page_number = it->teletext_page_number & 0xFF;
2688 int magazine_number = it->teletext_magazine_number & 7;
2689 int hash = magazine_number << 8 | page_number;
2690 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2692 ePyObject tuple = PyTuple_New(5);
2693 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2694 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2695 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2696 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2697 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2698 PyList_Append(l, tuple);
2700 added_ttx_pages.insert(hash);
2705 case 0x20 ... 0x23: // dvb subtitles
2707 ePyObject tuple = PyTuple_New(5);
2708 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2709 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2710 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2711 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2712 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2713 PyList_Insert(l, 0, tuple);
2721 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2722 it != subs.end(); ++it)
2724 int page_number = it->teletext_page_number & 0xFF;
2725 int magazine_number = it->teletext_magazine_number & 7;
2726 int hash = magazine_number << 8 | page_number;
2727 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2729 ePyObject tuple = PyTuple_New(5);
2730 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2731 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2732 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2733 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2734 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2735 PyList_Append(l, tuple);
2743 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2745 if (m_subtitle_widget)
2747 m_subtitle_pages.push_back(page);
2748 checkSubtitleTiming();
2752 void eDVBServicePlay::checkSubtitleTiming()
2754 // eDebug("checkSubtitleTiming");
2755 if (!m_subtitle_widget)
2759 enum { TELETEXT, DVB } type;
2760 eDVBTeletextSubtitlePage page;
2761 eDVBSubtitlePage dvb_page;
2763 if (!m_subtitle_pages.empty())
2765 page = m_subtitle_pages.front();
2767 show_time = page.m_pts;
2769 else if (!m_dvb_subtitle_pages.empty())
2771 dvb_page = m_dvb_subtitle_pages.front();
2773 show_time = dvb_page.m_show_time;
2781 m_decoder->getPTS(0, pos);
2783 // eDebug("%lld %lld", pos, show_time);
2784 int diff = show_time - pos;
2787 eDebug("[late (%d ms)]", -diff / 90);
2792 eDebug("[invalid]");
2798 if (type == TELETEXT)
2800 eDebug("display teletext subtitle page");
2801 m_subtitle_widget->setPage(page);
2802 m_subtitle_pages.pop_front();
2806 eDebug("display dvb subtitle Page");
2807 m_subtitle_widget->setPage(dvb_page);
2808 m_dvb_subtitle_pages.pop_front();
2812 // eDebug("start subtitle delay %d", diff / 90);
2813 m_subtitle_sync_timer.start(diff / 90, 1);
2819 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2821 if (m_subtitle_widget)
2823 m_dvb_subtitle_pages.push_back(p);
2824 checkSubtitleTiming();
2828 int eDVBServicePlay::getAC3Delay()
2831 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2833 return m_decoder->getAC3Delay();
2838 int eDVBServicePlay::getPCMDelay()
2841 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2843 return m_decoder->getPCMDelay();
2848 void eDVBServicePlay::setAC3Delay(int delay)
2851 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2853 m_decoder->setAC3Delay(delay);
2856 void eDVBServicePlay::setPCMDelay(int delay)
2859 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2861 m_decoder->setPCMDelay(delay);
2864 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2866 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2867 m_event((iPlayableService*)this, evVideoSizeChanged);
2870 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2876 PyObject *eDVBServicePlay::getStreamingData()
2878 eDVBServicePMTHandler::program program;
2879 if (m_service_handler.getProgramInfo(program))
2885 PyObject *r = program.createPythonObject();
2886 ePtr<iDVBDemux> demux;
2887 if (!m_service_handler.getDataDemux(demux))
2890 demux->getCADemuxID(demux_id);
2892 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
2899 DEFINE_REF(eDVBServicePlay)
2901 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2905 case iServiceInformation::sTransponderData:
2906 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2910 return iStaticServiceInformation::getInfoObject(ref, w);
2913 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");