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/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
36 DECLARE_REF(eStaticServiceDVBInformation);
38 RESULT getName(const eServiceReference &ref, std::string &name);
39 int getLength(const eServiceReference &ref);
40 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41 PyObject *getInfoObject(const eServiceReference &ref, int);
44 DEFINE_REF(eStaticServiceDVBInformation);
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
48 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49 if ( !ref.name.empty() )
51 if (service.getParentTransportStreamID().get()) // linkage subservice
53 ePtr<iServiceHandler> service_center;
54 if (!eServiceCenter::getInstance(service_center))
56 eServiceReferenceDVB parent = service;
57 parent.setTransportStreamID( service.getParentTransportStreamID() );
58 parent.setServiceID( service.getParentServiceID() );
59 parent.setParentTransportStreamID(eTransportStreamID(0));
60 parent.setParentServiceID(eServiceID(0));
62 ePtr<iStaticServiceInformation> service_info;
63 if (!service_center->info(parent, service_info))
65 if (!service_info->getName(parent, name))
66 name=buildShortName(name) + " - ";
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
86 ePtr<eDVBResourceManager> res_mgr;
87 if ( eDVBResourceManager::getInstance( res_mgr ) )
88 eDebug("isPlayable... no res manager!!");
91 eDVBChannelID chid, chid_ignore;
92 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94 return res_mgr->canAllocateChannel(chid, chid_ignore);
99 static void PutToDict(ePyObject &dict, const char*key, long value)
101 ePyObject item = PyString_FromFormat("%d", value);
104 if (PyDict_SetItemString(dict, key, item))
105 eDebug("put %s to dict failed", key);
109 eDebug("could not create PyObject for %s", key);
112 extern void PutToDict(ePyObject &dict, const char*key, ePyObject item); // defined in dvb/frontend.cpp
113 extern void PutToDict(ePyObject &dict, const char*key, const char *value); // defined in dvb/frontend.cpp
115 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
118 PutToDict(dict, "type", "Satellite");
119 PutToDict(dict, "frequency", feparm.frequency);
120 PutToDict(dict, "symbolrate", feparm.symbol_rate);
121 PutToDict(dict, "orbital position", feparm.orbital_position);
122 switch (feparm.inversion)
124 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
125 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
127 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
129 PutToDict(dict, "inversion", tmp);
132 case eDVBFrontendParametersSatellite::FEC::fNone: tmp="NONE"; break;
133 case eDVBFrontendParametersSatellite::FEC::f1_2: tmp="1/2"; break;
134 case eDVBFrontendParametersSatellite::FEC::f2_3: tmp="2/3"; break;
135 case eDVBFrontendParametersSatellite::FEC::f3_4: tmp="3/4"; break;
136 case eDVBFrontendParametersSatellite::FEC::f5_6: tmp="5/6"; break;
137 case eDVBFrontendParametersSatellite::FEC::f7_8: tmp="7/8"; break;
138 case eDVBFrontendParametersSatellite::FEC::f3_5: tmp="3/5"; break;
139 case eDVBFrontendParametersSatellite::FEC::f4_5: tmp="4/5"; break;
140 case eDVBFrontendParametersSatellite::FEC::f8_9: tmp="8/9"; break;
141 case eDVBFrontendParametersSatellite::FEC::f9_10: tmp="9/10"; break;
143 case eDVBFrontendParametersSatellite::FEC::fAuto: tmp="AUTO"; break;
145 PutToDict(dict, "fec inner", tmp);
146 switch (feparm.modulation)
148 case eDVBFrontendParametersSatellite::Modulation::Auto: tmp="AUTO"; break;
149 case eDVBFrontendParametersSatellite::Modulation::QPSK: tmp="QPSK"; break;
150 case eDVBFrontendParametersSatellite::Modulation::M8PSK: tmp="8PSK"; break;
151 case eDVBFrontendParametersSatellite::Modulation::QAM_16: tmp="QAM16"; break;
153 PutToDict(dict, "modulation", tmp);
154 switch(feparm.polarisation)
156 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
157 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
158 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR LEFT"; break;
160 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR RIGHT"; break;
162 PutToDict(dict, "polarization", tmp);
163 switch(feparm.system)
166 case eDVBFrontendParametersSatellite::System::DVB_S: tmp="DVB-S"; break;
167 case eDVBFrontendParametersSatellite::System::DVB_S2:
168 switch(feparm.rolloff)
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 PutToDict(dict, "roll off", tmp);
178 case eDVBFrontendParametersSatellite::Pilot::On: tmp="ON"; break;
179 case eDVBFrontendParametersSatellite::Pilot::Off: tmp="OFF"; break;
181 case eDVBFrontendParametersSatellite::Pilot::Unknown: tmp="AUTO"; break;
183 PutToDict(dict, "pilot", tmp);
187 PutToDict(dict, "system", tmp);
190 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
192 PutToDict(dict, "type", "Terrestrial");
193 PutToDict(dict, "frequency", feparm.frequency);
195 switch (feparm.bandwidth)
197 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz: tmp="8 MHz"; break;
198 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz: tmp="7 MHz"; break;
199 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz: tmp="6 MHz"; break;
201 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto: tmp="AUTO"; break;
203 PutToDict(dict, "bandwidth", tmp);
204 switch (feparm.code_rate_LP)
206 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
207 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
208 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
209 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
210 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
212 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
214 PutToDict(dict, "code rate lp", tmp);
215 switch (feparm.code_rate_HP)
217 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
218 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
219 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
220 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
221 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
223 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
225 PutToDict(dict, "code rate hp", tmp);
226 switch (feparm.modulation)
228 case eDVBFrontendParametersTerrestrial::Modulation::QPSK: tmp="QPSK"; break;
229 case eDVBFrontendParametersTerrestrial::Modulation::QAM16: tmp="QAM16"; break;
230 case eDVBFrontendParametersTerrestrial::Modulation::QAM64: tmp="QAM64"; break;
232 case eDVBFrontendParametersTerrestrial::Modulation::Auto: tmp="AUTO"; break;
234 PutToDict(dict, "constellation", tmp);
235 switch (feparm.transmission_mode)
237 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k: tmp="2k"; break;
238 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k: tmp="8k"; break;
240 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto: tmp="AUTO"; break;
242 PutToDict(dict, "transmission mode", tmp);
243 switch (feparm.guard_interval)
245 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32: tmp="1/32"; break;
246 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16: tmp="1/16"; break;
247 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8: tmp="1/8"; break;
248 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4: tmp="1/4"; break;
250 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto: tmp="AUTO"; break;
252 PutToDict(dict, "guard interval", tmp);
253 switch (feparm.hierarchy)
255 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone: tmp="NONE"; break;
256 case eDVBFrontendParametersTerrestrial::Hierarchy::H1: tmp="1"; break;
257 case eDVBFrontendParametersTerrestrial::Hierarchy::H2: tmp="2"; break;
258 case eDVBFrontendParametersTerrestrial::Hierarchy::H4: tmp="4"; break;
260 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto: tmp="AUTO"; break;
262 PutToDict(dict, "hierarchy", tmp);
263 switch (feparm.inversion)
265 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
266 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
268 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
270 PutToDict(dict, "inversion", tmp);
273 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
276 PutToDict(dict, "type", "Cable");
277 PutToDict(dict, "frequency", feparm.frequency);
278 PutToDict(dict, "symbolrate", feparm.symbol_rate);
279 switch (feparm.modulation)
281 case eDVBFrontendParametersCable::Modulation::QAM16: tmp="QAM16"; break;
282 case eDVBFrontendParametersCable::Modulation::QAM32: tmp="QAM32"; break;
283 case eDVBFrontendParametersCable::Modulation::QAM64: tmp="QAM64"; break;
284 case eDVBFrontendParametersCable::Modulation::QAM128: tmp="QAM128"; break;
285 case eDVBFrontendParametersCable::Modulation::QAM256: tmp="QAM256"; break;
287 case eDVBFrontendParametersCable::Modulation::Auto: tmp="AUTO"; break;
289 PutToDict(dict, "modulation", tmp);
290 switch (feparm.inversion)
292 case eDVBFrontendParametersCable::Inversion::On: tmp="ON"; break;
293 case eDVBFrontendParametersCable::Inversion::Off: tmp="OFF"; break;
295 case eDVBFrontendParametersCable::Inversion::Unknown: tmp="AUTO"; break;
297 PutToDict(dict, "inversion", tmp);
298 switch (feparm.fec_inner)
300 case eDVBFrontendParametersCable::FEC::fNone: tmp="NONE"; break;
301 case eDVBFrontendParametersCable::FEC::f1_2: tmp="1/2"; break;
302 case eDVBFrontendParametersCable::FEC::f2_3: tmp="2/3"; break;
303 case eDVBFrontendParametersCable::FEC::f3_4: tmp="3/4"; break;
304 case eDVBFrontendParametersCable::FEC::f5_6: tmp="5/6"; break;
305 case eDVBFrontendParametersCable::FEC::f7_8: tmp="7/8"; break;
306 case eDVBFrontendParametersCable::FEC::f8_9: tmp="8/9"; break;
308 case eDVBFrontendParametersCable::FEC::fAuto: tmp="AUTO"; break;
310 PutToDict(dict, "fec inner", tmp);
313 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
315 if (r.type == eServiceReference::idDVB)
317 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
320 case iServiceInformation::sTransponderData:
322 ePtr<eDVBResourceManager> res;
323 if (!eDVBResourceManager::getInstance(res))
325 ePtr<iDVBChannelList> db;
326 if (!res->getChannelList(db))
329 ref.getChannelID(chid);
330 ePtr<iDVBFrontendParameters> feparm;
331 if (!db->getChannelFrontendData(chid, feparm))
334 if (!feparm->getSystem(system))
336 ePyObject dict = PyDict_New();
339 case iDVBFrontend::feSatellite:
341 eDVBFrontendParametersSatellite s;
343 PutSatelliteDataToDict(dict, s);
346 case iDVBFrontend::feTerrestrial:
348 eDVBFrontendParametersTerrestrial t;
350 PutTerrestrialDataToDict(dict, t);
353 case iDVBFrontend::feCable:
355 eDVBFrontendParametersCable c;
357 PutCableDataToDict(dict, c);
361 eDebug("unknown frontend type %d", system);
376 DEFINE_REF(eStaticServiceDVBBouquetInformation);
378 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
380 ePtr<iDVBChannelList> db;
381 ePtr<eDVBResourceManager> res;
384 if ((err = eDVBResourceManager::getInstance(res)) != 0)
386 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
389 if ((err = res->getChannelList(db)) != 0)
391 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
396 if ((err = db->getBouquet(ref, bouquet)) != 0)
398 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
402 if ( bouquet && bouquet->m_bouquet_name.length() )
404 name = bouquet->m_bouquet_name;
411 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
413 if (ref.flags & eServiceReference::isGroup)
415 ePtr<iDVBChannelList> db;
416 ePtr<eDVBResourceManager> res;
418 if (eDVBResourceManager::getInstance(res))
420 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
424 if (res->getChannelList(db))
426 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
431 if (db->getBouquet(ref, bouquet))
433 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
437 int prio_order = eDVBFrontend::getTypePriorityOrder();
439 eDVBChannelID chid, chid_ignore;
440 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
441 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
443 static unsigned char prio_map[6][3] = {
444 { 3, 2, 1 }, // -S -C -T
445 { 3, 1, 2 }, // -S -T -C
446 { 2, 3, 1 }, // -C -S -T
447 { 1, 3, 2 }, // -C -T -S
448 { 1, 2, 3 }, // -T -C -S
449 { 2, 1, 3 } // -T -S -C
451 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
452 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
457 case 30000: // cached DVB-T channel
458 case 1: // DVB-T frontend
459 tmp = prio_map[prio_order][2];
461 case 40000: // cached DVB-C channel
463 tmp = prio_map[prio_order][1];
466 tmp = prio_map[prio_order][0];
471 m_playable_service = *it;
478 m_playable_service = eServiceReference();
482 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
487 #include <lib/dvb/epgcache.h>
489 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
491 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
494 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
496 DECLARE_REF(eStaticServiceDVBPVRInformation);
497 eServiceReference m_ref;
498 eDVBMetaParser m_parser;
500 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
501 RESULT getName(const eServiceReference &ref, std::string &name);
502 int getLength(const eServiceReference &ref);
503 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
504 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
505 int getInfo(const eServiceReference &ref, int w);
506 std::string getInfoString(const eServiceReference &ref,int w);
509 DEFINE_REF(eStaticServiceDVBPVRInformation);
511 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
514 m_parser.parseFile(ref.path);
517 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
519 ASSERT(ref == m_ref);
520 if (m_parser.m_name.size())
521 name = m_parser.m_name;
525 size_t n = name.rfind('/');
526 if (n != std::string::npos)
527 name = name.substr(n + 1);
532 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
534 ASSERT(ref == m_ref);
538 if (tstools.openFile(ref.path.c_str()))
542 if (tstools.calcLen(len))
548 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
552 case iServiceInformation::sDescription:
553 return iServiceInformation::resIsString;
554 case iServiceInformation::sServiceref:
555 return iServiceInformation::resIsString;
556 case iServiceInformation::sTimeCreate:
557 if (m_parser.m_time_create)
558 return m_parser.m_time_create;
560 return iServiceInformation::resNA;
562 return iServiceInformation::resNA;
566 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
570 case iServiceInformation::sDescription:
571 return m_parser.m_description;
572 case iServiceInformation::sServiceref:
573 return m_parser.m_ref.toString();
574 case iServiceInformation::sTags:
575 return m_parser.m_tags;
581 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
583 if (!ref.path.empty())
585 ePtr<eServiceEvent> event = new eServiceEvent;
586 std::string filename = ref.path;
587 filename.erase(filename.length()-2, 2);
589 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
599 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
601 DECLARE_REF(eDVBPVRServiceOfflineOperations);
602 eServiceReferenceDVB m_ref;
604 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
606 RESULT deleteFromDisk(int simulate);
607 RESULT getListOfFilenames(std::list<std::string> &);
610 DEFINE_REF(eDVBPVRServiceOfflineOperations);
612 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
616 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
622 std::list<std::string> res;
623 if (getListOfFilenames(res))
626 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
628 eDebug("FATAL !! can't get background file eraser");
630 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
632 eDebug("Removing %s...", i->c_str());
634 eraser->erase(i->c_str());
636 ::unlink(i->c_str());
643 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
646 res.push_back(m_ref.path);
648 // handling for old splitted recordings (enigma 1)
653 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
655 if (stat(buf, &s) < 0)
660 res.push_back(m_ref.path + ".meta");
661 res.push_back(m_ref.path + ".ap");
662 res.push_back(m_ref.path + ".cuts");
663 std::string tmp = m_ref.path;
664 tmp.erase(m_ref.path.length()-3);
665 res.push_back(tmp + ".eit");
669 DEFINE_REF(eServiceFactoryDVB)
671 eServiceFactoryDVB::eServiceFactoryDVB()
673 ePtr<eServiceCenter> sc;
675 eServiceCenter::getPrivInstance(sc);
678 std::list<std::string> extensions;
679 extensions.push_back("ts");
680 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
683 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
684 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
687 eServiceFactoryDVB::~eServiceFactoryDVB()
689 ePtr<eServiceCenter> sc;
691 eServiceCenter::getPrivInstance(sc);
693 sc->removeServiceFactory(eServiceFactoryDVB::id);
696 DEFINE_REF(eDVBServiceList);
698 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
702 eDVBServiceList::~eDVBServiceList()
706 RESULT eDVBServiceList::startQuery()
708 ePtr<iDVBChannelList> db;
709 ePtr<eDVBResourceManager> res;
712 if ((err = eDVBResourceManager::getInstance(res)) != 0)
714 eDebug("no resource manager");
717 if ((err = res->getChannelList(db)) != 0)
719 eDebug("no channel list");
723 ePtr<eDVBChannelQuery> q;
725 if (!m_parent.path.empty())
727 eDVBChannelQuery::compile(q, m_parent.path);
730 eDebug("compile query failed");
735 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
737 eDebug("startQuery failed");
744 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
746 eServiceReferenceDVB ref;
751 while (!m_query->getNextResult(ref))
755 list.sort(iListableServiceCompare(this));
760 // The first argument of this function is a format string to specify the order and
761 // the content of the returned list
762 // useable format options are
763 // R = Service Reference (as swig object .. this is very slow)
764 // S = Service Reference (as python string object .. same as ref.toString())
765 // C = Service Reference (as python string object .. same as ref.toCompareString())
766 // N = Service Name (as python string object)
767 // n = Short Service Name (short name brakets used) (as python string object)
768 // when exactly one return value per service is selected in the format string,
769 // then each value is directly a list entry
770 // when more than one value is returned per service, then the list is a list of
772 // unknown format string chars are returned as python None values !
773 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
776 std::list<eServiceReference> tmplist;
779 if (!format || !(retcount=strlen(format)))
780 format = "R"; // just return service reference swig object ...
782 if (!getContent(tmplist, sorted))
784 int services=tmplist.size();
785 ePtr<iStaticServiceInformation> sptr;
786 eServiceCenterPtr service_center;
788 if (strchr(format, 'N') || strchr(format, 'n'))
789 eServiceCenter::getPrivInstance(service_center);
791 ret = PyList_New(services);
792 std::list<eServiceReference>::iterator it(tmplist.begin());
794 for (int cnt=0; cnt < services; ++cnt)
796 eServiceReference &ref=*it++;
797 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
798 for (int i=0; i < retcount; ++i)
803 case 'R': // service reference (swig)object
804 tmp = NEW_eServiceReference(ref);
806 case 'C': // service reference compare string
807 tmp = PyString_FromString(ref.toCompareString().c_str());
809 case 'S': // service reference string
810 tmp = PyString_FromString(ref.toString().c_str());
812 case 'N': // service name
815 service_center->info(ref, sptr);
819 sptr->getName(ref, name);
821 // filter short name brakets
823 while((pos = name.find("\xc2\x86")) != std::string::npos)
825 while((pos = name.find("\xc2\x87")) != std::string::npos)
829 tmp = PyString_FromString(name.c_str());
833 tmp = PyString_FromString("<n/a>");
835 case 'n': // short service name
838 service_center->info(ref, sptr);
842 sptr->getName(ref, name);
843 name = buildShortName(name);
845 tmp = PyString_FromString(name.c_str());
849 tmp = PyString_FromString("<n/a>");
862 PyTuple_SET_ITEM(tuple, i, tmp);
864 PyList_SET_ITEM(ret, cnt, tmp);
868 PyList_SET_ITEM(ret, cnt, tuple);
871 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
874 RESULT eDVBServiceList::getNext(eServiceReference &ref)
879 return m_query->getNextResult((eServiceReferenceDVB&)ref);
882 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
884 if (m_parent.flags & eServiceReference::canDescent) // bouquet
886 ePtr<iDVBChannelList> db;
887 ePtr<eDVBResourceManager> resm;
889 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
892 if (db->getBouquet(m_parent, m_bouquet) != 0)
903 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
907 return m_bouquet->addService(ref, before);
910 RESULT eDVBServiceList::removeService(eServiceReference &ref)
914 return m_bouquet->removeService(ref);
917 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
921 return m_bouquet->moveService(ref, pos);
924 RESULT eDVBServiceList::flushChanges()
928 return m_bouquet->flushChanges();
931 RESULT eDVBServiceList::setListName(const std::string &name)
935 return m_bouquet->setListName(name);
938 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
940 ePtr<eDVBService> service;
941 int r = lookupService(service, ref);
944 // check resources...
945 ptr = new eDVBServicePlay(ref, service);
949 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
951 if (ref.path.empty())
953 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
962 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
964 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
965 if (list->startQuery())
975 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
977 /* is a listable service? */
978 if (ref.flags & eServiceReference::canDescent) // bouquet
980 if ( !ref.name.empty() ) // satellites or providers list
981 ptr = m_StaticServiceDVBInfo;
982 else // a dvb bouquet
983 ptr = m_StaticServiceDVBBouquetInfo;
985 else if (!ref.path.empty()) /* do we have a PVR service? */
986 ptr = new eStaticServiceDVBPVRInformation(ref);
987 else // normal dvb service
989 ePtr<eDVBService> service;
990 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
991 ptr = m_StaticServiceDVBInfo;
993 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
999 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
1001 if (ref.path.empty())
1007 ptr = new eDVBPVRServiceOfflineOperations(ref);
1012 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
1014 // TODO: handle the listing itself
1015 // if (ref.... == -1) .. return "... bouquets ...";
1016 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
1018 ePtr<iDVBChannelList> db;
1019 ePtr<eDVBResourceManager> res;
1022 if ((err = eDVBResourceManager::getInstance(res)) != 0)
1024 eDebug("no resource manager");
1027 if ((err = res->getChannelList(db)) != 0)
1029 eDebug("no channel list");
1033 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
1034 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
1036 eDebug("getService failed!");
1043 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
1044 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
1046 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
1048 m_is_pvr = !m_reference.path.empty();
1050 m_timeshift_enabled = m_timeshift_active = 0;
1053 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
1054 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
1055 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
1057 m_cuesheet_changed = 0;
1058 m_cutlist_enabled = 1;
1060 m_subtitle_widget = 0;
1064 m_subtitle_sync_timer = eTimer::create(eApp);
1066 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
1069 eDVBServicePlay::~eDVBServicePlay()
1071 delete m_subtitle_widget;
1074 void eDVBServicePlay::gotNewEvent()
1078 ePtr<eServiceEvent> m_event_now, m_event_next;
1079 getEvent(m_event_now, 0);
1080 getEvent(m_event_next, 1);
1083 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1085 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1087 m_event((iPlayableService*)this, evUpdatedEventInfo);
1090 void eDVBServicePlay::serviceEvent(int event)
1092 m_tune_state = event;
1096 case eDVBServicePMTHandler::eventTuned:
1098 ePtr<iDVBDemux> m_demux;
1099 if (!m_service_handler.getDataDemux(m_demux))
1101 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1102 int sid = ref.getParentServiceID().get();
1104 sid = ref.getServiceID().get();
1105 if ( ref.getParentTransportStreamID().get() &&
1106 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1107 m_event_handler.startOther(m_demux, sid);
1109 m_event_handler.start(m_demux, sid);
1111 m_event((iPlayableService*)this, evTunedIn);
1114 case eDVBServicePMTHandler::eventNoResources:
1115 case eDVBServicePMTHandler::eventNoPAT:
1116 case eDVBServicePMTHandler::eventNoPATEntry:
1117 case eDVBServicePMTHandler::eventNoPMT:
1118 case eDVBServicePMTHandler::eventTuneFailed:
1119 case eDVBServicePMTHandler::eventMisconfiguration:
1121 eDebug("DVB service failed to tune - error %d", event);
1122 m_event((iPlayableService*)this, evTuneFailed);
1125 case eDVBServicePMTHandler::eventNewProgramInfo:
1127 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1128 if (m_timeshift_enabled)
1129 updateTimeshiftPids();
1130 if (!m_timeshift_active)
1132 if (m_first_program_info && m_is_pvr)
1134 m_first_program_info = 0;
1137 m_event((iPlayableService*)this, evUpdatedInfo);
1140 case eDVBServicePMTHandler::eventEOF:
1141 m_event((iPlayableService*)this, evEOF);
1143 case eDVBServicePMTHandler::eventSOF:
1144 m_event((iPlayableService*)this, evSOF);
1149 void eDVBServicePlay::serviceEventTimeshift(int event)
1153 case eDVBServicePMTHandler::eventNewProgramInfo:
1154 if (m_timeshift_active)
1157 case eDVBServicePMTHandler::eventSOF:
1158 m_event((iPlayableService*)this, evSOF);
1160 case eDVBServicePMTHandler::eventEOF:
1161 if ((!m_is_paused) && (m_skipmode >= 0))
1167 RESULT eDVBServicePlay::start()
1170 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1171 two (one for decoding, one for data source), as we must be prepared
1172 to start recording from the data demux. */
1174 m_cue = new eCueSheet();
1176 m_event(this, evStart);
1178 m_first_program_info = 1;
1179 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1180 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1182 /* inject EIT if there is a stored one */
1185 std::string filename = service.path;
1186 filename.erase(filename.length()-2, 2);
1188 ePtr<eServiceEvent> event = new eServiceEvent;
1189 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1191 ePtr<eServiceEvent> empty;
1192 m_event_handler.inject(event, 0);
1193 m_event_handler.inject(empty, 1);
1200 m_event(this, evStart);
1205 RESULT eDVBServicePlay::stop()
1207 /* add bookmark for last play position */
1210 pts_t play_position, length;
1211 if (!getPlayPosition(play_position))
1213 /* remove last position */
1214 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1216 if (i->what == 3) /* current play position */
1218 m_cue_entries.erase(i);
1219 i = m_cue_entries.begin();
1225 if (getLength(length))
1230 int perc = play_position * 100LL / length;
1232 /* only store last play position when between 1% and 99% */
1233 if ((1 < perc) && (perc < 99))
1234 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1236 m_cuesheet_changed = 1;
1240 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1242 m_service_handler_timeshift.free();
1243 m_service_handler.free();
1245 if (m_is_pvr && m_cuesheet_changed)
1248 /* save cuesheet only when main file is accessible. */
1249 if (!::stat(m_reference.path.c_str(), &s))
1252 m_event((iPlayableService*)this, evStopped);
1256 RESULT eDVBServicePlay::setTarget(int target)
1258 m_is_primary = !target;
1262 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1264 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1268 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1270 /* note: we check for timeshift to be enabled,
1271 not neccessary active. if you pause when timeshift
1272 is not active, you should activate it when unpausing */
1273 if ((!m_is_pvr) && (!m_timeshift_enabled))
1283 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1286 return m_decoder->setSlowMotion(ratio);
1291 RESULT eDVBServicePlay::setFastForward(int ratio)
1293 int skipmode, ffratio;
1299 } else if (ratio > 0)
1307 } else // if (ratio < 0)
1313 if (m_skipmode != skipmode)
1315 eDebug("setting cue skipmode to %d", skipmode);
1317 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1320 m_skipmode = skipmode;
1325 return m_decoder->setFastForward(ffratio);
1328 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1330 if (m_is_pvr || m_timeshift_enabled)
1340 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1341 RESULT eDVBServicePlay::getLength(pts_t &len)
1343 ePtr<iDVBPVRChannel> pvr_channel;
1345 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1348 return pvr_channel->getLength(len);
1351 RESULT eDVBServicePlay::pause()
1353 if (!m_is_paused && m_decoder)
1356 return m_decoder->freeze(0);
1361 RESULT eDVBServicePlay::unpause()
1363 if (m_is_paused && m_decoder)
1366 return m_decoder->unfreeze();
1371 RESULT eDVBServicePlay::seekTo(pts_t to)
1373 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1375 if (!m_decode_demux)
1378 ePtr<iDVBPVRChannel> pvr_channel;
1380 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1386 m_cue->seekTo(0, to);
1387 m_dvb_subtitle_pages.clear();
1388 m_subtitle_pages.clear();
1393 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1395 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1397 if (!m_decode_demux)
1400 ePtr<iDVBPVRChannel> pvr_channel;
1402 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1407 /* HACK until we have skip-AP api */
1408 if ((to > 0) && (to < 100))
1416 m_cue->seekTo(mode, to);
1417 m_dvb_subtitle_pages.clear();
1418 m_subtitle_pages.clear();
1422 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1424 ePtr<iDVBPVRChannel> pvr_channel;
1426 if (!m_decode_demux)
1429 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1434 /* if there is a decoder, use audio or video PTS */
1437 r = m_decoder->getPTS(0, pos);
1443 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1446 RESULT eDVBServicePlay::setTrickmode(int trick)
1449 m_decoder->setTrickmode(trick);
1453 RESULT eDVBServicePlay::isCurrentlySeekable()
1455 return m_is_pvr || m_timeshift_active;
1458 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1464 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1470 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1476 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1482 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1488 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1491 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1492 (m_timeshift_enabled || !m_is_pvr))
1494 if (!m_timeshift_enabled)
1496 /* query config path */
1498 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1499 eDebug("could not query ts path from config");
1503 /* we need enough diskspace */
1505 if (statfs(tspath.c_str(), &fs) < 0)
1507 eDebug("statfs failed!");
1511 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1513 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1523 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1534 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1540 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1546 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1552 RESULT eDVBServicePlay::getName(std::string &name)
1556 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1557 return i->getName(m_reference, name);
1561 m_dvb_service->getName(m_reference, name);
1565 else if (!m_reference.name.empty())
1566 eStaticServiceDVBInformation().getName(m_reference, name);
1568 name = "DVB service";
1572 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1574 return m_event_handler.getEvent(evt, nownext);
1577 static int readMpegProc(char *str, int decoder)
1581 sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
1582 FILE *f = fopen(tmp, "r");
1585 fscanf(f, "%x", &val);
1591 int eDVBServicePlay::getInfo(int w)
1593 eDVBServicePMTHandler::program program;
1596 return resIsPyObject;
1598 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1600 int no_program_info = 0;
1602 if (h.getProgramInfo(program))
1603 no_program_info = 1;
1607 #if HAVE_DVB_API_VERSION >= 3
1609 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1610 return m_videoEventData.height;
1612 return readMpegProc("yres", !m_is_primary);
1614 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1615 return m_videoEventData.width;
1617 return readMpegProc("xres", !m_is_primary);
1619 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventFrameRateChanged)
1620 return m_videoEventData.framerate;
1622 return readMpegProc("framerate", !m_is_primary);
1624 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventProgressiveChanged)
1625 return m_videoEventData.progressive;
1626 return readMpegProc("progressive", !m_is_primary);
1628 #warning "FIXMEE implement sFrameRate, sProgressive, sVideoHeight, sVideoWidth for old DVB API"
1633 #if HAVE_DVB_API_VERSION >= 3
1634 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1635 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1636 else if ((val=readMpegProc("aspect", !m_is_primary)) != -1)
1640 #warning "FIXMEE implement sAspect for old DVB API"
1642 if (no_program_info)
1644 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1646 ePtr<eServiceEvent> evt;
1647 if (!m_event_handler.getEvent(evt, 0))
1649 ePtr<eComponentData> data;
1650 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1652 if ( data->getStreamContent() == 1 )
1654 switch(data->getComponentType())
1657 case 1: // 4:3 SD PAL
1659 case 3: // 16:9 SD PAL
1660 case 4: // > 16:9 PAL
1661 case 5: // 4:3 SD NTSC
1663 case 7: // 16:9 SD NTSC
1664 case 8: // > 16:9 NTSC
1667 case 9: // 4:3 HD PAL
1669 case 0xB: // 16:9 HD PAL
1670 case 0xC: // > 16:9 HD PAL
1671 case 0xD: // 4:3 HD NTSC
1673 case 0xF: // 16:9 HD NTSC
1674 case 0x10: // > 16:9 HD PAL
1675 return data->getComponentType();
1683 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1684 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1685 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1686 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1687 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1688 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1689 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1690 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1691 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1692 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1693 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1694 case sProvider: if (!m_dvb_service) return -1; return -2;
1695 case sServiceref: return resIsString;
1696 case sDVBState: return m_tune_state;
1702 std::string eDVBServicePlay::getInfoString(int w)
1707 if (!m_dvb_service) return "";
1708 return m_dvb_service->m_provider_name;
1710 return m_reference.toString();
1714 return iServiceInformation::getInfoString(w);
1717 PyObject *eDVBServicePlay::getInfoObject(int w)
1722 return m_service_handler.getCaIds();
1723 case sTransponderData:
1724 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1728 return iServiceInformation::getInfoObject(w);
1731 int eDVBServicePlay::getNumberOfTracks()
1733 eDVBServicePMTHandler::program program;
1734 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1735 if (h.getProgramInfo(program))
1737 return program.audioStreams.size();
1740 int eDVBServicePlay::getCurrentTrack()
1742 eDVBServicePMTHandler::program program;
1743 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1744 if (h.getProgramInfo(program))
1747 int max = program.audioStreams.size();
1750 for (i = 0; i < max; ++i)
1751 if (program.audioStreams[i].pid == m_current_audio_pid)
1757 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1759 int ret = selectAudioStream(i);
1761 if (m_decoder->start())
1767 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1769 eDVBServicePMTHandler::program program;
1770 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1772 if (h.getProgramInfo(program))
1775 if (i >= program.audioStreams.size())
1778 info.m_pid = program.audioStreams[i].pid;
1780 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1781 info.m_description = "MPEG";
1782 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1783 info.m_description = "AC3";
1784 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1785 info.m_description = "AAC";
1786 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1787 info.m_description = "DTS";
1789 info.m_description = "???";
1791 if (program.audioStreams[i].component_tag != -1)
1793 ePtr<eServiceEvent> evt;
1794 if (!m_event_handler.getEvent(evt, 0))
1796 ePtr<eComponentData> data;
1797 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1798 info.m_language = data->getText();
1802 if (info.m_language.empty())
1803 info.m_language = program.audioStreams[i].language_code;
1808 int eDVBServicePlay::selectAudioStream(int i)
1810 eDVBServicePMTHandler::program program;
1811 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1813 if (h.getProgramInfo(program))
1816 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1824 stream = program.defaultAudioStream;
1826 int apid = -1, apidtype = -1;
1828 if (((unsigned int)stream) < program.audioStreams.size())
1830 apid = program.audioStreams[stream].pid;
1831 apidtype = program.audioStreams[stream].type;
1834 m_current_audio_pid = apid;
1836 if (m_decoder->setAudioPID(apid, apidtype))
1838 eDebug("set audio pid failed");
1842 /* if we are not in PVR mode, timeshift is not active and we are not in pip mode, check if we need to enable the rds reader */
1843 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1846 ePtr<iDVBDemux> data_demux;
1847 if (!h.getDataDemux(data_demux))
1849 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1850 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1854 /* if we decided that we need one, update the pid */
1856 m_rds_decoder->start(apid);
1858 /* store new pid as default only when:
1859 a.) we have an entry in the service db for the current service,
1860 b.) we are not playing back something,
1861 c.) we are not selecting the default entry. (we wouldn't change
1862 anything in the best case, or destroy the default setting in
1863 case the real default is not yet available.)
1865 if (m_dvb_service && !m_is_pvr && ((i != -1)
1866 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1868 if (apidtype == eDVBAudio::aMPEG)
1870 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1871 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1875 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1876 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1880 h.resetCachedProgram();
1885 int eDVBServicePlay::getCurrentChannel()
1887 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1890 RESULT eDVBServicePlay::selectChannel(int i)
1892 if (i < LEFT || i > RIGHT || i == STEREO)
1895 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1897 m_decoder->setAudioChannel(i);
1901 std::string eDVBServicePlay::getText(int x)
1907 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1909 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1914 void eDVBServicePlay::rdsDecoderEvent(int what)
1918 case eDVBRdsDecoder::RadioTextChanged:
1919 m_event((iPlayableService*)this, evUpdatedRadioText);
1921 case eDVBRdsDecoder::RtpTextChanged:
1922 m_event((iPlayableService*)this, evUpdatedRtpText);
1924 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1925 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1927 case eDVBRdsDecoder::RecvRassSlidePic:
1928 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1933 void eDVBServicePlay::showRassSlidePicture()
1939 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1940 if (rass_slide_pic.length())
1941 m_decoder->showSinglePic(rass_slide_pic.c_str());
1943 eDebug("empty filename for rass slide picture received!!");
1946 eDebug("no MPEG Decoder to show iframes avail");
1949 eDebug("showRassSlidePicture called.. but not decoder");
1952 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1958 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1959 if (rass_interactive_pic.length())
1960 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1962 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1965 eDebug("no MPEG Decoder to show iframes avail");
1968 eDebug("showRassInteractivePic called.. but not decoder");
1971 ePyObject eDVBServicePlay::getRassInteractiveMask()
1974 return m_rds_decoder->getRassPictureMask();
1978 int eDVBServiceBase::getFrontendInfo(int w)
1980 eUsePtr<iDVBChannel> channel;
1981 if(m_service_handler.getChannel(channel))
1983 ePtr<iDVBFrontend> fe;
1984 if(channel->getFrontend(fe))
1986 return fe->readFrontendData(w);
1989 PyObject *eDVBServiceBase::getFrontendData()
1991 ePyObject ret = PyDict_New();
1994 eUsePtr<iDVBChannel> channel;
1995 if(!m_service_handler.getChannel(channel))
1997 ePtr<iDVBFrontend> fe;
1998 if(!channel->getFrontend(fe))
1999 fe->getFrontendData(ret);
2007 PyObject *eDVBServiceBase::getFrontendStatus()
2009 ePyObject ret = PyDict_New();
2012 eUsePtr<iDVBChannel> channel;
2013 if(!m_service_handler.getChannel(channel))
2015 ePtr<iDVBFrontend> fe;
2016 if(!channel->getFrontend(fe))
2017 fe->getFrontendStatus(ret);
2025 PyObject *eDVBServiceBase::getTransponderData(bool original)
2027 ePyObject ret = PyDict_New();
2030 eUsePtr<iDVBChannel> channel;
2031 if(!m_service_handler.getChannel(channel))
2033 ePtr<iDVBFrontend> fe;
2034 if(!channel->getFrontend(fe))
2036 fe->getTransponderData(ret, original);
2037 ePtr<iDVBFrontendParameters> feparm;
2038 channel->getCurrentFrontendParameters(feparm);
2041 eDVBFrontendParametersSatellite osat;
2042 if (!feparm->getDVBS(osat))
2044 PutToDict(ret, "orbital_position", osat.orbital_position);
2045 const char *tmp = "UNKNOWN";
2046 switch(osat.polarisation)
2048 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2049 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2050 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2051 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2054 PutToDict(ret, "polarization", tmp);
2065 PyObject *eDVBServiceBase::getAll(bool original)
2067 ePyObject ret = getTransponderData(original);
2070 eUsePtr<iDVBChannel> channel;
2071 if(!m_service_handler.getChannel(channel))
2073 ePtr<iDVBFrontend> fe;
2074 if(!channel->getFrontend(fe))
2076 fe->getFrontendData(ret);
2077 fe->getFrontendStatus(ret);
2084 int eDVBServicePlay::getNumberOfSubservices()
2086 ePtr<eServiceEvent> evt;
2087 if (!m_event_handler.getEvent(evt, 0))
2088 return evt->getNumOfLinkageServices();
2092 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2094 ePtr<eServiceEvent> evt;
2095 if (!m_event_handler.getEvent(evt, 0))
2097 if (!evt->getLinkageService(sub, m_reference, n))
2100 sub.type=eServiceReference::idInvalid;
2104 RESULT eDVBServicePlay::startTimeshift()
2106 ePtr<iDVBDemux> demux;
2108 eDebug("Start timeshift!");
2110 if (m_timeshift_enabled)
2113 /* start recording with the data demux. */
2114 if (m_service_handler.getDataDemux(demux))
2117 demux->createTSRecorder(m_record);
2122 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2123 eDebug("could not query ts path");
2126 tspath.append("/timeshift.XXXXXX");
2128 templ = new char[tspath.length() + 1];
2129 strcpy(templ, tspath.c_str());
2131 m_timeshift_fd = mkstemp(templ);
2132 m_timeshift_file = std::string(templ);
2134 eDebug("recording to %s", templ);
2138 if (m_timeshift_fd < 0)
2144 m_record->setTargetFD(m_timeshift_fd);
2146 m_timeshift_enabled = 1;
2148 updateTimeshiftPids();
2154 RESULT eDVBServicePlay::stopTimeshift()
2156 if (!m_timeshift_enabled)
2161 m_timeshift_enabled = 0;
2166 close(m_timeshift_fd);
2167 eDebug("remove timeshift file");
2168 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2173 int eDVBServicePlay::isTimeshiftActive()
2175 return m_timeshift_enabled && m_timeshift_active;
2178 RESULT eDVBServicePlay::activateTimeshift()
2180 if (!m_timeshift_enabled)
2183 if (!m_timeshift_active)
2185 switchToTimeshift();
2192 PyObject *eDVBServicePlay::getCutList()
2194 ePyObject list = PyList_New(0);
2196 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2198 ePyObject tuple = PyTuple_New(2);
2199 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2200 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2201 PyList_Append(list, tuple);
2208 void eDVBServicePlay::setCutList(ePyObject list)
2210 if (!PyList_Check(list))
2212 int size = PyList_Size(list);
2215 m_cue_entries.clear();
2217 for (i=0; i<size; ++i)
2219 ePyObject tuple = PyList_GET_ITEM(list, i);
2220 if (!PyTuple_Check(tuple))
2222 eDebug("non-tuple in cutlist");
2225 if (PyTuple_Size(tuple) != 2)
2227 eDebug("cutlist entries need to be a 2-tuple");
2230 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2231 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2233 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2236 pts_t pts = PyLong_AsLongLong(ppts);
2237 int type = PyInt_AsLong(ptype);
2238 m_cue_entries.insert(cueEntry(pts, type));
2239 eDebug("adding %08llx, %d", pts, type);
2241 m_cuesheet_changed = 1;
2243 cutlistToCuesheet();
2244 m_event((iPlayableService*)this, evCuesheetChanged);
2247 void eDVBServicePlay::setCutListEnable(int enable)
2249 m_cutlist_enabled = enable;
2250 cutlistToCuesheet();
2253 void eDVBServicePlay::updateTimeshiftPids()
2258 eDVBServicePMTHandler::program program;
2259 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2261 if (h.getProgramInfo(program))
2265 std::set<int> pids_to_record;
2266 pids_to_record.insert(0); // PAT
2267 if (program.pmtPid != -1)
2268 pids_to_record.insert(program.pmtPid); // PMT
2270 if (program.textPid != -1)
2271 pids_to_record.insert(program.textPid); // Videotext
2273 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2274 i(program.videoStreams.begin());
2275 i != program.videoStreams.end(); ++i)
2276 pids_to_record.insert(i->pid);
2278 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2279 i(program.audioStreams.begin());
2280 i != program.audioStreams.end(); ++i)
2281 pids_to_record.insert(i->pid);
2283 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2284 i(program.subtitleStreams.begin());
2285 i != program.subtitleStreams.end(); ++i)
2286 pids_to_record.insert(i->pid);
2288 std::set<int> new_pids, obsolete_pids;
2290 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2291 m_pids_active.begin(), m_pids_active.end(),
2292 std::inserter(new_pids, new_pids.begin()));
2294 std::set_difference(
2295 m_pids_active.begin(), m_pids_active.end(),
2296 pids_to_record.begin(), pids_to_record.end(),
2297 std::inserter(new_pids, new_pids.begin())
2300 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2301 m_record->addPID(*i);
2303 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2304 m_record->removePID(*i);
2308 void eDVBServicePlay::switchToLive()
2310 if (!m_timeshift_active)
2316 m_teletext_parser = 0;
2318 m_subtitle_parser = 0;
2319 m_new_dvb_subtitle_page_connection = 0;
2320 m_new_subtitle_page_connection = 0;
2321 m_rds_decoder_event_connection = 0;
2322 m_video_event_connection = 0;
2324 /* free the timeshift service handler, we need the resources */
2325 m_service_handler_timeshift.free();
2326 m_timeshift_active = 0;
2328 m_event((iPlayableService*)this, evSeekableStatusChanged);
2333 void eDVBServicePlay::switchToTimeshift()
2335 if (m_timeshift_active)
2340 m_teletext_parser = 0;
2342 m_subtitle_parser = 0;
2343 m_new_subtitle_page_connection = 0;
2344 m_new_dvb_subtitle_page_connection = 0;
2345 m_rds_decoder_event_connection = 0;
2346 m_video_event_connection = 0;
2348 m_timeshift_active = 1;
2350 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2351 r.path = m_timeshift_file;
2353 m_cue = new eCueSheet();
2354 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2356 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2358 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2360 m_event((iPlayableService*)this, evSeekableStatusChanged);
2363 void eDVBServicePlay::updateDecoder()
2365 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2367 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2369 eDVBServicePMTHandler::program program;
2370 if (h.getProgramInfo(program))
2371 eDebug("getting program info failed.");
2374 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2375 if (!program.videoStreams.empty())
2377 eDebugNoNewLine(" (");
2378 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2379 i(program.videoStreams.begin());
2380 i != program.videoStreams.end(); ++i)
2387 if (i != program.videoStreams.begin())
2388 eDebugNoNewLine(", ");
2389 eDebugNoNewLine("%04x", i->pid);
2391 eDebugNoNewLine(")");
2393 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2394 if (!program.audioStreams.empty())
2396 eDebugNoNewLine(" (");
2397 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2398 i(program.audioStreams.begin());
2399 i != program.audioStreams.end(); ++i)
2401 if (i != program.audioStreams.begin())
2402 eDebugNoNewLine(", ");
2403 eDebugNoNewLine("%04x", i->pid);
2405 eDebugNoNewLine(")");
2407 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2408 pcrpid = program.pcrPid;
2409 eDebug(", and the text pid is %04x", program.textPid);
2410 tpid = program.textPid;
2415 h.getDecodeDemux(m_decode_demux);
2418 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2420 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2421 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2422 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2423 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2424 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2427 m_teletext_parser = 0;
2428 m_subtitle_parser = 0;
2432 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2439 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2440 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2441 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2443 else // subservice or recording
2445 eServiceReferenceDVB ref;
2446 m_service_handler.getServiceReference(ref);
2447 eServiceReferenceDVB parent = ref.getParentServiceReference();
2452 ePtr<eDVBResourceManager> res_mgr;
2453 if (!eDVBResourceManager::getInstance(res_mgr))
2455 ePtr<iDVBChannelList> db;
2456 if (!res_mgr->getChannelList(db))
2458 ePtr<eDVBService> origService;
2459 if (!db->getService(parent, origService))
2461 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2462 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2468 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2469 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2471 m_decoder->setVideoPID(vpid, vpidtype);
2472 selectAudioStream();
2474 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2475 m_decoder->setSyncPCR(pcrpid);
2477 m_decoder->setSyncPCR(-1);
2479 m_decoder->setTextPID(tpid);
2481 m_teletext_parser->start(program.textPid);
2484 m_decoder->setTrickmode(1);
2487 m_decoder->preroll();
2491 if (vpid > 0 && vpid < 0x2000)
2495 std::string radio_pic;
2496 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2497 m_decoder->setRadioPic(radio_pic);
2500 m_decoder->setAudioChannel(achannel);
2502 /* don't worry about non-existing services, nor pvr services */
2503 if (m_dvb_service && !m_is_pvr)
2505 /* (audio pid will be set in selectAudioTrack */
2506 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2507 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2508 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2509 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2512 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2515 void eDVBServicePlay::loadCuesheet()
2517 std::string filename = m_reference.path + ".cuts";
2519 m_cue_entries.clear();
2521 FILE *f = fopen(filename.c_str(), "rb");
2525 eDebug("loading cuts..");
2528 unsigned long long where;
2531 if (!fread(&where, sizeof(where), 1, f))
2533 if (!fread(&what, sizeof(what), 1, f))
2536 #if BYTE_ORDER == LITTLE_ENDIAN
2537 where = bswap_64(where);
2544 m_cue_entries.insert(cueEntry(where, what));
2547 eDebug("%d entries", m_cue_entries.size());
2549 eDebug("cutfile not found!");
2551 m_cuesheet_changed = 0;
2552 cutlistToCuesheet();
2553 m_event((iPlayableService*)this, evCuesheetChanged);
2556 void eDVBServicePlay::saveCuesheet()
2558 std::string filename = m_reference.path + ".cuts";
2560 FILE *f = fopen(filename.c_str(), "wb");
2564 unsigned long long where;
2567 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2569 #if BYTE_ORDER == BIG_ENDIAN
2572 where = bswap_64(i->where);
2574 what = htonl(i->what);
2575 fwrite(&where, sizeof(where), 1, f);
2576 fwrite(&what, sizeof(what), 1, f);
2582 m_cuesheet_changed = 0;
2585 void eDVBServicePlay::cutlistToCuesheet()
2589 eDebug("no cue sheet");
2594 if (!m_cutlist_enabled)
2596 m_cue->commitSpans();
2597 eDebug("cutlists were disabled");
2601 pts_t in = 0, out = 0, length = 0;
2605 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2609 if (i == m_cue_entries.end())
2612 if (i->what == 0) /* in */
2616 } else if (i->what == 1) /* out */
2618 else /* mark (2) or last play position (3) */
2635 m_cue->addSourceSpan(in, out);
2639 if (i == m_cue_entries.end())
2642 m_cue->commitSpans();
2645 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2647 if (m_subtitle_widget)
2648 disableSubtitles(parent);
2651 int tuplesize = PyTuple_Size(tuple);
2654 if (!PyTuple_Check(tuple))
2660 entry = PyTuple_GET_ITEM(tuple, 0);
2662 if (!PyInt_Check(entry))
2665 type = PyInt_AsLong(entry);
2667 if (type == 1) // teletext subtitles
2669 int page, magazine, pid;
2673 if (!m_teletext_parser)
2675 eDebug("enable teletext subtitles.. no parser !!!");
2679 entry = PyTuple_GET_ITEM(tuple, 1);
2680 if (!PyInt_Check(entry))
2682 pid = PyInt_AsLong(entry);
2684 entry = PyTuple_GET_ITEM(tuple, 2);
2685 if (!PyInt_Check(entry))
2687 page = PyInt_AsLong(entry);
2689 entry = PyTuple_GET_ITEM(tuple, 3);
2690 if (!PyInt_Check(entry))
2692 magazine = PyInt_AsLong(entry);
2694 m_subtitle_widget = new eSubtitleWidget(parent);
2695 m_subtitle_widget->resize(parent->size()); /* full size */
2696 m_teletext_parser->setPageAndMagazine(page, magazine);
2698 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2702 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2703 if (!m_subtitle_parser)
2705 eDebug("enable dvb subtitles.. no parser !!!");
2711 entry = PyTuple_GET_ITEM(tuple, 1);
2712 if (!PyInt_Check(entry))
2714 pid = PyInt_AsLong(entry);
2716 entry = PyTuple_GET_ITEM(tuple, 2);
2717 if (!PyInt_Check(entry))
2719 composition_page_id = PyInt_AsLong(entry);
2721 entry = PyTuple_GET_ITEM(tuple, 3);
2722 if (!PyInt_Check(entry))
2724 ancillary_page_id = PyInt_AsLong(entry);
2726 m_subtitle_widget = new eSubtitleWidget(parent);
2727 m_subtitle_widget->resize(parent->size()); /* full size */
2728 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2730 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2736 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2737 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2738 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2742 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2744 delete m_subtitle_widget;
2745 m_subtitle_widget = 0;
2746 if (m_subtitle_parser)
2748 m_subtitle_parser->stop();
2749 m_dvb_subtitle_pages.clear();
2751 if (m_teletext_parser)
2753 m_teletext_parser->setPageAndMagazine(-1, -1);
2754 m_subtitle_pages.clear();
2757 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2761 PyObject *eDVBServicePlay::getCachedSubtitle()
2765 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2768 unsigned int data = (unsigned int)tmp;
2769 int pid = (data&0xFFFF0000)>>16;
2770 ePyObject tuple = PyTuple_New(4);
2771 eDVBServicePMTHandler::program program;
2772 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2773 if (!h.getProgramInfo(program))
2775 if (program.textPid==pid) // teletext
2776 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2778 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2779 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2780 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2781 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2789 PyObject *eDVBServicePlay::getSubtitleList()
2791 if (!m_teletext_parser)
2794 ePyObject l = PyList_New(0);
2795 std::set<int> added_ttx_pages;
2797 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2798 m_teletext_parser->m_found_subtitle_pages;
2800 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2801 eDVBServicePMTHandler::program program;
2802 if (h.getProgramInfo(program))
2803 eDebug("getting program info failed.");
2806 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2807 it != program.subtitleStreams.end(); ++it)
2809 switch(it->subtitling_type)
2811 case 0x01: // ebu teletext subtitles
2813 int page_number = it->teletext_page_number & 0xFF;
2814 int magazine_number = it->teletext_magazine_number & 7;
2815 int hash = magazine_number << 8 | page_number;
2816 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2818 ePyObject tuple = PyTuple_New(5);
2819 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2820 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2821 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2822 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2823 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2824 PyList_Append(l, tuple);
2826 added_ttx_pages.insert(hash);
2831 case 0x20 ... 0x23: // dvb subtitles
2833 ePyObject tuple = PyTuple_New(5);
2834 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2835 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2836 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2837 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2838 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2839 PyList_Insert(l, 0, tuple);
2847 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2848 it != subs.end(); ++it)
2850 int page_number = it->teletext_page_number & 0xFF;
2851 int magazine_number = it->teletext_magazine_number & 7;
2852 int hash = magazine_number << 8 | page_number;
2853 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2855 ePyObject tuple = PyTuple_New(5);
2856 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2857 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2858 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2859 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2860 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2861 PyList_Append(l, tuple);
2869 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2871 if (m_subtitle_widget)
2875 m_decoder->getPTS(0, pos);
2876 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2877 m_subtitle_pages.push_back(page);
2878 checkSubtitleTiming();
2882 void eDVBServicePlay::checkSubtitleTiming()
2884 eDebug("checkSubtitleTiming");
2885 if (!m_subtitle_widget)
2889 enum { TELETEXT, DVB } type;
2890 eDVBTeletextSubtitlePage page;
2891 eDVBSubtitlePage dvb_page;
2893 if (!m_subtitle_pages.empty())
2895 page = m_subtitle_pages.front();
2897 show_time = page.m_pts;
2899 else if (!m_dvb_subtitle_pages.empty())
2901 dvb_page = m_dvb_subtitle_pages.front();
2903 show_time = dvb_page.m_show_time;
2911 m_decoder->getPTS(0, pos);
2913 eDebug("%lld %lld", pos, show_time);
2914 int diff = show_time - pos;
2917 eDebug("[late (%d ms)]", -diff / 90);
2920 // if (diff > 900000)
2922 // eDebug("[invalid]");
2928 if (type == TELETEXT)
2930 eDebug("display teletext subtitle page %lld", show_time);
2931 m_subtitle_widget->setPage(page);
2932 m_subtitle_pages.pop_front();
2936 eDebug("display dvb subtitle Page %lld", show_time);
2937 m_subtitle_widget->setPage(dvb_page);
2938 m_dvb_subtitle_pages.pop_front();
2942 eDebug("start subtitle delay %d", diff / 90);
2943 m_subtitle_sync_timer->start(diff / 90, 1);
2949 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2951 if (m_subtitle_widget)
2955 m_decoder->getPTS(0, pos);
2956 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2957 m_dvb_subtitle_pages.push_back(p);
2958 checkSubtitleTiming();
2962 int eDVBServicePlay::getAC3Delay()
2965 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2967 return m_decoder->getAC3Delay();
2972 int eDVBServicePlay::getPCMDelay()
2975 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2977 return m_decoder->getPCMDelay();
2982 void eDVBServicePlay::setAC3Delay(int delay)
2985 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2987 m_decoder->setAC3Delay(delay);
2990 void eDVBServicePlay::setPCMDelay(int delay)
2993 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2995 m_decoder->setPCMDelay(delay);
2998 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3000 memcpy(&m_videoEventData, &event, sizeof(event));
3001 switch(event.type) {
3002 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3003 m_event((iPlayableService*)this, evVideoSizeChanged);
3005 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3006 m_event((iPlayableService*)this, evVideoFramerateChanged);
3008 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3009 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3016 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3022 PyObject *eDVBServicePlay::getStreamingData()
3024 eDVBServicePMTHandler::program program;
3025 if (m_service_handler.getProgramInfo(program))
3030 ePyObject r = program.createPythonObject();
3031 ePtr<iDVBDemux> demux;
3032 if (!m_service_handler.getDataDemux(demux))
3035 if (!demux->getCADemuxID(demux_id))
3036 PutToDict(r, "demux", PyInt_FromLong(demux_id));
3043 DEFINE_REF(eDVBServicePlay)
3045 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3049 case iServiceInformation::sTransponderData:
3050 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3054 return iStaticServiceInformation::getInfoObject(ref, w);
3057 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");