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);
1113 m_event((iPlayableService*)this, evTunedIn);
1116 case eDVBServicePMTHandler::eventNoResources:
1117 case eDVBServicePMTHandler::eventNoPAT:
1118 case eDVBServicePMTHandler::eventNoPATEntry:
1119 case eDVBServicePMTHandler::eventNoPMT:
1120 case eDVBServicePMTHandler::eventTuneFailed:
1121 case eDVBServicePMTHandler::eventMisconfiguration:
1123 eDebug("DVB service failed to tune - error %d", event);
1124 m_event((iPlayableService*)this, evTuneFailed);
1127 case eDVBServicePMTHandler::eventNewProgramInfo:
1129 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1130 if (m_timeshift_enabled)
1131 updateTimeshiftPids();
1132 if (!m_timeshift_active)
1134 if (m_first_program_info && m_is_pvr)
1136 m_first_program_info = 0;
1139 m_event((iPlayableService*)this, evUpdatedInfo);
1142 case eDVBServicePMTHandler::eventEOF:
1143 m_event((iPlayableService*)this, evEOF);
1145 case eDVBServicePMTHandler::eventSOF:
1146 m_event((iPlayableService*)this, evSOF);
1151 void eDVBServicePlay::serviceEventTimeshift(int event)
1155 case eDVBServicePMTHandler::eventNewProgramInfo:
1156 if (m_timeshift_active)
1159 case eDVBServicePMTHandler::eventSOF:
1160 m_event((iPlayableService*)this, evSOF);
1162 case eDVBServicePMTHandler::eventEOF:
1163 if ((!m_is_paused) && (m_skipmode >= 0))
1169 RESULT eDVBServicePlay::start()
1172 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1173 two (one for decoding, one for data source), as we must be prepared
1174 to start recording from the data demux. */
1176 m_cue = new eCueSheet();
1178 m_event(this, evStart);
1180 m_first_program_info = 1;
1181 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1182 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1184 /* inject EIT if there is a stored one */
1187 std::string filename = service.path;
1188 filename.erase(filename.length()-2, 2);
1190 ePtr<eServiceEvent> event = new eServiceEvent;
1191 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1193 ePtr<eServiceEvent> empty;
1194 m_event_handler.inject(event, 0);
1195 m_event_handler.inject(empty, 1);
1202 m_event(this, evStart);
1207 RESULT eDVBServicePlay::stop()
1209 /* add bookmark for last play position */
1212 pts_t play_position, length;
1213 if (!getPlayPosition(play_position))
1215 /* remove last position */
1216 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1218 if (i->what == 3) /* current play position */
1220 m_cue_entries.erase(i);
1221 i = m_cue_entries.begin();
1227 if (getLength(length))
1232 int perc = play_position * 100LL / length;
1234 /* only store last play position when between 1% and 99% */
1235 if ((1 < perc) && (perc < 99))
1236 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1238 m_cuesheet_changed = 1;
1242 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1244 m_service_handler_timeshift.free();
1245 m_service_handler.free();
1247 if (m_is_pvr && m_cuesheet_changed)
1250 /* save cuesheet only when main file is accessible. */
1251 if (!::stat(m_reference.path.c_str(), &s))
1254 m_event((iPlayableService*)this, evStopped);
1258 RESULT eDVBServicePlay::setTarget(int target)
1260 m_is_primary = !target;
1264 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1266 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1270 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1272 /* note: we check for timeshift to be enabled,
1273 not neccessary active. if you pause when timeshift
1274 is not active, you should activate it when unpausing */
1275 if ((!m_is_pvr) && (!m_timeshift_enabled))
1285 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1288 return m_decoder->setSlowMotion(ratio);
1293 RESULT eDVBServicePlay::setFastForward(int ratio)
1295 int skipmode, ffratio;
1301 } else if (ratio > 0)
1309 } else // if (ratio < 0)
1315 if (m_skipmode != skipmode)
1317 eDebug("setting cue skipmode to %d", skipmode);
1319 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1322 m_skipmode = skipmode;
1327 return m_decoder->setFastForward(ffratio);
1330 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1332 if (m_is_pvr || m_timeshift_enabled)
1342 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1343 RESULT eDVBServicePlay::getLength(pts_t &len)
1345 ePtr<iDVBPVRChannel> pvr_channel;
1347 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1350 return pvr_channel->getLength(len);
1353 RESULT eDVBServicePlay::pause()
1355 if (!m_is_paused && m_decoder)
1358 return m_decoder->freeze(0);
1363 RESULT eDVBServicePlay::unpause()
1365 if (m_is_paused && m_decoder)
1368 return m_decoder->unfreeze();
1373 RESULT eDVBServicePlay::seekTo(pts_t to)
1375 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1377 if (!m_decode_demux)
1380 ePtr<iDVBPVRChannel> pvr_channel;
1382 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1388 m_cue->seekTo(0, to);
1389 m_dvb_subtitle_pages.clear();
1390 m_subtitle_pages.clear();
1395 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1397 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1399 if (!m_decode_demux)
1402 ePtr<iDVBPVRChannel> pvr_channel;
1404 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1409 /* HACK until we have skip-AP api */
1410 if ((to > 0) && (to < 100))
1418 m_cue->seekTo(mode, to);
1419 m_dvb_subtitle_pages.clear();
1420 m_subtitle_pages.clear();
1424 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1426 ePtr<iDVBPVRChannel> pvr_channel;
1428 if (!m_decode_demux)
1431 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1436 /* if there is a decoder, use audio or video PTS */
1439 r = m_decoder->getPTS(0, pos);
1445 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1448 RESULT eDVBServicePlay::setTrickmode(int trick)
1451 m_decoder->setTrickmode(trick);
1455 RESULT eDVBServicePlay::isCurrentlySeekable()
1457 return m_is_pvr || m_timeshift_active;
1460 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1466 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1472 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1478 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1484 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1490 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1493 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1494 (m_timeshift_enabled || !m_is_pvr))
1496 if (!m_timeshift_enabled)
1498 /* we need enough diskspace */
1500 if (statfs(TSPATH "/.", &fs) < 0)
1502 eDebug("statfs failed!");
1506 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1508 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1518 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1529 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1535 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1541 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1547 RESULT eDVBServicePlay::getName(std::string &name)
1551 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1552 return i->getName(m_reference, name);
1556 m_dvb_service->getName(m_reference, name);
1560 else if (!m_reference.name.empty())
1561 eStaticServiceDVBInformation().getName(m_reference, name);
1563 name = "DVB service";
1567 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1569 return m_event_handler.getEvent(evt, nownext);
1572 static int readMpegProc(char *str, int decoder)
1576 sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
1577 FILE *f = fopen(tmp, "r");
1580 fscanf(f, "%x", &val);
1586 int eDVBServicePlay::getInfo(int w)
1588 eDVBServicePMTHandler::program program;
1591 return resIsPyObject;
1593 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1595 int no_program_info = 0;
1597 if (h.getProgramInfo(program))
1598 no_program_info = 1;
1602 #if HAVE_DVB_API_VERSION >= 3
1604 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1605 return m_videoEventData.height;
1607 return readMpegProc("yres", !m_is_primary);
1609 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1610 return m_videoEventData.width;
1612 return readMpegProc("xres", !m_is_primary);
1614 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1615 return m_videoEventData.framerate;
1617 return readMpegProc("framerate", !m_is_primary);
1619 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1620 return m_videoEventData.progressive;
1621 return readMpegProc("progressive", !m_is_primary);
1623 #warning "FIXMEE implement sFrameRate, sProgressive, sVideoHeight, sVideoWidth for old DVB API"
1628 #if HAVE_DVB_API_VERSION >= 3
1629 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1630 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1631 else if ((val=readMpegProc("aspect", !m_is_primary)) != -1)
1635 #warning "FIXMEE implement sAspect for old DVB API"
1637 if (no_program_info)
1639 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1641 ePtr<eServiceEvent> evt;
1642 if (!m_event_handler.getEvent(evt, 0))
1644 ePtr<eComponentData> data;
1645 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1647 if ( data->getStreamContent() == 1 )
1649 switch(data->getComponentType())
1652 case 1: // 4:3 SD PAL
1654 case 3: // 16:9 SD PAL
1655 case 4: // > 16:9 PAL
1656 case 5: // 4:3 SD NTSC
1658 case 7: // 16:9 SD NTSC
1659 case 8: // > 16:9 NTSC
1662 case 9: // 4:3 HD PAL
1664 case 0xB: // 16:9 HD PAL
1665 case 0xC: // > 16:9 HD PAL
1666 case 0xD: // 4:3 HD NTSC
1668 case 0xF: // 16:9 HD NTSC
1669 case 0x10: // > 16:9 HD PAL
1670 return data->getComponentType();
1678 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1679 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1680 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1681 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1682 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1683 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1684 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1685 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1686 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1687 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1688 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1689 case sProvider: if (!m_dvb_service) return -1; return -2;
1690 case sServiceref: return resIsString;
1691 case sDVBState: return m_tune_state;
1697 std::string eDVBServicePlay::getInfoString(int w)
1702 if (!m_dvb_service) return "";
1703 return m_dvb_service->m_provider_name;
1705 return m_reference.toString();
1709 return iServiceInformation::getInfoString(w);
1712 PyObject *eDVBServicePlay::getInfoObject(int w)
1717 return m_service_handler.getCaIds();
1718 case sTransponderData:
1719 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1723 return iServiceInformation::getInfoObject(w);
1726 int eDVBServicePlay::getNumberOfTracks()
1728 eDVBServicePMTHandler::program program;
1729 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1730 if (h.getProgramInfo(program))
1732 return program.audioStreams.size();
1735 int eDVBServicePlay::getCurrentTrack()
1737 eDVBServicePMTHandler::program program;
1738 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1739 if (h.getProgramInfo(program))
1742 int max = program.audioStreams.size();
1745 for (i = 0; i < max; ++i)
1746 if (program.audioStreams[i].pid == m_current_audio_pid)
1752 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1754 int ret = selectAudioStream(i);
1756 if (m_decoder->start())
1762 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1764 eDVBServicePMTHandler::program program;
1765 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1767 if (h.getProgramInfo(program))
1770 if (i >= program.audioStreams.size())
1773 info.m_pid = program.audioStreams[i].pid;
1775 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1776 info.m_description = "MPEG";
1777 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1778 info.m_description = "AC3";
1779 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1780 info.m_description = "AAC";
1781 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1782 info.m_description = "DTS";
1784 info.m_description = "???";
1786 if (program.audioStreams[i].component_tag != -1)
1788 ePtr<eServiceEvent> evt;
1789 if (!m_event_handler.getEvent(evt, 0))
1791 ePtr<eComponentData> data;
1792 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1793 info.m_language = data->getText();
1797 if (info.m_language.empty())
1798 info.m_language = program.audioStreams[i].language_code;
1803 int eDVBServicePlay::selectAudioStream(int i)
1805 eDVBServicePMTHandler::program program;
1806 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1808 if (h.getProgramInfo(program))
1811 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1819 stream = program.defaultAudioStream;
1821 int apid = -1, apidtype = -1;
1823 if (((unsigned int)stream) < program.audioStreams.size())
1825 apid = program.audioStreams[stream].pid;
1826 apidtype = program.audioStreams[stream].type;
1829 m_current_audio_pid = apid;
1831 if (m_decoder->setAudioPID(apid, apidtype))
1833 eDebug("set audio pid failed");
1837 /* 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 */
1838 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1841 ePtr<iDVBDemux> data_demux;
1842 if (!h.getDataDemux(data_demux))
1844 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1845 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1849 /* if we decided that we need one, update the pid */
1851 m_rds_decoder->start(apid);
1853 /* store new pid as default only when:
1854 a.) we have an entry in the service db for the current service,
1855 b.) we are not playing back something,
1856 c.) we are not selecting the default entry. (we wouldn't change
1857 anything in the best case, or destroy the default setting in
1858 case the real default is not yet available.)
1860 if (m_dvb_service && !m_is_pvr && ((i != -1)
1861 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1863 if (apidtype == eDVBAudio::aMPEG)
1865 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1866 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1870 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1871 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1875 h.resetCachedProgram();
1880 int eDVBServicePlay::getCurrentChannel()
1882 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1885 RESULT eDVBServicePlay::selectChannel(int i)
1887 if (i < LEFT || i > RIGHT || i == STEREO)
1890 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1892 m_decoder->setAudioChannel(i);
1896 std::string eDVBServicePlay::getText(int x)
1902 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1904 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1909 void eDVBServicePlay::rdsDecoderEvent(int what)
1913 case eDVBRdsDecoder::RadioTextChanged:
1914 m_event((iPlayableService*)this, evUpdatedRadioText);
1916 case eDVBRdsDecoder::RtpTextChanged:
1917 m_event((iPlayableService*)this, evUpdatedRtpText);
1919 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1920 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1922 case eDVBRdsDecoder::RecvRassSlidePic:
1923 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1928 void eDVBServicePlay::showRassSlidePicture()
1934 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1935 if (rass_slide_pic.length())
1936 m_decoder->showSinglePic(rass_slide_pic.c_str());
1938 eDebug("empty filename for rass slide picture received!!");
1941 eDebug("no MPEG Decoder to show iframes avail");
1944 eDebug("showRassSlidePicture called.. but not decoder");
1947 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1953 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1954 if (rass_interactive_pic.length())
1955 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1957 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1960 eDebug("no MPEG Decoder to show iframes avail");
1963 eDebug("showRassInteractivePic called.. but not decoder");
1966 ePyObject eDVBServicePlay::getRassInteractiveMask()
1969 return m_rds_decoder->getRassPictureMask();
1973 int eDVBServiceBase::getFrontendInfo(int w)
1975 eUsePtr<iDVBChannel> channel;
1976 if(m_service_handler.getChannel(channel))
1978 ePtr<iDVBFrontend> fe;
1979 if(channel->getFrontend(fe))
1981 return fe->readFrontendData(w);
1984 PyObject *eDVBServiceBase::getFrontendData()
1986 ePyObject ret = PyDict_New();
1989 eUsePtr<iDVBChannel> channel;
1990 if(!m_service_handler.getChannel(channel))
1992 ePtr<iDVBFrontend> fe;
1993 if(!channel->getFrontend(fe))
1994 fe->getFrontendData(ret);
2002 PyObject *eDVBServiceBase::getFrontendStatus()
2004 ePyObject ret = PyDict_New();
2007 eUsePtr<iDVBChannel> channel;
2008 if(!m_service_handler.getChannel(channel))
2010 ePtr<iDVBFrontend> fe;
2011 if(!channel->getFrontend(fe))
2012 fe->getFrontendStatus(ret);
2020 PyObject *eDVBServiceBase::getTransponderData(bool original)
2022 ePyObject ret = PyDict_New();
2025 eUsePtr<iDVBChannel> channel;
2026 if(!m_service_handler.getChannel(channel))
2028 ePtr<iDVBFrontend> fe;
2029 if(!channel->getFrontend(fe))
2031 fe->getTransponderData(ret, original);
2032 ePtr<iDVBFrontendParameters> feparm;
2033 channel->getCurrentFrontendParameters(feparm);
2036 eDVBFrontendParametersSatellite osat;
2037 if (!feparm->getDVBS(osat))
2039 void PutToDict(ePyObject &, const char*, long);
2040 void PutToDict(ePyObject &, const char*, const char*);
2041 PutToDict(ret, "orbital_position", osat.orbital_position);
2042 const char *tmp = "UNKNOWN";
2043 switch(osat.polarisation)
2045 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2046 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2047 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2048 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2051 PutToDict(ret, "polarization", tmp);
2062 PyObject *eDVBServiceBase::getAll(bool original)
2064 ePyObject ret = getTransponderData(original);
2067 eUsePtr<iDVBChannel> channel;
2068 if(!m_service_handler.getChannel(channel))
2070 ePtr<iDVBFrontend> fe;
2071 if(!channel->getFrontend(fe))
2073 fe->getFrontendData(ret);
2074 fe->getFrontendStatus(ret);
2081 int eDVBServicePlay::getNumberOfSubservices()
2083 ePtr<eServiceEvent> evt;
2084 if (!m_event_handler.getEvent(evt, 0))
2085 return evt->getNumOfLinkageServices();
2089 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2091 ePtr<eServiceEvent> evt;
2092 if (!m_event_handler.getEvent(evt, 0))
2094 if (!evt->getLinkageService(sub, m_reference, n))
2097 sub.type=eServiceReference::idInvalid;
2101 RESULT eDVBServicePlay::startTimeshift()
2103 ePtr<iDVBDemux> demux;
2105 eDebug("Start timeshift!");
2107 if (m_timeshift_enabled)
2110 /* start recording with the data demux. */
2111 if (m_service_handler.getDataDemux(demux))
2114 demux->createTSRecorder(m_record);
2118 char templ[]=TSPATH "/timeshift.XXXXXX";
2119 m_timeshift_fd = mkstemp(templ);
2120 m_timeshift_file = templ;
2122 eDebug("recording to %s", templ);
2124 if (m_timeshift_fd < 0)
2130 m_record->setTargetFD(m_timeshift_fd);
2132 m_timeshift_enabled = 1;
2134 updateTimeshiftPids();
2140 RESULT eDVBServicePlay::stopTimeshift()
2142 if (!m_timeshift_enabled)
2147 m_timeshift_enabled = 0;
2152 close(m_timeshift_fd);
2153 eDebug("remove timeshift file");
2154 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2159 int eDVBServicePlay::isTimeshiftActive()
2161 return m_timeshift_enabled && m_timeshift_active;
2164 RESULT eDVBServicePlay::activateTimeshift()
2166 if (!m_timeshift_enabled)
2169 if (!m_timeshift_active)
2171 switchToTimeshift();
2178 PyObject *eDVBServicePlay::getCutList()
2180 ePyObject list = PyList_New(0);
2182 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2184 ePyObject tuple = PyTuple_New(2);
2185 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2186 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2187 PyList_Append(list, tuple);
2194 void eDVBServicePlay::setCutList(ePyObject list)
2196 if (!PyList_Check(list))
2198 int size = PyList_Size(list);
2201 m_cue_entries.clear();
2203 for (i=0; i<size; ++i)
2205 ePyObject tuple = PyList_GET_ITEM(list, i);
2206 if (!PyTuple_Check(tuple))
2208 eDebug("non-tuple in cutlist");
2211 if (PyTuple_Size(tuple) != 2)
2213 eDebug("cutlist entries need to be a 2-tuple");
2216 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2217 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2219 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2222 pts_t pts = PyLong_AsLongLong(ppts);
2223 int type = PyInt_AsLong(ptype);
2224 m_cue_entries.insert(cueEntry(pts, type));
2225 eDebug("adding %08llx, %d", pts, type);
2227 m_cuesheet_changed = 1;
2229 cutlistToCuesheet();
2230 m_event((iPlayableService*)this, evCuesheetChanged);
2233 void eDVBServicePlay::setCutListEnable(int enable)
2235 m_cutlist_enabled = enable;
2236 cutlistToCuesheet();
2239 void eDVBServicePlay::updateTimeshiftPids()
2244 eDVBServicePMTHandler::program program;
2245 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2247 if (h.getProgramInfo(program))
2251 std::set<int> pids_to_record;
2252 pids_to_record.insert(0); // PAT
2253 if (program.pmtPid != -1)
2254 pids_to_record.insert(program.pmtPid); // PMT
2256 if (program.textPid != -1)
2257 pids_to_record.insert(program.textPid); // Videotext
2259 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2260 i(program.videoStreams.begin());
2261 i != program.videoStreams.end(); ++i)
2262 pids_to_record.insert(i->pid);
2264 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2265 i(program.audioStreams.begin());
2266 i != program.audioStreams.end(); ++i)
2267 pids_to_record.insert(i->pid);
2269 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2270 i(program.subtitleStreams.begin());
2271 i != program.subtitleStreams.end(); ++i)
2272 pids_to_record.insert(i->pid);
2274 std::set<int> new_pids, obsolete_pids;
2276 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2277 m_pids_active.begin(), m_pids_active.end(),
2278 std::inserter(new_pids, new_pids.begin()));
2280 std::set_difference(
2281 m_pids_active.begin(), m_pids_active.end(),
2282 pids_to_record.begin(), pids_to_record.end(),
2283 std::inserter(new_pids, new_pids.begin())
2286 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2287 m_record->addPID(*i);
2289 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2290 m_record->removePID(*i);
2294 void eDVBServicePlay::switchToLive()
2296 if (!m_timeshift_active)
2302 m_teletext_parser = 0;
2304 m_subtitle_parser = 0;
2305 m_new_dvb_subtitle_page_connection = 0;
2306 m_new_subtitle_page_connection = 0;
2307 m_rds_decoder_event_connection = 0;
2308 m_video_event_connection = 0;
2310 /* free the timeshift service handler, we need the resources */
2311 m_service_handler_timeshift.free();
2312 m_timeshift_active = 0;
2314 m_event((iPlayableService*)this, evSeekableStatusChanged);
2319 void eDVBServicePlay::switchToTimeshift()
2321 if (m_timeshift_active)
2326 m_teletext_parser = 0;
2328 m_subtitle_parser = 0;
2329 m_new_subtitle_page_connection = 0;
2330 m_new_dvb_subtitle_page_connection = 0;
2331 m_rds_decoder_event_connection = 0;
2332 m_video_event_connection = 0;
2334 m_timeshift_active = 1;
2336 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2337 r.path = m_timeshift_file;
2339 m_cue = new eCueSheet();
2340 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2342 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2344 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2346 m_event((iPlayableService*)this, evSeekableStatusChanged);
2349 void eDVBServicePlay::updateDecoder()
2351 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2353 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2355 eDVBServicePMTHandler::program program;
2356 if (h.getProgramInfo(program))
2357 eDebug("getting program info failed.");
2360 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2361 if (!program.videoStreams.empty())
2363 eDebugNoNewLine(" (");
2364 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2365 i(program.videoStreams.begin());
2366 i != program.videoStreams.end(); ++i)
2373 if (i != program.videoStreams.begin())
2374 eDebugNoNewLine(", ");
2375 eDebugNoNewLine("%04x", i->pid);
2377 eDebugNoNewLine(")");
2379 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2380 if (!program.audioStreams.empty())
2382 eDebugNoNewLine(" (");
2383 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2384 i(program.audioStreams.begin());
2385 i != program.audioStreams.end(); ++i)
2387 if (i != program.audioStreams.begin())
2388 eDebugNoNewLine(", ");
2389 eDebugNoNewLine("%04x", i->pid);
2391 eDebugNoNewLine(")");
2393 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2394 pcrpid = program.pcrPid;
2395 eDebug(", and the text pid is %04x", program.textPid);
2396 tpid = program.textPid;
2401 h.getDecodeDemux(m_decode_demux);
2404 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2406 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2407 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2408 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2409 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2410 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2413 m_teletext_parser = 0;
2414 m_subtitle_parser = 0;
2418 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2425 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2426 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2427 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2429 else // subservice or recording
2431 eServiceReferenceDVB ref;
2432 m_service_handler.getServiceReference(ref);
2433 eServiceReferenceDVB parent = ref.getParentServiceReference();
2438 ePtr<eDVBResourceManager> res_mgr;
2439 if (!eDVBResourceManager::getInstance(res_mgr))
2441 ePtr<iDVBChannelList> db;
2442 if (!res_mgr->getChannelList(db))
2444 ePtr<eDVBService> origService;
2445 if (!db->getService(parent, origService))
2447 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2448 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2454 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2455 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2457 m_decoder->setVideoPID(vpid, vpidtype);
2458 selectAudioStream();
2460 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2461 m_decoder->setSyncPCR(pcrpid);
2463 m_decoder->setSyncPCR(-1);
2465 m_decoder->setTextPID(tpid);
2467 m_teletext_parser->start(program.textPid);
2470 m_decoder->setTrickmode(1);
2473 m_decoder->preroll();
2477 if (vpid > 0 && vpid < 0x2000)
2481 std::string radio_pic;
2482 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2483 m_decoder->setRadioPic(radio_pic);
2486 m_decoder->setAudioChannel(achannel);
2488 /* don't worry about non-existing services, nor pvr services */
2489 if (m_dvb_service && !m_is_pvr)
2491 /* (audio pid will be set in selectAudioTrack */
2492 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2493 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2494 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2495 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2498 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2501 void eDVBServicePlay::loadCuesheet()
2503 std::string filename = m_reference.path + ".cuts";
2505 m_cue_entries.clear();
2507 FILE *f = fopen(filename.c_str(), "rb");
2511 eDebug("loading cuts..");
2514 unsigned long long where;
2517 if (!fread(&where, sizeof(where), 1, f))
2519 if (!fread(&what, sizeof(what), 1, f))
2522 #if BYTE_ORDER == LITTLE_ENDIAN
2523 where = bswap_64(where);
2530 m_cue_entries.insert(cueEntry(where, what));
2533 eDebug("%d entries", m_cue_entries.size());
2535 eDebug("cutfile not found!");
2537 m_cuesheet_changed = 0;
2538 cutlistToCuesheet();
2539 m_event((iPlayableService*)this, evCuesheetChanged);
2542 void eDVBServicePlay::saveCuesheet()
2544 std::string filename = m_reference.path + ".cuts";
2546 FILE *f = fopen(filename.c_str(), "wb");
2550 unsigned long long where;
2553 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2555 #if BYTE_ORDER == BIG_ENDIAN
2558 where = bswap_64(i->where);
2560 what = htonl(i->what);
2561 fwrite(&where, sizeof(where), 1, f);
2562 fwrite(&what, sizeof(what), 1, f);
2568 m_cuesheet_changed = 0;
2571 void eDVBServicePlay::cutlistToCuesheet()
2575 eDebug("no cue sheet");
2580 if (!m_cutlist_enabled)
2582 m_cue->commitSpans();
2583 eDebug("cutlists were disabled");
2587 pts_t in = 0, out = 0, length = 0;
2591 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2595 if (i == m_cue_entries.end())
2598 if (i->what == 0) /* in */
2602 } else if (i->what == 1) /* out */
2604 else /* mark (2) or last play position (3) */
2621 m_cue->addSourceSpan(in, out);
2625 if (i == m_cue_entries.end())
2628 m_cue->commitSpans();
2631 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2633 if (m_subtitle_widget)
2634 disableSubtitles(parent);
2637 int tuplesize = PyTuple_Size(tuple);
2640 if (!PyTuple_Check(tuple))
2646 entry = PyTuple_GET_ITEM(tuple, 0);
2648 if (!PyInt_Check(entry))
2651 type = PyInt_AsLong(entry);
2653 if (type == 1) // teletext subtitles
2655 int page, magazine, pid;
2659 if (!m_teletext_parser)
2661 eDebug("enable teletext subtitles.. no parser !!!");
2665 entry = PyTuple_GET_ITEM(tuple, 1);
2666 if (!PyInt_Check(entry))
2668 pid = PyInt_AsLong(entry);
2670 entry = PyTuple_GET_ITEM(tuple, 2);
2671 if (!PyInt_Check(entry))
2673 page = PyInt_AsLong(entry);
2675 entry = PyTuple_GET_ITEM(tuple, 3);
2676 if (!PyInt_Check(entry))
2678 magazine = PyInt_AsLong(entry);
2680 m_subtitle_widget = new eSubtitleWidget(parent);
2681 m_subtitle_widget->resize(parent->size()); /* full size */
2682 m_teletext_parser->setPageAndMagazine(page, magazine);
2684 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2688 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2689 if (!m_subtitle_parser)
2691 eDebug("enable dvb subtitles.. no parser !!!");
2697 entry = PyTuple_GET_ITEM(tuple, 1);
2698 if (!PyInt_Check(entry))
2700 pid = PyInt_AsLong(entry);
2702 entry = PyTuple_GET_ITEM(tuple, 2);
2703 if (!PyInt_Check(entry))
2705 composition_page_id = PyInt_AsLong(entry);
2707 entry = PyTuple_GET_ITEM(tuple, 3);
2708 if (!PyInt_Check(entry))
2710 ancillary_page_id = PyInt_AsLong(entry);
2712 m_subtitle_widget = new eSubtitleWidget(parent);
2713 m_subtitle_widget->resize(parent->size()); /* full size */
2714 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2716 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2722 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2723 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2724 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2728 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2730 delete m_subtitle_widget;
2731 m_subtitle_widget = 0;
2732 if (m_subtitle_parser)
2734 m_subtitle_parser->stop();
2735 m_dvb_subtitle_pages.clear();
2737 if (m_teletext_parser)
2739 m_teletext_parser->setPageAndMagazine(-1, -1);
2740 m_subtitle_pages.clear();
2743 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2747 PyObject *eDVBServicePlay::getCachedSubtitle()
2751 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2754 unsigned int data = (unsigned int)tmp;
2755 int pid = (data&0xFFFF0000)>>16;
2756 ePyObject tuple = PyTuple_New(4);
2757 eDVBServicePMTHandler::program program;
2758 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2759 if (!h.getProgramInfo(program))
2761 if (program.textPid==pid) // teletext
2762 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2764 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2765 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2766 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2767 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2775 PyObject *eDVBServicePlay::getSubtitleList()
2777 if (!m_teletext_parser)
2780 ePyObject l = PyList_New(0);
2781 std::set<int> added_ttx_pages;
2783 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2784 m_teletext_parser->m_found_subtitle_pages;
2786 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2787 eDVBServicePMTHandler::program program;
2788 if (h.getProgramInfo(program))
2789 eDebug("getting program info failed.");
2792 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2793 it != program.subtitleStreams.end(); ++it)
2795 switch(it->subtitling_type)
2797 case 0x01: // ebu teletext subtitles
2799 int page_number = it->teletext_page_number & 0xFF;
2800 int magazine_number = it->teletext_magazine_number & 7;
2801 int hash = magazine_number << 8 | page_number;
2802 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2804 ePyObject tuple = PyTuple_New(5);
2805 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2806 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2807 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2808 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2809 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2810 PyList_Append(l, tuple);
2812 added_ttx_pages.insert(hash);
2817 case 0x20 ... 0x23: // dvb subtitles
2819 ePyObject tuple = PyTuple_New(5);
2820 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2821 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2822 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2823 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2824 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2825 PyList_Insert(l, 0, tuple);
2833 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2834 it != subs.end(); ++it)
2836 int page_number = it->teletext_page_number & 0xFF;
2837 int magazine_number = it->teletext_magazine_number & 7;
2838 int hash = magazine_number << 8 | page_number;
2839 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2841 ePyObject tuple = PyTuple_New(5);
2842 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2843 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2844 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2845 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2846 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2847 PyList_Append(l, tuple);
2855 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2857 if (m_subtitle_widget)
2861 m_decoder->getPTS(0, pos);
2862 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2863 m_subtitle_pages.push_back(page);
2864 checkSubtitleTiming();
2868 void eDVBServicePlay::checkSubtitleTiming()
2870 eDebug("checkSubtitleTiming");
2871 if (!m_subtitle_widget)
2875 enum { TELETEXT, DVB } type;
2876 eDVBTeletextSubtitlePage page;
2877 eDVBSubtitlePage dvb_page;
2879 if (!m_subtitle_pages.empty())
2881 page = m_subtitle_pages.front();
2883 show_time = page.m_pts;
2885 else if (!m_dvb_subtitle_pages.empty())
2887 dvb_page = m_dvb_subtitle_pages.front();
2889 show_time = dvb_page.m_show_time;
2897 m_decoder->getPTS(0, pos);
2899 eDebug("%lld %lld", pos, show_time);
2900 int diff = show_time - pos;
2903 eDebug("[late (%d ms)]", -diff / 90);
2906 // if (diff > 900000)
2908 // eDebug("[invalid]");
2914 if (type == TELETEXT)
2916 eDebug("display teletext subtitle page %lld", show_time);
2917 m_subtitle_widget->setPage(page);
2918 m_subtitle_pages.pop_front();
2922 eDebug("display dvb subtitle Page %lld", show_time);
2923 m_subtitle_widget->setPage(dvb_page);
2924 m_dvb_subtitle_pages.pop_front();
2928 eDebug("start subtitle delay %d", diff / 90);
2929 m_subtitle_sync_timer.start(diff / 90, 1);
2935 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2937 if (m_subtitle_widget)
2941 m_decoder->getPTS(0, pos);
2942 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2943 m_dvb_subtitle_pages.push_back(p);
2944 checkSubtitleTiming();
2948 int eDVBServicePlay::getAC3Delay()
2951 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2953 return m_decoder->getAC3Delay();
2958 int eDVBServicePlay::getPCMDelay()
2961 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2963 return m_decoder->getPCMDelay();
2968 void eDVBServicePlay::setAC3Delay(int delay)
2971 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2973 m_decoder->setAC3Delay(delay);
2976 void eDVBServicePlay::setPCMDelay(int delay)
2979 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2981 m_decoder->setPCMDelay(delay);
2984 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2986 memcpy(&m_videoEventData, &event, sizeof(event));
2987 switch(event.type) {
2988 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2989 m_event((iPlayableService*)this, evVideoSizeChanged);
2991 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2992 m_event((iPlayableService*)this, evVideoFramerateChanged);
2994 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2995 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3000 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3006 PyObject *eDVBServicePlay::getStreamingData()
3008 eDVBServicePMTHandler::program program;
3009 if (m_service_handler.getProgramInfo(program))
3015 PyObject *r = program.createPythonObject();
3016 ePtr<iDVBDemux> demux;
3017 if (!m_service_handler.getDataDemux(demux))
3020 demux->getCADemuxID(demux_id);
3022 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
3029 DEFINE_REF(eDVBServicePlay)
3031 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3035 case iServiceInformation::sTransponderData:
3036 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3040 return iStaticServiceInformation::getInfoObject(ref, w);
3043 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");