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 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
944 ePtr<eDVBService> service;
945 int r = lookupService(service, ref);
948 // check resources...
949 ptr = new eDVBServicePlay(ref, service);
953 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
955 if (ref.path.empty())
957 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
966 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
968 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
969 if (list->startQuery())
979 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
981 /* is a listable service? */
982 if (ref.flags & eServiceReference::canDescent) // bouquet
984 if ( !ref.name.empty() ) // satellites or providers list
985 ptr = m_StaticServiceDVBInfo;
986 else // a dvb bouquet
987 ptr = m_StaticServiceDVBBouquetInfo;
989 else if (!ref.path.empty()) /* do we have a PVR service? */
990 ptr = new eStaticServiceDVBPVRInformation(ref);
991 else // normal dvb service
993 ePtr<eDVBService> service;
994 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
995 ptr = m_StaticServiceDVBInfo;
997 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
1003 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
1005 if (ref.path.empty())
1011 ptr = new eDVBPVRServiceOfflineOperations(ref);
1016 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
1018 // TODO: handle the listing itself
1019 // if (ref.... == -1) .. return "... bouquets ...";
1020 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
1022 ePtr<iDVBChannelList> db;
1023 ePtr<eDVBResourceManager> res;
1026 if ((err = eDVBResourceManager::getInstance(res)) != 0)
1028 eDebug("no resource manager");
1031 if ((err = res->getChannelList(db)) != 0)
1033 eDebug("no channel list");
1037 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
1038 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
1040 eDebug("getService failed!");
1047 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
1048 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
1050 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
1052 m_is_pvr = !m_reference.path.empty();
1054 m_timeshift_enabled = m_timeshift_active = 0;
1057 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
1058 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
1059 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
1061 m_cuesheet_changed = 0;
1062 m_cutlist_enabled = 1;
1064 m_subtitle_widget = 0;
1068 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
1071 eDVBServicePlay::~eDVBServicePlay()
1073 delete m_subtitle_widget;
1076 void eDVBServicePlay::gotNewEvent()
1080 ePtr<eServiceEvent> m_event_now, m_event_next;
1081 getEvent(m_event_now, 0);
1082 getEvent(m_event_next, 1);
1085 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1087 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1089 m_event((iPlayableService*)this, evUpdatedEventInfo);
1092 void eDVBServicePlay::serviceEvent(int event)
1094 m_tune_state = event;
1098 case eDVBServicePMTHandler::eventTuned:
1100 ePtr<iDVBDemux> m_demux;
1101 if (!m_service_handler.getDataDemux(m_demux))
1103 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1104 int sid = ref.getParentServiceID().get();
1106 sid = ref.getServiceID().get();
1107 if ( ref.getParentTransportStreamID().get() &&
1108 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1109 m_event_handler.startOther(m_demux, sid);
1111 m_event_handler.start(m_demux, sid);
1115 case eDVBServicePMTHandler::eventNoResources:
1116 case eDVBServicePMTHandler::eventNoPAT:
1117 case eDVBServicePMTHandler::eventNoPATEntry:
1118 case eDVBServicePMTHandler::eventNoPMT:
1119 case eDVBServicePMTHandler::eventTuneFailed:
1120 case eDVBServicePMTHandler::eventMisconfiguration:
1122 eDebug("DVB service failed to tune - error %d", event);
1123 m_event((iPlayableService*)this, evTuneFailed);
1126 case eDVBServicePMTHandler::eventNewProgramInfo:
1128 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1129 if (m_timeshift_enabled)
1130 updateTimeshiftPids();
1131 if (!m_timeshift_active)
1133 if (m_first_program_info && m_is_pvr)
1135 m_first_program_info = 0;
1138 m_event((iPlayableService*)this, evUpdatedInfo);
1141 case eDVBServicePMTHandler::eventEOF:
1142 m_event((iPlayableService*)this, evEOF);
1144 case eDVBServicePMTHandler::eventSOF:
1145 m_event((iPlayableService*)this, evSOF);
1150 void eDVBServicePlay::serviceEventTimeshift(int event)
1154 case eDVBServicePMTHandler::eventNewProgramInfo:
1155 if (m_timeshift_active)
1158 case eDVBServicePMTHandler::eventSOF:
1159 m_event((iPlayableService*)this, evSOF);
1161 case eDVBServicePMTHandler::eventEOF:
1162 if ((!m_is_paused) && (m_skipmode >= 0))
1168 RESULT eDVBServicePlay::start()
1171 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1172 two (one for decoding, one for data source), as we must be prepared
1173 to start recording from the data demux. */
1175 m_cue = new eCueSheet();
1177 m_event(this, evStart);
1179 m_first_program_info = 1;
1180 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1181 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1183 /* inject EIT if there is a stored one */
1186 std::string filename = service.path;
1187 filename.erase(filename.length()-2, 2);
1189 ePtr<eServiceEvent> event = new eServiceEvent;
1190 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1192 ePtr<eServiceEvent> empty;
1193 m_event_handler.inject(event, 0);
1194 m_event_handler.inject(empty, 1);
1201 m_event(this, evStart);
1206 RESULT eDVBServicePlay::stop()
1208 /* add bookmark for last play position */
1211 pts_t play_position, length;
1212 if (!getPlayPosition(play_position))
1214 /* remove last position */
1215 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1217 if (i->what == 3) /* current play position */
1219 m_cue_entries.erase(i);
1220 i = m_cue_entries.begin();
1226 if (getLength(length))
1231 int perc = play_position * 100LL / length;
1233 /* only store last play position when between 1% and 99% */
1234 if ((1 < perc) && (perc < 99))
1235 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1237 m_cuesheet_changed = 1;
1241 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1243 m_service_handler_timeshift.free();
1244 m_service_handler.free();
1246 if (m_is_pvr && m_cuesheet_changed)
1249 /* save cuesheet only when main file is accessible. */
1250 if (!::stat(m_reference.path.c_str(), &s))
1253 m_event((iPlayableService*)this, evStopped);
1257 RESULT eDVBServicePlay::setTarget(int target)
1259 m_is_primary = !target;
1263 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1265 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1269 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1271 /* note: we check for timeshift to be enabled,
1272 not neccessary active. if you pause when timeshift
1273 is not active, you should activate it when unpausing */
1274 if ((!m_is_pvr) && (!m_timeshift_enabled))
1284 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1287 return m_decoder->setSlowMotion(ratio);
1292 RESULT eDVBServicePlay::setFastForward(int ratio)
1294 int skipmode, ffratio;
1300 } else if (ratio > 0)
1308 } else // if (ratio < 0)
1314 if (m_skipmode != skipmode)
1316 eDebug("setting cue skipmode to %d", skipmode);
1318 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1321 m_skipmode = skipmode;
1326 return m_decoder->setFastForward(ffratio);
1329 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1331 if (m_is_pvr || m_timeshift_enabled)
1341 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1342 RESULT eDVBServicePlay::getLength(pts_t &len)
1344 ePtr<iDVBPVRChannel> pvr_channel;
1346 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1349 return pvr_channel->getLength(len);
1352 RESULT eDVBServicePlay::pause()
1354 if (!m_is_paused && m_decoder)
1357 return m_decoder->freeze(0);
1362 RESULT eDVBServicePlay::unpause()
1364 if (m_is_paused && m_decoder)
1367 return m_decoder->unfreeze();
1372 RESULT eDVBServicePlay::seekTo(pts_t to)
1374 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1376 if (!m_decode_demux)
1379 ePtr<iDVBPVRChannel> pvr_channel;
1381 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1387 m_cue->seekTo(0, to);
1388 m_dvb_subtitle_pages.clear();
1389 m_subtitle_pages.clear();
1394 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1396 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1398 if (!m_decode_demux)
1401 ePtr<iDVBPVRChannel> pvr_channel;
1403 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1408 /* HACK until we have skip-AP api */
1409 if ((to > 0) && (to < 100))
1417 m_cue->seekTo(mode, to);
1418 m_dvb_subtitle_pages.clear();
1419 m_subtitle_pages.clear();
1423 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1425 ePtr<iDVBPVRChannel> pvr_channel;
1427 if (!m_decode_demux)
1430 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1435 /* if there is a decoder, use audio or video PTS */
1438 r = m_decoder->getPTS(0, pos);
1444 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1447 RESULT eDVBServicePlay::setTrickmode(int trick)
1450 m_decoder->setTrickmode(trick);
1454 RESULT eDVBServicePlay::isCurrentlySeekable()
1456 return m_is_pvr || m_timeshift_active;
1459 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1465 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1471 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1477 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1483 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1489 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1492 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1493 (m_timeshift_enabled || !m_is_pvr))
1495 if (!m_timeshift_enabled)
1497 /* we need enough diskspace */
1499 if (statfs(TSPATH "/.", &fs) < 0)
1501 eDebug("statfs failed!");
1505 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1507 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1517 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1528 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1534 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1540 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1546 RESULT eDVBServicePlay::getName(std::string &name)
1550 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1551 return i->getName(m_reference, name);
1555 m_dvb_service->getName(m_reference, name);
1559 else if (!m_reference.name.empty())
1560 eStaticServiceDVBInformation().getName(m_reference, name);
1562 name = "DVB service";
1566 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1568 return m_event_handler.getEvent(evt, nownext);
1571 int eDVBServicePlay::getInfo(int w)
1573 eDVBServicePMTHandler::program program;
1576 return resIsPyObject;
1578 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1580 int no_program_info = 0;
1582 if (h.getProgramInfo(program))
1583 no_program_info = 1;
1587 #if HAVE_DVB_API_VERSION >= 3
1589 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1590 return m_videoEventData.height;
1593 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1594 return m_videoEventData.width;
1597 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1600 #if HAVE_DVB_API_VERSION >= 3
1601 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1602 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1605 #warning "FIXMEE implement sAspect for old DVB API"
1607 if (no_program_info)
1609 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1611 ePtr<eServiceEvent> evt;
1612 if (!m_event_handler.getEvent(evt, 0))
1614 ePtr<eComponentData> data;
1615 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1617 if ( data->getStreamContent() == 1 )
1619 switch(data->getComponentType())
1622 case 1: // 4:3 SD PAL
1624 case 3: // 16:9 SD PAL
1625 case 4: // > 16:9 PAL
1626 case 5: // 4:3 SD NTSC
1628 case 7: // 16:9 SD NTSC
1629 case 8: // > 16:9 NTSC
1632 case 9: // 4:3 HD PAL
1634 case 0xB: // 16:9 HD PAL
1635 case 0xC: // > 16:9 HD PAL
1636 case 0xD: // 4:3 HD NTSC
1638 case 0xF: // 16:9 HD NTSC
1639 case 0x10: // > 16:9 HD PAL
1640 return data->getComponentType();
1647 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1648 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1649 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1650 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1651 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1652 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1653 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1654 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1655 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1656 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1657 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1658 case sProvider: if (!m_dvb_service) return -1; return -2;
1659 case sServiceref: return resIsString;
1660 case sDVBState: return m_tune_state;
1666 std::string eDVBServicePlay::getInfoString(int w)
1671 if (!m_dvb_service) return "";
1672 return m_dvb_service->m_provider_name;
1674 return m_reference.toString();
1678 return iServiceInformation::getInfoString(w);
1681 PyObject *eDVBServicePlay::getInfoObject(int w)
1686 return m_service_handler.getCaIds();
1687 case sTransponderData:
1688 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1692 return iServiceInformation::getInfoObject(w);
1695 int eDVBServicePlay::getNumberOfTracks()
1697 eDVBServicePMTHandler::program program;
1698 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1699 if (h.getProgramInfo(program))
1701 return program.audioStreams.size();
1704 int eDVBServicePlay::getCurrentTrack()
1706 eDVBServicePMTHandler::program program;
1707 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1708 if (h.getProgramInfo(program))
1711 int max = program.audioStreams.size();
1714 for (i = 0; i < max; ++i)
1715 if (program.audioStreams[i].pid == m_current_audio_pid)
1721 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1723 int ret = selectAudioStream(i);
1725 if (m_decoder->start())
1731 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1733 eDVBServicePMTHandler::program program;
1734 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1736 if (h.getProgramInfo(program))
1739 if (i >= program.audioStreams.size())
1742 info.m_pid = program.audioStreams[i].pid;
1744 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1745 info.m_description = "MPEG";
1746 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1747 info.m_description = "AC3";
1748 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1749 info.m_description = "AAC";
1750 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1751 info.m_description = "DTS";
1753 info.m_description = "???";
1755 if (program.audioStreams[i].component_tag != -1)
1757 ePtr<eServiceEvent> evt;
1758 if (!m_event_handler.getEvent(evt, 0))
1760 ePtr<eComponentData> data;
1761 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1762 info.m_language = data->getText();
1766 if (info.m_language.empty())
1767 info.m_language = program.audioStreams[i].language_code;
1772 int eDVBServicePlay::selectAudioStream(int i)
1774 eDVBServicePMTHandler::program program;
1775 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1777 if (h.getProgramInfo(program))
1780 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1788 stream = program.defaultAudioStream;
1790 int apid = -1, apidtype = -1;
1792 if (((unsigned int)stream) < program.audioStreams.size())
1794 apid = program.audioStreams[stream].pid;
1795 apidtype = program.audioStreams[stream].type;
1798 m_current_audio_pid = apid;
1800 if (m_decoder->setAudioPID(apid, apidtype))
1802 eDebug("set audio pid failed");
1806 /* 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 */
1807 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1810 ePtr<iDVBDemux> data_demux;
1811 if (!h.getDataDemux(data_demux))
1813 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1814 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1818 /* if we decided that we need one, update the pid */
1820 m_rds_decoder->start(apid);
1822 /* store new pid as default only when:
1823 a.) we have an entry in the service db for the current service,
1824 b.) we are not playing back something,
1825 c.) we are not selecting the default entry. (we wouldn't change
1826 anything in the best case, or destroy the default setting in
1827 case the real default is not yet available.)
1829 if (m_dvb_service && !m_is_pvr && ((i != -1)
1830 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1832 if (apidtype == eDVBAudio::aMPEG)
1834 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1835 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1839 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1840 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1844 h.resetCachedProgram();
1849 int eDVBServicePlay::getCurrentChannel()
1851 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1854 RESULT eDVBServicePlay::selectChannel(int i)
1856 if (i < LEFT || i > RIGHT || i == STEREO)
1859 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1861 m_decoder->setAudioChannel(i);
1865 std::string eDVBServicePlay::getText(int x)
1871 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1873 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1878 void eDVBServicePlay::rdsDecoderEvent(int what)
1882 case eDVBRdsDecoder::RadioTextChanged:
1883 m_event((iPlayableService*)this, evUpdatedRadioText);
1885 case eDVBRdsDecoder::RtpTextChanged:
1886 m_event((iPlayableService*)this, evUpdatedRtpText);
1888 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1889 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1891 case eDVBRdsDecoder::RecvRassSlidePic:
1892 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1897 void eDVBServicePlay::showRassSlidePicture()
1903 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1904 if (rass_slide_pic.length())
1905 m_decoder->showSinglePic(rass_slide_pic.c_str());
1907 eDebug("empty filename for rass slide picture received!!");
1910 eDebug("no MPEG Decoder to show iframes avail");
1913 eDebug("showRassSlidePicture called.. but not decoder");
1916 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1922 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1923 if (rass_interactive_pic.length())
1924 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1926 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1929 eDebug("no MPEG Decoder to show iframes avail");
1932 eDebug("showRassInteractivePic called.. but not decoder");
1935 ePyObject eDVBServicePlay::getRassInteractiveMask()
1938 return m_rds_decoder->getRassPictureMask();
1942 int eDVBServiceBase::getFrontendInfo(int w)
1944 eUsePtr<iDVBChannel> channel;
1945 if(m_service_handler.getChannel(channel))
1947 ePtr<iDVBFrontend> fe;
1948 if(channel->getFrontend(fe))
1950 return fe->readFrontendData(w);
1953 PyObject *eDVBServiceBase::getFrontendData()
1955 ePyObject ret = PyDict_New();
1958 eUsePtr<iDVBChannel> channel;
1959 if(!m_service_handler.getChannel(channel))
1961 ePtr<iDVBFrontend> fe;
1962 if(!channel->getFrontend(fe))
1963 fe->getFrontendData(ret);
1971 PyObject *eDVBServiceBase::getFrontendStatus()
1973 ePyObject ret = PyDict_New();
1976 eUsePtr<iDVBChannel> channel;
1977 if(!m_service_handler.getChannel(channel))
1979 ePtr<iDVBFrontend> fe;
1980 if(!channel->getFrontend(fe))
1981 fe->getFrontendStatus(ret);
1989 PyObject *eDVBServiceBase::getTransponderData(bool original)
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))
2000 fe->getTransponderData(ret, original);
2001 ePtr<iDVBFrontendParameters> feparm;
2002 channel->getCurrentFrontendParameters(feparm);
2005 eDVBFrontendParametersSatellite osat;
2006 if (!feparm->getDVBS(osat))
2008 void PutToDict(ePyObject &, const char*, long);
2009 void PutToDict(ePyObject &, const char*, const char*);
2010 PutToDict(ret, "orbital_position", osat.orbital_position);
2011 const char *tmp = "UNKNOWN";
2012 switch(osat.polarisation)
2014 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2015 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2016 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2017 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2020 PutToDict(ret, "polarization", tmp);
2031 PyObject *eDVBServiceBase::getAll(bool original)
2033 ePyObject ret = getTransponderData(original);
2036 eUsePtr<iDVBChannel> channel;
2037 if(!m_service_handler.getChannel(channel))
2039 ePtr<iDVBFrontend> fe;
2040 if(!channel->getFrontend(fe))
2042 fe->getFrontendData(ret);
2043 fe->getFrontendStatus(ret);
2050 int eDVBServicePlay::getNumberOfSubservices()
2052 ePtr<eServiceEvent> evt;
2053 if (!m_event_handler.getEvent(evt, 0))
2054 return evt->getNumOfLinkageServices();
2058 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2060 ePtr<eServiceEvent> evt;
2061 if (!m_event_handler.getEvent(evt, 0))
2063 if (!evt->getLinkageService(sub, m_reference, n))
2066 sub.type=eServiceReference::idInvalid;
2070 RESULT eDVBServicePlay::startTimeshift()
2072 ePtr<iDVBDemux> demux;
2074 eDebug("Start timeshift!");
2076 if (m_timeshift_enabled)
2079 /* start recording with the data demux. */
2080 if (m_service_handler.getDataDemux(demux))
2083 demux->createTSRecorder(m_record);
2087 char templ[]=TSPATH "/timeshift.XXXXXX";
2088 m_timeshift_fd = mkstemp(templ);
2089 m_timeshift_file = templ;
2091 eDebug("recording to %s", templ);
2093 if (m_timeshift_fd < 0)
2099 m_record->setTargetFD(m_timeshift_fd);
2101 m_timeshift_enabled = 1;
2103 updateTimeshiftPids();
2109 RESULT eDVBServicePlay::stopTimeshift()
2111 if (!m_timeshift_enabled)
2116 m_timeshift_enabled = 0;
2121 close(m_timeshift_fd);
2122 eDebug("remove timeshift file");
2123 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2128 int eDVBServicePlay::isTimeshiftActive()
2130 return m_timeshift_enabled && m_timeshift_active;
2133 RESULT eDVBServicePlay::activateTimeshift()
2135 if (!m_timeshift_enabled)
2138 if (!m_timeshift_active)
2140 switchToTimeshift();
2147 PyObject *eDVBServicePlay::getCutList()
2149 ePyObject list = PyList_New(0);
2151 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2153 ePyObject tuple = PyTuple_New(2);
2154 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2155 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2156 PyList_Append(list, tuple);
2163 void eDVBServicePlay::setCutList(ePyObject list)
2165 if (!PyList_Check(list))
2167 int size = PyList_Size(list);
2170 m_cue_entries.clear();
2172 for (i=0; i<size; ++i)
2174 ePyObject tuple = PyList_GET_ITEM(list, i);
2175 if (!PyTuple_Check(tuple))
2177 eDebug("non-tuple in cutlist");
2180 if (PyTuple_Size(tuple) != 2)
2182 eDebug("cutlist entries need to be a 2-tuple");
2185 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2186 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2188 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2191 pts_t pts = PyLong_AsLongLong(ppts);
2192 int type = PyInt_AsLong(ptype);
2193 m_cue_entries.insert(cueEntry(pts, type));
2194 eDebug("adding %08llx, %d", pts, type);
2196 m_cuesheet_changed = 1;
2198 cutlistToCuesheet();
2199 m_event((iPlayableService*)this, evCuesheetChanged);
2202 void eDVBServicePlay::setCutListEnable(int enable)
2204 m_cutlist_enabled = enable;
2205 cutlistToCuesheet();
2208 void eDVBServicePlay::updateTimeshiftPids()
2213 eDVBServicePMTHandler::program program;
2214 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2216 if (h.getProgramInfo(program))
2220 std::set<int> pids_to_record;
2221 pids_to_record.insert(0); // PAT
2222 if (program.pmtPid != -1)
2223 pids_to_record.insert(program.pmtPid); // PMT
2225 if (program.textPid != -1)
2226 pids_to_record.insert(program.textPid); // Videotext
2228 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2229 i(program.videoStreams.begin());
2230 i != program.videoStreams.end(); ++i)
2231 pids_to_record.insert(i->pid);
2233 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2234 i(program.audioStreams.begin());
2235 i != program.audioStreams.end(); ++i)
2236 pids_to_record.insert(i->pid);
2238 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2239 i(program.subtitleStreams.begin());
2240 i != program.subtitleStreams.end(); ++i)
2241 pids_to_record.insert(i->pid);
2243 std::set<int> new_pids, obsolete_pids;
2245 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2246 m_pids_active.begin(), m_pids_active.end(),
2247 std::inserter(new_pids, new_pids.begin()));
2249 std::set_difference(
2250 m_pids_active.begin(), m_pids_active.end(),
2251 pids_to_record.begin(), pids_to_record.end(),
2252 std::inserter(new_pids, new_pids.begin())
2255 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2256 m_record->addPID(*i);
2258 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2259 m_record->removePID(*i);
2263 void eDVBServicePlay::switchToLive()
2265 if (!m_timeshift_active)
2271 m_teletext_parser = 0;
2273 m_subtitle_parser = 0;
2274 m_new_dvb_subtitle_page_connection = 0;
2275 m_new_subtitle_page_connection = 0;
2276 m_rds_decoder_event_connection = 0;
2277 m_video_event_connection = 0;
2279 /* free the timeshift service handler, we need the resources */
2280 m_service_handler_timeshift.free();
2281 m_timeshift_active = 0;
2283 m_event((iPlayableService*)this, evSeekableStatusChanged);
2288 void eDVBServicePlay::switchToTimeshift()
2290 if (m_timeshift_active)
2295 m_teletext_parser = 0;
2297 m_subtitle_parser = 0;
2298 m_new_subtitle_page_connection = 0;
2299 m_new_dvb_subtitle_page_connection = 0;
2300 m_rds_decoder_event_connection = 0;
2301 m_video_event_connection = 0;
2303 m_timeshift_active = 1;
2305 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2306 r.path = m_timeshift_file;
2308 m_cue = new eCueSheet();
2309 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2311 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2313 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2315 m_event((iPlayableService*)this, evSeekableStatusChanged);
2318 void eDVBServicePlay::updateDecoder()
2320 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2322 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2324 eDVBServicePMTHandler::program program;
2325 if (h.getProgramInfo(program))
2326 eDebug("getting program info failed.");
2329 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2330 if (!program.videoStreams.empty())
2332 eDebugNoNewLine(" (");
2333 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2334 i(program.videoStreams.begin());
2335 i != program.videoStreams.end(); ++i)
2342 if (i != program.videoStreams.begin())
2343 eDebugNoNewLine(", ");
2344 eDebugNoNewLine("%04x", i->pid);
2346 eDebugNoNewLine(")");
2348 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2349 if (!program.audioStreams.empty())
2351 eDebugNoNewLine(" (");
2352 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2353 i(program.audioStreams.begin());
2354 i != program.audioStreams.end(); ++i)
2356 if (i != program.audioStreams.begin())
2357 eDebugNoNewLine(", ");
2358 eDebugNoNewLine("%04x", i->pid);
2360 eDebugNoNewLine(")");
2362 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2363 pcrpid = program.pcrPid;
2364 eDebug(", and the text pid is %04x", program.textPid);
2365 tpid = program.textPid;
2370 h.getDecodeDemux(m_decode_demux);
2373 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2375 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2376 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2377 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2378 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2379 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2382 m_teletext_parser = 0;
2383 m_subtitle_parser = 0;
2387 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2394 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2395 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2396 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2398 else // subservice or recording
2400 eServiceReferenceDVB ref;
2401 m_service_handler.getServiceReference(ref);
2402 eServiceReferenceDVB parent = ref.getParentServiceReference();
2407 ePtr<eDVBResourceManager> res_mgr;
2408 if (!eDVBResourceManager::getInstance(res_mgr))
2410 ePtr<iDVBChannelList> db;
2411 if (!res_mgr->getChannelList(db))
2413 ePtr<eDVBService> origService;
2414 if (!db->getService(parent, origService))
2416 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2417 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2423 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2424 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2426 m_decoder->setVideoPID(vpid, vpidtype);
2427 selectAudioStream();
2429 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2430 m_decoder->setSyncPCR(pcrpid);
2432 m_decoder->setSyncPCR(-1);
2434 m_decoder->setTextPID(tpid);
2436 m_teletext_parser->start(program.textPid);
2439 m_decoder->setTrickmode(1);
2442 m_decoder->preroll();
2446 if (vpid > 0 && vpid < 0x2000)
2450 std::string radio_pic;
2451 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2452 m_decoder->setRadioPic(radio_pic);
2455 m_decoder->setAudioChannel(achannel);
2457 /* don't worry about non-existing services, nor pvr services */
2458 if (m_dvb_service && !m_is_pvr)
2460 /* (audio pid will be set in selectAudioTrack */
2461 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2462 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2463 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2464 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2467 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2470 void eDVBServicePlay::loadCuesheet()
2472 std::string filename = m_reference.path + ".cuts";
2474 m_cue_entries.clear();
2476 FILE *f = fopen(filename.c_str(), "rb");
2480 eDebug("loading cuts..");
2483 unsigned long long where;
2486 if (!fread(&where, sizeof(where), 1, f))
2488 if (!fread(&what, sizeof(what), 1, f))
2491 #if BYTE_ORDER == LITTLE_ENDIAN
2492 where = bswap_64(where);
2499 m_cue_entries.insert(cueEntry(where, what));
2502 eDebug("%d entries", m_cue_entries.size());
2504 eDebug("cutfile not found!");
2506 m_cuesheet_changed = 0;
2507 cutlistToCuesheet();
2508 m_event((iPlayableService*)this, evCuesheetChanged);
2511 void eDVBServicePlay::saveCuesheet()
2513 std::string filename = m_reference.path + ".cuts";
2515 FILE *f = fopen(filename.c_str(), "wb");
2519 unsigned long long where;
2522 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2524 #if BYTE_ORDER == BIG_ENDIAN
2527 where = bswap_64(i->where);
2529 what = htonl(i->what);
2530 fwrite(&where, sizeof(where), 1, f);
2531 fwrite(&what, sizeof(what), 1, f);
2537 m_cuesheet_changed = 0;
2540 void eDVBServicePlay::cutlistToCuesheet()
2544 eDebug("no cue sheet");
2549 if (!m_cutlist_enabled)
2551 m_cue->commitSpans();
2552 eDebug("cutlists were disabled");
2556 pts_t in = 0, out = 0, length = 0;
2560 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2564 if (i == m_cue_entries.end())
2567 if (i->what == 0) /* in */
2571 } else if (i->what == 1) /* out */
2573 else /* mark (2) or last play position (3) */
2590 m_cue->addSourceSpan(in, out);
2594 if (i == m_cue_entries.end())
2597 m_cue->commitSpans();
2600 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2602 if (m_subtitle_widget)
2603 disableSubtitles(parent);
2606 int tuplesize = PyTuple_Size(tuple);
2609 if (!PyTuple_Check(tuple))
2615 entry = PyTuple_GET_ITEM(tuple, 0);
2617 if (!PyInt_Check(entry))
2620 type = PyInt_AsLong(entry);
2622 if (type == 1) // teletext subtitles
2624 int page, magazine, pid;
2628 if (!m_teletext_parser)
2630 eDebug("enable teletext subtitles.. no parser !!!");
2634 entry = PyTuple_GET_ITEM(tuple, 1);
2635 if (!PyInt_Check(entry))
2637 pid = PyInt_AsLong(entry);
2639 entry = PyTuple_GET_ITEM(tuple, 2);
2640 if (!PyInt_Check(entry))
2642 page = PyInt_AsLong(entry);
2644 entry = PyTuple_GET_ITEM(tuple, 3);
2645 if (!PyInt_Check(entry))
2647 magazine = PyInt_AsLong(entry);
2649 m_subtitle_widget = new eSubtitleWidget(parent);
2650 m_subtitle_widget->resize(parent->size()); /* full size */
2651 m_teletext_parser->setPageAndMagazine(page, magazine);
2653 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2657 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2658 if (!m_subtitle_parser)
2660 eDebug("enable dvb subtitles.. no parser !!!");
2666 entry = PyTuple_GET_ITEM(tuple, 1);
2667 if (!PyInt_Check(entry))
2669 pid = PyInt_AsLong(entry);
2671 entry = PyTuple_GET_ITEM(tuple, 2);
2672 if (!PyInt_Check(entry))
2674 composition_page_id = PyInt_AsLong(entry);
2676 entry = PyTuple_GET_ITEM(tuple, 3);
2677 if (!PyInt_Check(entry))
2679 ancillary_page_id = PyInt_AsLong(entry);
2681 m_subtitle_widget = new eSubtitleWidget(parent);
2682 m_subtitle_widget->resize(parent->size()); /* full size */
2683 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2685 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2691 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2692 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2693 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2697 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2699 delete m_subtitle_widget;
2700 m_subtitle_widget = 0;
2701 if (m_subtitle_parser)
2703 m_subtitle_parser->stop();
2704 m_dvb_subtitle_pages.clear();
2706 if (m_teletext_parser)
2708 m_teletext_parser->setPageAndMagazine(-1, -1);
2709 m_subtitle_pages.clear();
2712 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2716 PyObject *eDVBServicePlay::getCachedSubtitle()
2720 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2723 unsigned int data = (unsigned int)tmp;
2724 int pid = (data&0xFFFF0000)>>16;
2725 ePyObject tuple = PyTuple_New(4);
2726 eDVBServicePMTHandler::program program;
2727 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2728 if (!h.getProgramInfo(program))
2730 if (program.textPid==pid) // teletext
2731 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2733 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2734 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2735 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2736 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2744 PyObject *eDVBServicePlay::getSubtitleList()
2746 if (!m_teletext_parser)
2749 ePyObject l = PyList_New(0);
2750 std::set<int> added_ttx_pages;
2752 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2753 m_teletext_parser->m_found_subtitle_pages;
2755 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2756 eDVBServicePMTHandler::program program;
2757 if (h.getProgramInfo(program))
2758 eDebug("getting program info failed.");
2761 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2762 it != program.subtitleStreams.end(); ++it)
2764 switch(it->subtitling_type)
2766 case 0x01: // ebu teletext subtitles
2768 int page_number = it->teletext_page_number & 0xFF;
2769 int magazine_number = it->teletext_magazine_number & 7;
2770 int hash = magazine_number << 8 | page_number;
2771 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2773 ePyObject tuple = PyTuple_New(5);
2774 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2775 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2776 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2777 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2778 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2779 PyList_Append(l, tuple);
2781 added_ttx_pages.insert(hash);
2786 case 0x20 ... 0x23: // dvb subtitles
2788 ePyObject tuple = PyTuple_New(5);
2789 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2790 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2791 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2792 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2793 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2794 PyList_Insert(l, 0, tuple);
2802 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2803 it != subs.end(); ++it)
2805 int page_number = it->teletext_page_number & 0xFF;
2806 int magazine_number = it->teletext_magazine_number & 7;
2807 int hash = magazine_number << 8 | page_number;
2808 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2810 ePyObject tuple = PyTuple_New(5);
2811 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2812 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2813 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2814 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2815 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2816 PyList_Append(l, tuple);
2824 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2826 if (m_subtitle_widget)
2830 m_decoder->getPTS(0, pos);
2831 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2832 m_subtitle_pages.push_back(page);
2833 checkSubtitleTiming();
2837 void eDVBServicePlay::checkSubtitleTiming()
2839 eDebug("checkSubtitleTiming");
2840 if (!m_subtitle_widget)
2844 enum { TELETEXT, DVB } type;
2845 eDVBTeletextSubtitlePage page;
2846 eDVBSubtitlePage dvb_page;
2848 if (!m_subtitle_pages.empty())
2850 page = m_subtitle_pages.front();
2852 show_time = page.m_pts;
2854 else if (!m_dvb_subtitle_pages.empty())
2856 dvb_page = m_dvb_subtitle_pages.front();
2858 show_time = dvb_page.m_show_time;
2866 m_decoder->getPTS(0, pos);
2868 eDebug("%lld %lld", pos, show_time);
2869 int diff = show_time - pos;
2872 eDebug("[late (%d ms)]", -diff / 90);
2875 // if (diff > 900000)
2877 // eDebug("[invalid]");
2883 if (type == TELETEXT)
2885 eDebug("display teletext subtitle page %lld", show_time);
2886 m_subtitle_widget->setPage(page);
2887 m_subtitle_pages.pop_front();
2891 eDebug("display dvb subtitle Page %lld", show_time);
2892 m_subtitle_widget->setPage(dvb_page);
2893 m_dvb_subtitle_pages.pop_front();
2897 eDebug("start subtitle delay %d", diff / 90);
2898 m_subtitle_sync_timer.start(diff / 90, 1);
2904 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2906 if (m_subtitle_widget)
2910 m_decoder->getPTS(0, pos);
2911 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2912 m_dvb_subtitle_pages.push_back(p);
2913 checkSubtitleTiming();
2917 int eDVBServicePlay::getAC3Delay()
2920 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2922 return m_decoder->getAC3Delay();
2927 int eDVBServicePlay::getPCMDelay()
2930 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2932 return m_decoder->getPCMDelay();
2937 void eDVBServicePlay::setAC3Delay(int delay)
2940 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2942 m_decoder->setAC3Delay(delay);
2945 void eDVBServicePlay::setPCMDelay(int delay)
2948 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2950 m_decoder->setPCMDelay(delay);
2953 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2955 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2956 m_event((iPlayableService*)this, evVideoSizeChanged);
2959 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2965 PyObject *eDVBServicePlay::getStreamingData()
2967 eDVBServicePMTHandler::program program;
2968 if (m_service_handler.getProgramInfo(program))
2974 PyObject *r = program.createPythonObject();
2975 ePtr<iDVBDemux> demux;
2976 if (!m_service_handler.getDataDemux(demux))
2979 demux->getCADemuxID(demux_id);
2981 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
2988 DEFINE_REF(eDVBServicePlay)
2990 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2994 case iServiceInformation::sTransponderData:
2995 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2999 return iStaticServiceInformation::getInfoObject(ref, w);
3002 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");