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 #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.rolloff)
172 case eDVBFrontendParametersSatellite::RollOff::alpha_0_35: tmp="0.35"; break;
173 case eDVBFrontendParametersSatellite::RollOff::alpha_0_25: tmp="0.25"; break;
174 case eDVBFrontendParametersSatellite::RollOff::alpha_0_20: tmp="0.20"; break;
176 PutToDict(dict, "roll off", tmp);
177 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK)
181 case eDVBFrontendParametersSatellite::Pilot::On: tmp="ON"; break;
182 case eDVBFrontendParametersSatellite::Pilot::Off: tmp="OFF"; break;
184 case eDVBFrontendParametersSatellite::Pilot::Unknown: tmp="AUTO"; break;
186 PutToDict(dict, "pilot", tmp);
191 PutToDict(dict, "system", tmp);
194 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
196 PutToDict(dict, "type", "Terrestrial");
197 PutToDict(dict, "frequency", feparm.frequency);
199 switch (feparm.bandwidth)
201 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz: tmp="8 MHz"; break;
202 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz: tmp="7 MHz"; break;
203 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz: tmp="6 MHz"; break;
205 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto: tmp="AUTO"; break;
207 PutToDict(dict, "bandwidth", tmp);
208 switch (feparm.code_rate_LP)
210 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
211 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
212 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
213 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
214 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
216 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
218 PutToDict(dict, "code rate lp", tmp);
219 switch (feparm.code_rate_HP)
221 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
222 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
223 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
224 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
225 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
227 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
229 PutToDict(dict, "code rate hp", tmp);
230 switch (feparm.modulation)
232 case eDVBFrontendParametersTerrestrial::Modulation::QPSK: tmp="QPSK"; break;
233 case eDVBFrontendParametersTerrestrial::Modulation::QAM16: tmp="QAM16"; break;
234 case eDVBFrontendParametersTerrestrial::Modulation::QAM64: tmp="QAM64"; break;
236 case eDVBFrontendParametersTerrestrial::Modulation::Auto: tmp="AUTO"; break;
238 PutToDict(dict, "constellation", tmp);
239 switch (feparm.transmission_mode)
241 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k: tmp="2k"; break;
242 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k: tmp="8k"; break;
244 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto: tmp="AUTO"; break;
246 PutToDict(dict, "transmission mode", tmp);
247 switch (feparm.guard_interval)
249 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32: tmp="1/32"; break;
250 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16: tmp="1/16"; break;
251 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8: tmp="1/8"; break;
252 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4: tmp="1/4"; break;
254 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto: tmp="AUTO"; break;
256 PutToDict(dict, "guard interval", tmp);
257 switch (feparm.hierarchy)
259 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone: tmp="NONE"; break;
260 case eDVBFrontendParametersTerrestrial::Hierarchy::H1: tmp="1"; break;
261 case eDVBFrontendParametersTerrestrial::Hierarchy::H2: tmp="2"; break;
262 case eDVBFrontendParametersTerrestrial::Hierarchy::H4: tmp="4"; break;
264 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto: tmp="AUTO"; break;
266 PutToDict(dict, "hierarchy", tmp);
267 switch (feparm.inversion)
269 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
270 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
272 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
274 PutToDict(dict, "inversion", tmp);
277 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
280 PutToDict(dict, "type", "Cable");
281 PutToDict(dict, "frequency", feparm.frequency);
282 PutToDict(dict, "symbolrate", feparm.symbol_rate);
283 switch (feparm.modulation)
285 case eDVBFrontendParametersCable::Modulation::QAM16: tmp="QAM16"; break;
286 case eDVBFrontendParametersCable::Modulation::QAM32: tmp="QAM32"; break;
287 case eDVBFrontendParametersCable::Modulation::QAM64: tmp="QAM64"; break;
288 case eDVBFrontendParametersCable::Modulation::QAM128: tmp="QAM128"; break;
289 case eDVBFrontendParametersCable::Modulation::QAM256: tmp="QAM256"; break;
291 case eDVBFrontendParametersCable::Modulation::Auto: tmp="AUTO"; break;
293 PutToDict(dict, "modulation", tmp);
294 switch (feparm.inversion)
296 case eDVBFrontendParametersCable::Inversion::On: tmp="ON"; break;
297 case eDVBFrontendParametersCable::Inversion::Off: tmp="OFF"; break;
299 case eDVBFrontendParametersCable::Inversion::Unknown: tmp="AUTO"; break;
301 PutToDict(dict, "inversion", tmp);
302 switch (feparm.fec_inner)
304 case eDVBFrontendParametersCable::FEC::fNone: tmp="NONE"; break;
305 case eDVBFrontendParametersCable::FEC::f1_2: tmp="1/2"; break;
306 case eDVBFrontendParametersCable::FEC::f2_3: tmp="2/3"; break;
307 case eDVBFrontendParametersCable::FEC::f3_4: tmp="3/4"; break;
308 case eDVBFrontendParametersCable::FEC::f5_6: tmp="5/6"; break;
309 case eDVBFrontendParametersCable::FEC::f7_8: tmp="7/8"; break;
310 case eDVBFrontendParametersCable::FEC::f8_9: tmp="8/9"; break;
312 case eDVBFrontendParametersCable::FEC::fAuto: tmp="AUTO"; break;
314 PutToDict(dict, "fec inner", tmp);
317 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
319 if (r.type == eServiceReference::idDVB)
321 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
324 case iServiceInformation::sTransponderData:
326 ePtr<eDVBResourceManager> res;
327 if (!eDVBResourceManager::getInstance(res))
329 ePtr<iDVBChannelList> db;
330 if (!res->getChannelList(db))
333 ref.getChannelID(chid);
334 ePtr<iDVBFrontendParameters> feparm;
335 if (!db->getChannelFrontendData(chid, feparm))
338 if (!feparm->getSystem(system))
340 ePyObject dict = PyDict_New();
343 case iDVBFrontend::feSatellite:
345 eDVBFrontendParametersSatellite s;
347 PutSatelliteDataToDict(dict, s);
350 case iDVBFrontend::feTerrestrial:
352 eDVBFrontendParametersTerrestrial t;
354 PutTerrestrialDataToDict(dict, t);
357 case iDVBFrontend::feCable:
359 eDVBFrontendParametersCable c;
361 PutCableDataToDict(dict, c);
365 eDebug("unknown frontend type %d", system);
380 DEFINE_REF(eStaticServiceDVBBouquetInformation);
382 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
384 ePtr<iDVBChannelList> db;
385 ePtr<eDVBResourceManager> res;
388 if ((err = eDVBResourceManager::getInstance(res)) != 0)
390 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
393 if ((err = res->getChannelList(db)) != 0)
395 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
400 if ((err = db->getBouquet(ref, bouquet)) != 0)
402 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
406 if ( bouquet && bouquet->m_bouquet_name.length() )
408 name = bouquet->m_bouquet_name;
415 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
417 if (ref.flags & eServiceReference::isGroup)
419 ePtr<iDVBChannelList> db;
420 ePtr<eDVBResourceManager> res;
422 if (eDVBResourceManager::getInstance(res))
424 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
428 if (res->getChannelList(db))
430 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
435 if (db->getBouquet(ref, bouquet))
437 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
441 int prio_order = eDVBFrontend::getTypePriorityOrder();
443 eDVBChannelID chid, chid_ignore;
444 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
445 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
447 static unsigned char prio_map[6][3] = {
448 { 3, 2, 1 }, // -S -C -T
449 { 3, 1, 2 }, // -S -T -C
450 { 2, 3, 1 }, // -C -S -T
451 { 1, 3, 2 }, // -C -T -S
452 { 1, 2, 3 }, // -T -C -S
453 { 2, 1, 3 } // -T -S -C
455 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
456 int tmp=res->canAllocateChannel(chid, chid_ignore);
461 case 30000: // cached DVB-T channel
462 case 1: // DVB-T frontend
463 tmp = prio_map[prio_order][2];
465 case 40000: // cached DVB-C channel
467 tmp = prio_map[prio_order][1];
470 tmp = prio_map[prio_order][0];
475 m_playable_service = *it;
482 m_playable_service = eServiceReference();
486 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
491 #include <lib/dvb/epgcache.h>
493 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
495 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
498 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
500 DECLARE_REF(eStaticServiceDVBPVRInformation);
501 eServiceReference m_ref;
502 eDVBMetaParser m_parser;
504 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
505 RESULT getName(const eServiceReference &ref, std::string &name);
506 int getLength(const eServiceReference &ref);
507 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
508 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
509 int getInfo(const eServiceReference &ref, int w);
510 std::string getInfoString(const eServiceReference &ref,int w);
513 DEFINE_REF(eStaticServiceDVBPVRInformation);
515 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
518 m_parser.parseFile(ref.path);
521 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
523 ASSERT(ref == m_ref);
524 if (m_parser.m_name.size())
525 name = m_parser.m_name;
529 size_t n = name.rfind('/');
530 if (n != std::string::npos)
531 name = name.substr(n + 1);
536 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
538 ASSERT(ref == m_ref);
542 if (tstools.openFile(ref.path.c_str()))
546 if (tstools.calcLen(len))
552 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
556 case iServiceInformation::sDescription:
557 return iServiceInformation::resIsString;
558 case iServiceInformation::sServiceref:
559 return iServiceInformation::resIsString;
560 case iServiceInformation::sTimeCreate:
561 if (m_parser.m_time_create)
562 return m_parser.m_time_create;
564 return iServiceInformation::resNA;
566 return iServiceInformation::resNA;
570 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
574 case iServiceInformation::sDescription:
575 return m_parser.m_description;
576 case iServiceInformation::sServiceref:
577 return m_parser.m_ref.toString();
578 case iServiceInformation::sTags:
579 return m_parser.m_tags;
585 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
587 if (!ref.path.empty())
589 ePtr<eServiceEvent> event = new eServiceEvent;
590 std::string filename = ref.path;
591 filename.erase(filename.length()-2, 2);
593 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
603 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
605 DECLARE_REF(eDVBPVRServiceOfflineOperations);
606 eServiceReferenceDVB m_ref;
608 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
610 RESULT deleteFromDisk(int simulate);
611 RESULT getListOfFilenames(std::list<std::string> &);
614 DEFINE_REF(eDVBPVRServiceOfflineOperations);
616 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
620 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
626 std::list<std::string> res;
627 if (getListOfFilenames(res))
630 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
632 eDebug("FATAL !! can't get background file eraser");
634 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
636 eDebug("Removing %s...", i->c_str());
638 eraser->erase(i->c_str());
640 ::unlink(i->c_str());
647 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
650 res.push_back(m_ref.path);
652 // handling for old splitted recordings (enigma 1)
657 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
659 if (stat(buf, &s) < 0)
664 res.push_back(m_ref.path + ".meta");
665 res.push_back(m_ref.path + ".ap");
666 res.push_back(m_ref.path + ".cuts");
667 std::string tmp = m_ref.path;
668 tmp.erase(m_ref.path.length()-3);
669 res.push_back(tmp + ".eit");
673 DEFINE_REF(eServiceFactoryDVB)
675 eServiceFactoryDVB::eServiceFactoryDVB()
677 ePtr<eServiceCenter> sc;
679 eServiceCenter::getPrivInstance(sc);
682 std::list<std::string> extensions;
683 extensions.push_back("ts");
684 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
687 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
688 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
691 eServiceFactoryDVB::~eServiceFactoryDVB()
693 ePtr<eServiceCenter> sc;
695 eServiceCenter::getPrivInstance(sc);
697 sc->removeServiceFactory(eServiceFactoryDVB::id);
700 DEFINE_REF(eDVBServiceList);
702 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
706 eDVBServiceList::~eDVBServiceList()
710 RESULT eDVBServiceList::startQuery()
712 ePtr<iDVBChannelList> db;
713 ePtr<eDVBResourceManager> res;
716 if ((err = eDVBResourceManager::getInstance(res)) != 0)
718 eDebug("no resource manager");
721 if ((err = res->getChannelList(db)) != 0)
723 eDebug("no channel list");
727 ePtr<eDVBChannelQuery> q;
729 if (!m_parent.path.empty())
731 eDVBChannelQuery::compile(q, m_parent.path);
734 eDebug("compile query failed");
739 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
741 eDebug("startQuery failed");
748 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
750 eServiceReferenceDVB ref;
755 while (!m_query->getNextResult(ref))
759 list.sort(iListableServiceCompare(this));
764 // The first argument of this function is a format string to specify the order and
765 // the content of the returned list
766 // useable format options are
767 // R = Service Reference (as swig object .. this is very slow)
768 // S = Service Reference (as python string object .. same as ref.toString())
769 // C = Service Reference (as python string object .. same as ref.toCompareString())
770 // N = Service Name (as python string object)
771 // n = Short Service Name (short name brakets used) (as python string object)
772 // when exactly one return value per service is selected in the format string,
773 // then each value is directly a list entry
774 // when more than one value is returned per service, then the list is a list of
776 // unknown format string chars are returned as python None values !
777 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
780 std::list<eServiceReference> tmplist;
783 if (!format || !(retcount=strlen(format)))
784 format = "R"; // just return service reference swig object ...
786 if (!getContent(tmplist, sorted))
788 int services=tmplist.size();
789 ePtr<iStaticServiceInformation> sptr;
790 eServiceCenterPtr service_center;
792 if (strchr(format, 'N') || strchr(format, 'n'))
793 eServiceCenter::getPrivInstance(service_center);
795 ret = PyList_New(services);
796 std::list<eServiceReference>::iterator it(tmplist.begin());
798 for (int cnt=0; cnt < services; ++cnt)
800 eServiceReference &ref=*it++;
801 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
802 for (int i=0; i < retcount; ++i)
807 case 'R': // service reference (swig)object
808 tmp = NEW_eServiceReference(ref);
810 case 'C': // service reference compare string
811 tmp = PyString_FromString(ref.toCompareString().c_str());
813 case 'S': // service reference string
814 tmp = PyString_FromString(ref.toString().c_str());
816 case 'N': // service name
819 service_center->info(ref, sptr);
823 sptr->getName(ref, name);
825 // filter short name brakets
827 while((pos = name.find("\xc2\x86")) != std::string::npos)
829 while((pos = name.find("\xc2\x87")) != std::string::npos)
833 tmp = PyString_FromString(name.c_str());
837 tmp = PyString_FromString("<n/a>");
839 case 'n': // short service name
842 service_center->info(ref, sptr);
846 sptr->getName(ref, name);
847 name = buildShortName(name);
849 tmp = PyString_FromString(name.c_str());
853 tmp = PyString_FromString("<n/a>");
866 PyTuple_SET_ITEM(tuple, i, tmp);
868 PyList_SET_ITEM(ret, cnt, tmp);
872 PyList_SET_ITEM(ret, cnt, tuple);
875 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
878 RESULT eDVBServiceList::getNext(eServiceReference &ref)
883 return m_query->getNextResult((eServiceReferenceDVB&)ref);
886 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
888 if (m_parent.flags & eServiceReference::canDescent) // bouquet
890 ePtr<iDVBChannelList> db;
891 ePtr<eDVBResourceManager> resm;
893 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
896 if (db->getBouquet(m_parent, m_bouquet) != 0)
907 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
911 return m_bouquet->addService(ref, before);
914 RESULT eDVBServiceList::removeService(eServiceReference &ref)
918 return m_bouquet->removeService(ref);
921 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
925 return m_bouquet->moveService(ref, pos);
928 RESULT eDVBServiceList::flushChanges()
932 return m_bouquet->flushChanges();
935 RESULT eDVBServiceList::setListName(const std::string &name)
939 return m_bouquet->setListName(name);
942 timespec service_start;
944 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
946 ePtr<eDVBService> service;
947 int r = lookupService(service, ref);
950 // check resources...
951 clock_gettime(CLOCK_MONOTONIC, &service_start);
952 ptr = new eDVBServicePlay(ref, service);
956 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
958 if (ref.path.empty())
960 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
969 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
971 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
972 if (list->startQuery())
982 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
984 /* is a listable service? */
985 if (ref.flags & eServiceReference::canDescent) // bouquet
987 if ( !ref.name.empty() ) // satellites or providers list
988 ptr = m_StaticServiceDVBInfo;
989 else // a dvb bouquet
990 ptr = m_StaticServiceDVBBouquetInfo;
992 else if (!ref.path.empty()) /* do we have a PVR service? */
993 ptr = new eStaticServiceDVBPVRInformation(ref);
994 else // normal dvb service
996 ePtr<eDVBService> service;
997 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
998 ptr = m_StaticServiceDVBInfo;
1000 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
1006 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
1008 if (ref.path.empty())
1014 ptr = new eDVBPVRServiceOfflineOperations(ref);
1019 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
1021 // TODO: handle the listing itself
1022 // if (ref.... == -1) .. return "... bouquets ...";
1023 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
1025 ePtr<iDVBChannelList> db;
1026 ePtr<eDVBResourceManager> res;
1029 if ((err = eDVBResourceManager::getInstance(res)) != 0)
1031 eDebug("no resource manager");
1034 if ((err = res->getChannelList(db)) != 0)
1036 eDebug("no channel list");
1040 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
1041 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
1043 eDebug("getService failed!");
1050 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
1051 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
1053 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
1055 m_is_pvr = !m_reference.path.empty();
1057 m_timeshift_enabled = m_timeshift_active = 0;
1060 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
1061 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
1062 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
1064 m_cuesheet_changed = 0;
1065 m_cutlist_enabled = 1;
1067 m_subtitle_widget = 0;
1071 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
1074 eDVBServicePlay::~eDVBServicePlay()
1076 delete m_subtitle_widget;
1079 void eDVBServicePlay::gotNewEvent()
1083 ePtr<eServiceEvent> m_event_now, m_event_next;
1084 getEvent(m_event_now, 0);
1085 getEvent(m_event_next, 1);
1088 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1090 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1092 m_event((iPlayableService*)this, evUpdatedEventInfo);
1095 void eDVBServicePlay::serviceEvent(int event)
1097 m_tune_state = event;
1101 case eDVBServicePMTHandler::eventTuned:
1103 ePtr<iDVBDemux> m_demux;
1104 if (!m_service_handler.getDataDemux(m_demux))
1106 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1107 int sid = ref.getParentServiceID().get();
1109 sid = ref.getServiceID().get();
1110 if ( ref.getParentTransportStreamID().get() &&
1111 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1112 m_event_handler.startOther(m_demux, sid);
1114 m_event_handler.start(m_demux, sid);
1116 m_event((iPlayableService*)this, evTunedIn);
1119 case eDVBServicePMTHandler::eventNoResources:
1120 case eDVBServicePMTHandler::eventNoPAT:
1121 case eDVBServicePMTHandler::eventNoPATEntry:
1122 case eDVBServicePMTHandler::eventNoPMT:
1123 case eDVBServicePMTHandler::eventTuneFailed:
1124 case eDVBServicePMTHandler::eventMisconfiguration:
1126 eDebug("DVB service failed to tune - error %d", event);
1127 m_event((iPlayableService*)this, evTuneFailed);
1130 case eDVBServicePMTHandler::eventNewProgramInfo:
1132 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1133 if (m_timeshift_enabled)
1134 updateTimeshiftPids();
1135 if (!m_timeshift_active)
1137 if (m_first_program_info && m_is_pvr)
1139 m_first_program_info = 0;
1142 m_event((iPlayableService*)this, evUpdatedInfo);
1145 case eDVBServicePMTHandler::eventEOF:
1146 m_event((iPlayableService*)this, evEOF);
1148 case eDVBServicePMTHandler::eventSOF:
1149 m_event((iPlayableService*)this, evSOF);
1154 void eDVBServicePlay::serviceEventTimeshift(int event)
1158 case eDVBServicePMTHandler::eventNewProgramInfo:
1159 if (m_timeshift_active)
1162 case eDVBServicePMTHandler::eventSOF:
1163 m_event((iPlayableService*)this, evSOF);
1165 case eDVBServicePMTHandler::eventEOF:
1166 if ((!m_is_paused) && (m_skipmode >= 0))
1172 RESULT eDVBServicePlay::start()
1175 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1176 two (one for decoding, one for data source), as we must be prepared
1177 to start recording from the data demux. */
1179 m_cue = new eCueSheet();
1181 m_event(this, evStart);
1183 m_first_program_info = 1;
1184 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1185 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1187 /* inject EIT if there is a stored one */
1190 std::string filename = service.path;
1191 filename.erase(filename.length()-2, 2);
1193 ePtr<eServiceEvent> event = new eServiceEvent;
1194 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1196 ePtr<eServiceEvent> empty;
1197 m_event_handler.inject(event, 0);
1198 m_event_handler.inject(empty, 1);
1205 m_event(this, evStart);
1210 RESULT eDVBServicePlay::stop()
1212 /* add bookmark for last play position */
1215 pts_t play_position, length;
1216 if (!getPlayPosition(play_position))
1218 /* remove last position */
1219 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1221 if (i->what == 3) /* current play position */
1223 m_cue_entries.erase(i);
1224 i = m_cue_entries.begin();
1230 if (getLength(length))
1235 int perc = play_position * 100LL / length;
1237 /* only store last play position when between 1% and 99% */
1238 if ((1 < perc) && (perc < 99))
1239 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1241 m_cuesheet_changed = 1;
1245 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1247 m_service_handler_timeshift.free();
1248 m_service_handler.free();
1250 if (m_is_pvr && m_cuesheet_changed)
1253 /* save cuesheet only when main file is accessible. */
1254 if (!::stat(m_reference.path.c_str(), &s))
1257 m_event((iPlayableService*)this, evStopped);
1261 RESULT eDVBServicePlay::setTarget(int target)
1263 m_is_primary = !target;
1267 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1269 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1273 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1275 /* note: we check for timeshift to be enabled,
1276 not neccessary active. if you pause when timeshift
1277 is not active, you should activate it when unpausing */
1278 if ((!m_is_pvr) && (!m_timeshift_enabled))
1288 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1291 return m_decoder->setSlowMotion(ratio);
1296 RESULT eDVBServicePlay::setFastForward(int ratio)
1298 int skipmode, ffratio;
1304 } else if (ratio > 0)
1312 } else // if (ratio < 0)
1318 if (m_skipmode != skipmode)
1320 eDebug("setting cue skipmode to %d", skipmode);
1322 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1325 m_skipmode = skipmode;
1330 return m_decoder->setFastForward(ffratio);
1333 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1335 if (m_is_pvr || m_timeshift_enabled)
1345 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1346 RESULT eDVBServicePlay::getLength(pts_t &len)
1348 ePtr<iDVBPVRChannel> pvr_channel;
1350 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1353 return pvr_channel->getLength(len);
1356 RESULT eDVBServicePlay::pause()
1358 if (!m_is_paused && m_decoder)
1361 return m_decoder->freeze(0);
1366 RESULT eDVBServicePlay::unpause()
1368 if (m_is_paused && m_decoder)
1371 return m_decoder->unfreeze();
1376 RESULT eDVBServicePlay::seekTo(pts_t to)
1378 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1380 if (!m_decode_demux)
1383 ePtr<iDVBPVRChannel> pvr_channel;
1385 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1391 m_cue->seekTo(0, to);
1392 m_dvb_subtitle_pages.clear();
1393 m_subtitle_pages.clear();
1398 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1400 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1402 if (!m_decode_demux)
1405 ePtr<iDVBPVRChannel> pvr_channel;
1407 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1412 /* HACK until we have skip-AP api */
1413 if ((to > 0) && (to < 100))
1421 m_cue->seekTo(mode, to);
1422 m_dvb_subtitle_pages.clear();
1423 m_subtitle_pages.clear();
1427 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1429 ePtr<iDVBPVRChannel> pvr_channel;
1431 if (!m_decode_demux)
1434 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1439 /* if there is a decoder, use audio or video PTS */
1442 r = m_decoder->getPTS(0, pos);
1448 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1451 RESULT eDVBServicePlay::setTrickmode(int trick)
1454 m_decoder->setTrickmode(trick);
1458 RESULT eDVBServicePlay::isCurrentlySeekable()
1460 return m_is_pvr || m_timeshift_active;
1463 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1469 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1475 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1481 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1487 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1493 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1496 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1497 (m_timeshift_enabled || !m_is_pvr))
1499 if (!m_timeshift_enabled)
1501 /* we need enough diskspace */
1503 if (statfs(TSPATH "/.", &fs) < 0)
1505 eDebug("statfs failed!");
1509 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1511 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1521 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1532 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1538 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1544 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1550 RESULT eDVBServicePlay::getName(std::string &name)
1554 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1555 return i->getName(m_reference, name);
1559 m_dvb_service->getName(m_reference, name);
1563 else if (!m_reference.name.empty())
1564 eStaticServiceDVBInformation().getName(m_reference, name);
1566 name = "DVB service";
1570 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1572 return m_event_handler.getEvent(evt, nownext);
1575 int eDVBServicePlay::getInfo(int w)
1577 eDVBServicePMTHandler::program program;
1580 return resIsPyObject;
1582 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1584 int no_program_info = 0;
1586 if (h.getProgramInfo(program))
1587 no_program_info = 1;
1591 #if HAVE_DVB_API_VERSION >= 3
1593 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1594 return m_videoEventData.height;
1597 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1598 return m_videoEventData.width;
1601 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1604 #if HAVE_DVB_API_VERSION >= 3
1605 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1606 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1609 #warning "FIXMEE implement sAspect for old DVB API"
1611 if (no_program_info)
1613 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1615 ePtr<eServiceEvent> evt;
1616 if (!m_event_handler.getEvent(evt, 0))
1618 ePtr<eComponentData> data;
1619 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1621 if ( data->getStreamContent() == 1 )
1623 switch(data->getComponentType())
1626 case 1: // 4:3 SD PAL
1628 case 3: // 16:9 SD PAL
1629 case 4: // > 16:9 PAL
1630 case 5: // 4:3 SD NTSC
1632 case 7: // 16:9 SD NTSC
1633 case 8: // > 16:9 NTSC
1636 case 9: // 4:3 HD PAL
1638 case 0xB: // 16:9 HD PAL
1639 case 0xC: // > 16:9 HD PAL
1640 case 0xD: // 4:3 HD NTSC
1642 case 0xF: // 16:9 HD NTSC
1643 case 0x10: // > 16:9 HD PAL
1644 return data->getComponentType();
1651 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1652 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1653 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1654 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1655 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1656 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1657 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1658 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1659 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1660 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1661 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1662 case sProvider: if (!m_dvb_service) return -1; return -2;
1663 case sServiceref: return resIsString;
1664 case sDVBState: return m_tune_state;
1670 std::string eDVBServicePlay::getInfoString(int w)
1675 if (!m_dvb_service) return "";
1676 return m_dvb_service->m_provider_name;
1678 return m_reference.toString();
1682 return iServiceInformation::getInfoString(w);
1685 PyObject *eDVBServicePlay::getInfoObject(int w)
1690 return m_service_handler.getCaIds();
1691 case sTransponderData:
1692 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1696 return iServiceInformation::getInfoObject(w);
1699 int eDVBServicePlay::getNumberOfTracks()
1701 eDVBServicePMTHandler::program program;
1702 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1703 if (h.getProgramInfo(program))
1705 return program.audioStreams.size();
1708 int eDVBServicePlay::getCurrentTrack()
1710 eDVBServicePMTHandler::program program;
1711 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1712 if (h.getProgramInfo(program))
1715 int max = program.audioStreams.size();
1718 for (i = 0; i < max; ++i)
1719 if (program.audioStreams[i].pid == m_current_audio_pid)
1725 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1727 int ret = selectAudioStream(i);
1729 if (m_decoder->start())
1735 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1737 eDVBServicePMTHandler::program program;
1738 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1740 if (h.getProgramInfo(program))
1743 if (i >= program.audioStreams.size())
1746 info.m_pid = program.audioStreams[i].pid;
1748 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1749 info.m_description = "MPEG";
1750 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1751 info.m_description = "AC3";
1752 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1753 info.m_description = "AAC";
1754 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1755 info.m_description = "DTS";
1757 info.m_description = "???";
1759 if (program.audioStreams[i].component_tag != -1)
1761 ePtr<eServiceEvent> evt;
1762 if (!m_event_handler.getEvent(evt, 0))
1764 ePtr<eComponentData> data;
1765 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1766 info.m_language = data->getText();
1770 if (info.m_language.empty())
1771 info.m_language = program.audioStreams[i].language_code;
1776 int eDVBServicePlay::selectAudioStream(int i)
1778 eDVBServicePMTHandler::program program;
1779 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1781 if (h.getProgramInfo(program))
1784 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1792 stream = program.defaultAudioStream;
1794 int apid = -1, apidtype = -1;
1796 if (((unsigned int)stream) < program.audioStreams.size())
1798 apid = program.audioStreams[stream].pid;
1799 apidtype = program.audioStreams[stream].type;
1802 m_current_audio_pid = apid;
1804 if (m_decoder->setAudioPID(apid, apidtype))
1806 eDebug("set audio pid failed");
1810 /* 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 */
1811 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1814 ePtr<iDVBDemux> data_demux;
1815 if (!h.getDataDemux(data_demux))
1817 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1818 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1822 /* if we decided that we need one, update the pid */
1824 m_rds_decoder->start(apid);
1826 /* store new pid as default only when:
1827 a.) we have an entry in the service db for the current service,
1828 b.) we are not playing back something,
1829 c.) we are not selecting the default entry. (we wouldn't change
1830 anything in the best case, or destroy the default setting in
1831 case the real default is not yet available.)
1833 if (m_dvb_service && !m_is_pvr && ((i != -1)
1834 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1836 if (apidtype == eDVBAudio::aMPEG)
1838 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1839 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1843 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1844 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1848 h.resetCachedProgram();
1853 int eDVBServicePlay::getCurrentChannel()
1855 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1858 RESULT eDVBServicePlay::selectChannel(int i)
1860 if (i < LEFT || i > RIGHT || i == STEREO)
1863 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1865 m_decoder->setAudioChannel(i);
1869 std::string eDVBServicePlay::getText(int x)
1875 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1877 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1882 void eDVBServicePlay::rdsDecoderEvent(int what)
1886 case eDVBRdsDecoder::RadioTextChanged:
1887 m_event((iPlayableService*)this, evUpdatedRadioText);
1889 case eDVBRdsDecoder::RtpTextChanged:
1890 m_event((iPlayableService*)this, evUpdatedRtpText);
1892 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1893 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1895 case eDVBRdsDecoder::RecvRassSlidePic:
1896 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1901 void eDVBServicePlay::showRassSlidePicture()
1907 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1908 if (rass_slide_pic.length())
1909 m_decoder->showSinglePic(rass_slide_pic.c_str());
1911 eDebug("empty filename for rass slide picture received!!");
1914 eDebug("no MPEG Decoder to show iframes avail");
1917 eDebug("showRassSlidePicture called.. but not decoder");
1920 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1926 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1927 if (rass_interactive_pic.length())
1928 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1930 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1933 eDebug("no MPEG Decoder to show iframes avail");
1936 eDebug("showRassInteractivePic called.. but not decoder");
1939 ePyObject eDVBServicePlay::getRassInteractiveMask()
1942 return m_rds_decoder->getRassPictureMask();
1946 int eDVBServiceBase::getFrontendInfo(int w)
1948 eUsePtr<iDVBChannel> channel;
1949 if(m_service_handler.getChannel(channel))
1951 ePtr<iDVBFrontend> fe;
1952 if(channel->getFrontend(fe))
1954 return fe->readFrontendData(w);
1957 PyObject *eDVBServiceBase::getFrontendData()
1959 ePyObject ret = PyDict_New();
1962 eUsePtr<iDVBChannel> channel;
1963 if(!m_service_handler.getChannel(channel))
1965 ePtr<iDVBFrontend> fe;
1966 if(!channel->getFrontend(fe))
1967 fe->getFrontendData(ret);
1975 PyObject *eDVBServiceBase::getFrontendStatus()
1977 ePyObject ret = PyDict_New();
1980 eUsePtr<iDVBChannel> channel;
1981 if(!m_service_handler.getChannel(channel))
1983 ePtr<iDVBFrontend> fe;
1984 if(!channel->getFrontend(fe))
1985 fe->getFrontendStatus(ret);
1993 PyObject *eDVBServiceBase::getTransponderData(bool original)
1995 ePyObject ret = PyDict_New();
1998 eUsePtr<iDVBChannel> channel;
1999 if(!m_service_handler.getChannel(channel))
2001 ePtr<iDVBFrontend> fe;
2002 if(!channel->getFrontend(fe))
2004 fe->getTransponderData(ret, original);
2005 ePtr<iDVBFrontendParameters> feparm;
2006 channel->getCurrentFrontendParameters(feparm);
2009 eDVBFrontendParametersSatellite osat;
2010 if (!feparm->getDVBS(osat))
2012 void PutToDict(ePyObject &, const char*, long);
2013 void PutToDict(ePyObject &, const char*, const char*);
2014 PutToDict(ret, "orbital_position", osat.orbital_position);
2015 const char *tmp = "UNKNOWN";
2016 switch(osat.polarisation)
2018 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2019 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2020 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2021 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2024 PutToDict(ret, "polarization", tmp);
2035 PyObject *eDVBServiceBase::getAll(bool original)
2037 ePyObject ret = getTransponderData(original);
2040 eUsePtr<iDVBChannel> channel;
2041 if(!m_service_handler.getChannel(channel))
2043 ePtr<iDVBFrontend> fe;
2044 if(!channel->getFrontend(fe))
2046 fe->getFrontendData(ret);
2047 fe->getFrontendStatus(ret);
2054 int eDVBServicePlay::getNumberOfSubservices()
2056 ePtr<eServiceEvent> evt;
2057 if (!m_event_handler.getEvent(evt, 0))
2058 return evt->getNumOfLinkageServices();
2062 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2064 ePtr<eServiceEvent> evt;
2065 if (!m_event_handler.getEvent(evt, 0))
2067 if (!evt->getLinkageService(sub, m_reference, n))
2070 sub.type=eServiceReference::idInvalid;
2074 RESULT eDVBServicePlay::startTimeshift()
2076 ePtr<iDVBDemux> demux;
2078 eDebug("Start timeshift!");
2080 if (m_timeshift_enabled)
2083 /* start recording with the data demux. */
2084 if (m_service_handler.getDataDemux(demux))
2087 demux->createTSRecorder(m_record);
2091 char templ[]=TSPATH "/timeshift.XXXXXX";
2092 m_timeshift_fd = mkstemp(templ);
2093 m_timeshift_file = templ;
2095 eDebug("recording to %s", templ);
2097 if (m_timeshift_fd < 0)
2103 m_record->setTargetFD(m_timeshift_fd);
2105 m_timeshift_enabled = 1;
2107 updateTimeshiftPids();
2113 RESULT eDVBServicePlay::stopTimeshift()
2115 if (!m_timeshift_enabled)
2120 m_timeshift_enabled = 0;
2125 close(m_timeshift_fd);
2126 eDebug("remove timeshift file");
2127 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2132 int eDVBServicePlay::isTimeshiftActive()
2134 return m_timeshift_enabled && m_timeshift_active;
2137 RESULT eDVBServicePlay::activateTimeshift()
2139 if (!m_timeshift_enabled)
2142 if (!m_timeshift_active)
2144 switchToTimeshift();
2151 PyObject *eDVBServicePlay::getCutList()
2153 ePyObject list = PyList_New(0);
2155 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2157 ePyObject tuple = PyTuple_New(2);
2158 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2159 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2160 PyList_Append(list, tuple);
2167 void eDVBServicePlay::setCutList(ePyObject list)
2169 if (!PyList_Check(list))
2171 int size = PyList_Size(list);
2174 m_cue_entries.clear();
2176 for (i=0; i<size; ++i)
2178 ePyObject tuple = PyList_GET_ITEM(list, i);
2179 if (!PyTuple_Check(tuple))
2181 eDebug("non-tuple in cutlist");
2184 if (PyTuple_Size(tuple) != 2)
2186 eDebug("cutlist entries need to be a 2-tuple");
2189 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2190 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2192 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2195 pts_t pts = PyLong_AsLongLong(ppts);
2196 int type = PyInt_AsLong(ptype);
2197 m_cue_entries.insert(cueEntry(pts, type));
2198 eDebug("adding %08llx, %d", pts, type);
2200 m_cuesheet_changed = 1;
2202 cutlistToCuesheet();
2203 m_event((iPlayableService*)this, evCuesheetChanged);
2206 void eDVBServicePlay::setCutListEnable(int enable)
2208 m_cutlist_enabled = enable;
2209 cutlistToCuesheet();
2212 void eDVBServicePlay::updateTimeshiftPids()
2217 eDVBServicePMTHandler::program program;
2218 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2220 if (h.getProgramInfo(program))
2224 std::set<int> pids_to_record;
2225 pids_to_record.insert(0); // PAT
2226 if (program.pmtPid != -1)
2227 pids_to_record.insert(program.pmtPid); // PMT
2229 if (program.textPid != -1)
2230 pids_to_record.insert(program.textPid); // Videotext
2232 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2233 i(program.videoStreams.begin());
2234 i != program.videoStreams.end(); ++i)
2235 pids_to_record.insert(i->pid);
2237 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2238 i(program.audioStreams.begin());
2239 i != program.audioStreams.end(); ++i)
2240 pids_to_record.insert(i->pid);
2242 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2243 i(program.subtitleStreams.begin());
2244 i != program.subtitleStreams.end(); ++i)
2245 pids_to_record.insert(i->pid);
2247 std::set<int> new_pids, obsolete_pids;
2249 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2250 m_pids_active.begin(), m_pids_active.end(),
2251 std::inserter(new_pids, new_pids.begin()));
2253 std::set_difference(
2254 m_pids_active.begin(), m_pids_active.end(),
2255 pids_to_record.begin(), pids_to_record.end(),
2256 std::inserter(new_pids, new_pids.begin())
2259 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2260 m_record->addPID(*i);
2262 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2263 m_record->removePID(*i);
2267 void eDVBServicePlay::switchToLive()
2269 if (!m_timeshift_active)
2275 m_teletext_parser = 0;
2277 m_subtitle_parser = 0;
2278 m_new_dvb_subtitle_page_connection = 0;
2279 m_new_subtitle_page_connection = 0;
2280 m_rds_decoder_event_connection = 0;
2281 m_video_event_connection = 0;
2283 /* free the timeshift service handler, we need the resources */
2284 m_service_handler_timeshift.free();
2285 m_timeshift_active = 0;
2287 m_event((iPlayableService*)this, evSeekableStatusChanged);
2292 void eDVBServicePlay::switchToTimeshift()
2294 if (m_timeshift_active)
2299 m_teletext_parser = 0;
2301 m_subtitle_parser = 0;
2302 m_new_subtitle_page_connection = 0;
2303 m_new_dvb_subtitle_page_connection = 0;
2304 m_rds_decoder_event_connection = 0;
2305 m_video_event_connection = 0;
2307 m_timeshift_active = 1;
2309 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2310 r.path = m_timeshift_file;
2312 m_cue = new eCueSheet();
2313 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2315 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2317 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2319 m_event((iPlayableService*)this, evSeekableStatusChanged);
2322 void eDVBServicePlay::updateDecoder()
2324 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2326 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2328 eDVBServicePMTHandler::program program;
2329 if (h.getProgramInfo(program))
2330 eDebug("getting program info failed.");
2333 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2334 if (!program.videoStreams.empty())
2336 eDebugNoNewLine(" (");
2337 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2338 i(program.videoStreams.begin());
2339 i != program.videoStreams.end(); ++i)
2346 if (i != program.videoStreams.begin())
2347 eDebugNoNewLine(", ");
2348 eDebugNoNewLine("%04x", i->pid);
2350 eDebugNoNewLine(")");
2352 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2353 if (!program.audioStreams.empty())
2355 eDebugNoNewLine(" (");
2356 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2357 i(program.audioStreams.begin());
2358 i != program.audioStreams.end(); ++i)
2360 if (i != program.audioStreams.begin())
2361 eDebugNoNewLine(", ");
2362 eDebugNoNewLine("%04x", i->pid);
2364 eDebugNoNewLine(")");
2366 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2367 pcrpid = program.pcrPid;
2368 eDebug(", and the text pid is %04x", program.textPid);
2369 tpid = program.textPid;
2374 h.getDecodeDemux(m_decode_demux);
2377 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2379 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2380 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2381 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2382 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2383 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2386 m_teletext_parser = 0;
2387 m_subtitle_parser = 0;
2391 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2398 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2399 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2400 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2402 else // subservice or recording
2404 eServiceReferenceDVB ref;
2405 m_service_handler.getServiceReference(ref);
2406 eServiceReferenceDVB parent = ref.getParentServiceReference();
2411 ePtr<eDVBResourceManager> res_mgr;
2412 if (!eDVBResourceManager::getInstance(res_mgr))
2414 ePtr<iDVBChannelList> db;
2415 if (!res_mgr->getChannelList(db))
2417 ePtr<eDVBService> origService;
2418 if (!db->getService(parent, origService))
2420 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2421 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2427 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2428 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2430 m_decoder->setVideoPID(vpid, vpidtype);
2431 selectAudioStream();
2433 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2434 m_decoder->setSyncPCR(pcrpid);
2436 m_decoder->setSyncPCR(-1);
2438 m_decoder->setTextPID(tpid);
2440 m_teletext_parser->start(program.textPid);
2443 m_decoder->setTrickmode(1);
2446 m_decoder->preroll();
2450 if (vpid > 0 && vpid < 0x2000)
2454 std::string radio_pic;
2455 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2456 m_decoder->setRadioPic(radio_pic);
2459 m_decoder->setAudioChannel(achannel);
2461 /* don't worry about non-existing services, nor pvr services */
2462 if (m_dvb_service && !m_is_pvr)
2464 /* (audio pid will be set in selectAudioTrack */
2465 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2466 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2467 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2468 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2471 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2474 void eDVBServicePlay::loadCuesheet()
2476 std::string filename = m_reference.path + ".cuts";
2478 m_cue_entries.clear();
2480 FILE *f = fopen(filename.c_str(), "rb");
2484 eDebug("loading cuts..");
2487 unsigned long long where;
2490 if (!fread(&where, sizeof(where), 1, f))
2492 if (!fread(&what, sizeof(what), 1, f))
2495 #if BYTE_ORDER == LITTLE_ENDIAN
2496 where = bswap_64(where);
2503 m_cue_entries.insert(cueEntry(where, what));
2506 eDebug("%d entries", m_cue_entries.size());
2508 eDebug("cutfile not found!");
2510 m_cuesheet_changed = 0;
2511 cutlistToCuesheet();
2512 m_event((iPlayableService*)this, evCuesheetChanged);
2515 void eDVBServicePlay::saveCuesheet()
2517 std::string filename = m_reference.path + ".cuts";
2519 FILE *f = fopen(filename.c_str(), "wb");
2523 unsigned long long where;
2526 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2528 #if BYTE_ORDER == BIG_ENDIAN
2531 where = bswap_64(i->where);
2533 what = htonl(i->what);
2534 fwrite(&where, sizeof(where), 1, f);
2535 fwrite(&what, sizeof(what), 1, f);
2541 m_cuesheet_changed = 0;
2544 void eDVBServicePlay::cutlistToCuesheet()
2548 eDebug("no cue sheet");
2553 if (!m_cutlist_enabled)
2555 m_cue->commitSpans();
2556 eDebug("cutlists were disabled");
2560 pts_t in = 0, out = 0, length = 0;
2564 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2568 if (i == m_cue_entries.end())
2571 if (i->what == 0) /* in */
2575 } else if (i->what == 1) /* out */
2577 else /* mark (2) or last play position (3) */
2594 m_cue->addSourceSpan(in, out);
2598 if (i == m_cue_entries.end())
2601 m_cue->commitSpans();
2604 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2606 if (m_subtitle_widget)
2607 disableSubtitles(parent);
2610 int tuplesize = PyTuple_Size(tuple);
2613 if (!PyTuple_Check(tuple))
2619 entry = PyTuple_GET_ITEM(tuple, 0);
2621 if (!PyInt_Check(entry))
2624 type = PyInt_AsLong(entry);
2626 if (type == 1) // teletext subtitles
2628 int page, magazine, pid;
2632 if (!m_teletext_parser)
2634 eDebug("enable teletext subtitles.. no parser !!!");
2638 entry = PyTuple_GET_ITEM(tuple, 1);
2639 if (!PyInt_Check(entry))
2641 pid = PyInt_AsLong(entry);
2643 entry = PyTuple_GET_ITEM(tuple, 2);
2644 if (!PyInt_Check(entry))
2646 page = PyInt_AsLong(entry);
2648 entry = PyTuple_GET_ITEM(tuple, 3);
2649 if (!PyInt_Check(entry))
2651 magazine = PyInt_AsLong(entry);
2653 m_subtitle_widget = new eSubtitleWidget(parent);
2654 m_subtitle_widget->resize(parent->size()); /* full size */
2655 m_teletext_parser->setPageAndMagazine(page, magazine);
2657 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2661 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2662 if (!m_subtitle_parser)
2664 eDebug("enable dvb subtitles.. no parser !!!");
2670 entry = PyTuple_GET_ITEM(tuple, 1);
2671 if (!PyInt_Check(entry))
2673 pid = PyInt_AsLong(entry);
2675 entry = PyTuple_GET_ITEM(tuple, 2);
2676 if (!PyInt_Check(entry))
2678 composition_page_id = PyInt_AsLong(entry);
2680 entry = PyTuple_GET_ITEM(tuple, 3);
2681 if (!PyInt_Check(entry))
2683 ancillary_page_id = PyInt_AsLong(entry);
2685 m_subtitle_widget = new eSubtitleWidget(parent);
2686 m_subtitle_widget->resize(parent->size()); /* full size */
2687 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2689 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2695 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2696 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2697 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2701 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2703 delete m_subtitle_widget;
2704 m_subtitle_widget = 0;
2705 if (m_subtitle_parser)
2707 m_subtitle_parser->stop();
2708 m_dvb_subtitle_pages.clear();
2710 if (m_teletext_parser)
2712 m_teletext_parser->setPageAndMagazine(-1, -1);
2713 m_subtitle_pages.clear();
2716 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2720 PyObject *eDVBServicePlay::getCachedSubtitle()
2724 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2727 unsigned int data = (unsigned int)tmp;
2728 int pid = (data&0xFFFF0000)>>16;
2729 ePyObject tuple = PyTuple_New(4);
2730 eDVBServicePMTHandler::program program;
2731 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2732 if (!h.getProgramInfo(program))
2734 if (program.textPid==pid) // teletext
2735 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2737 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2738 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2739 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2740 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2748 PyObject *eDVBServicePlay::getSubtitleList()
2750 if (!m_teletext_parser)
2753 ePyObject l = PyList_New(0);
2754 std::set<int> added_ttx_pages;
2756 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2757 m_teletext_parser->m_found_subtitle_pages;
2759 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2760 eDVBServicePMTHandler::program program;
2761 if (h.getProgramInfo(program))
2762 eDebug("getting program info failed.");
2765 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2766 it != program.subtitleStreams.end(); ++it)
2768 switch(it->subtitling_type)
2770 case 0x01: // ebu teletext subtitles
2772 int page_number = it->teletext_page_number & 0xFF;
2773 int magazine_number = it->teletext_magazine_number & 7;
2774 int hash = magazine_number << 8 | page_number;
2775 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2777 ePyObject tuple = PyTuple_New(5);
2778 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2779 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2780 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2781 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2782 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2783 PyList_Append(l, tuple);
2785 added_ttx_pages.insert(hash);
2790 case 0x20 ... 0x23: // dvb subtitles
2792 ePyObject tuple = PyTuple_New(5);
2793 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2794 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2795 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2796 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2797 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2798 PyList_Insert(l, 0, tuple);
2806 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2807 it != subs.end(); ++it)
2809 int page_number = it->teletext_page_number & 0xFF;
2810 int magazine_number = it->teletext_magazine_number & 7;
2811 int hash = magazine_number << 8 | page_number;
2812 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2814 ePyObject tuple = PyTuple_New(5);
2815 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2816 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2817 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2818 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2819 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2820 PyList_Append(l, tuple);
2828 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2830 if (m_subtitle_widget)
2834 m_decoder->getPTS(0, pos);
2835 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2836 m_subtitle_pages.push_back(page);
2837 checkSubtitleTiming();
2841 void eDVBServicePlay::checkSubtitleTiming()
2843 eDebug("checkSubtitleTiming");
2844 if (!m_subtitle_widget)
2848 enum { TELETEXT, DVB } type;
2849 eDVBTeletextSubtitlePage page;
2850 eDVBSubtitlePage dvb_page;
2852 if (!m_subtitle_pages.empty())
2854 page = m_subtitle_pages.front();
2856 show_time = page.m_pts;
2858 else if (!m_dvb_subtitle_pages.empty())
2860 dvb_page = m_dvb_subtitle_pages.front();
2862 show_time = dvb_page.m_show_time;
2870 m_decoder->getPTS(0, pos);
2872 eDebug("%lld %lld", pos, show_time);
2873 int diff = show_time - pos;
2876 eDebug("[late (%d ms)]", -diff / 90);
2879 // if (diff > 900000)
2881 // eDebug("[invalid]");
2887 if (type == TELETEXT)
2889 eDebug("display teletext subtitle page %lld", show_time);
2890 m_subtitle_widget->setPage(page);
2891 m_subtitle_pages.pop_front();
2895 eDebug("display dvb subtitle Page %lld", show_time);
2896 m_subtitle_widget->setPage(dvb_page);
2897 m_dvb_subtitle_pages.pop_front();
2901 eDebug("start subtitle delay %d", diff / 90);
2902 m_subtitle_sync_timer.start(diff / 90, 1);
2908 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2910 if (m_subtitle_widget)
2914 m_decoder->getPTS(0, pos);
2915 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2916 m_dvb_subtitle_pages.push_back(p);
2917 checkSubtitleTiming();
2921 int eDVBServicePlay::getAC3Delay()
2924 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2926 return m_decoder->getAC3Delay();
2931 int eDVBServicePlay::getPCMDelay()
2934 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2936 return m_decoder->getPCMDelay();
2941 void eDVBServicePlay::setAC3Delay(int delay)
2944 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2946 m_decoder->setAC3Delay(delay);
2949 void eDVBServicePlay::setPCMDelay(int delay)
2952 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2954 m_decoder->setPCMDelay(delay);
2957 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2959 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2960 m_event((iPlayableService*)this, evVideoSizeChanged);
2963 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2969 PyObject *eDVBServicePlay::getStreamingData()
2971 eDVBServicePMTHandler::program program;
2972 if (m_service_handler.getProgramInfo(program))
2978 PyObject *r = program.createPythonObject();
2979 ePtr<iDVBDemux> demux;
2980 if (!m_service_handler.getDataDemux(demux))
2983 demux->getCADemuxID(demux_id);
2985 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
2992 DEFINE_REF(eDVBServicePlay)
2994 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2998 case iServiceInformation::sTransponderData:
2999 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3003 return iStaticServiceInformation::getInfoObject(ref, w);
3006 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");