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 m_subtitle_sync_timer = eTimer::create(eApp);
1070 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
1073 eDVBServicePlay::~eDVBServicePlay()
1075 delete m_subtitle_widget;
1078 void eDVBServicePlay::gotNewEvent()
1082 ePtr<eServiceEvent> m_event_now, m_event_next;
1083 getEvent(m_event_now, 0);
1084 getEvent(m_event_next, 1);
1087 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1089 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1091 m_event((iPlayableService*)this, evUpdatedEventInfo);
1094 void eDVBServicePlay::serviceEvent(int event)
1096 m_tune_state = event;
1100 case eDVBServicePMTHandler::eventTuned:
1102 ePtr<iDVBDemux> m_demux;
1103 if (!m_service_handler.getDataDemux(m_demux))
1105 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1106 int sid = ref.getParentServiceID().get();
1108 sid = ref.getServiceID().get();
1109 if ( ref.getParentTransportStreamID().get() &&
1110 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1111 m_event_handler.startOther(m_demux, sid);
1113 m_event_handler.start(m_demux, sid);
1115 m_event((iPlayableService*)this, evTunedIn);
1118 case eDVBServicePMTHandler::eventNoResources:
1119 case eDVBServicePMTHandler::eventNoPAT:
1120 case eDVBServicePMTHandler::eventNoPATEntry:
1121 case eDVBServicePMTHandler::eventNoPMT:
1122 case eDVBServicePMTHandler::eventTuneFailed:
1123 case eDVBServicePMTHandler::eventMisconfiguration:
1125 eDebug("DVB service failed to tune - error %d", event);
1126 m_event((iPlayableService*)this, evTuneFailed);
1129 case eDVBServicePMTHandler::eventNewProgramInfo:
1131 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1132 if (m_timeshift_enabled)
1133 updateTimeshiftPids();
1134 if (!m_timeshift_active)
1136 if (m_first_program_info && m_is_pvr)
1138 m_first_program_info = 0;
1141 m_event((iPlayableService*)this, evUpdatedInfo);
1144 case eDVBServicePMTHandler::eventEOF:
1145 m_event((iPlayableService*)this, evEOF);
1147 case eDVBServicePMTHandler::eventSOF:
1148 m_event((iPlayableService*)this, evSOF);
1153 void eDVBServicePlay::serviceEventTimeshift(int event)
1157 case eDVBServicePMTHandler::eventNewProgramInfo:
1158 if (m_timeshift_active)
1161 case eDVBServicePMTHandler::eventSOF:
1162 m_event((iPlayableService*)this, evSOF);
1164 case eDVBServicePMTHandler::eventEOF:
1165 if ((!m_is_paused) && (m_skipmode >= 0))
1171 RESULT eDVBServicePlay::start()
1174 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1175 two (one for decoding, one for data source), as we must be prepared
1176 to start recording from the data demux. */
1178 m_cue = new eCueSheet();
1180 m_event(this, evStart);
1182 m_first_program_info = 1;
1183 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1184 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1186 /* inject EIT if there is a stored one */
1189 std::string filename = service.path;
1190 filename.erase(filename.length()-2, 2);
1192 ePtr<eServiceEvent> event = new eServiceEvent;
1193 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1195 ePtr<eServiceEvent> empty;
1196 m_event_handler.inject(event, 0);
1197 m_event_handler.inject(empty, 1);
1204 m_event(this, evStart);
1209 RESULT eDVBServicePlay::stop()
1211 /* add bookmark for last play position */
1214 pts_t play_position, length;
1215 if (!getPlayPosition(play_position))
1217 /* remove last position */
1218 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1220 if (i->what == 3) /* current play position */
1222 m_cue_entries.erase(i);
1223 i = m_cue_entries.begin();
1229 if (getLength(length))
1234 int perc = play_position * 100LL / length;
1236 /* only store last play position when between 1% and 99% */
1237 if ((1 < perc) && (perc < 99))
1238 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1240 m_cuesheet_changed = 1;
1244 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1246 m_service_handler_timeshift.free();
1247 m_service_handler.free();
1249 if (m_is_pvr && m_cuesheet_changed)
1252 /* save cuesheet only when main file is accessible. */
1253 if (!::stat(m_reference.path.c_str(), &s))
1256 m_event((iPlayableService*)this, evStopped);
1260 RESULT eDVBServicePlay::setTarget(int target)
1262 m_is_primary = !target;
1266 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1268 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1272 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1274 /* note: we check for timeshift to be enabled,
1275 not neccessary active. if you pause when timeshift
1276 is not active, you should activate it when unpausing */
1277 if ((!m_is_pvr) && (!m_timeshift_enabled))
1287 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1289 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1291 return m_decoder->setSlowMotion(ratio);
1296 RESULT eDVBServicePlay::setFastForward(int ratio)
1298 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1299 int skipmode, ffratio;
1305 } else if (ratio > 0)
1313 } else // if (ratio < 0)
1319 if (m_skipmode != skipmode)
1321 eDebug("setting cue skipmode to %d", skipmode);
1323 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1326 m_skipmode = skipmode;
1331 return m_decoder->setFastForward(ffratio);
1334 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1336 if (m_is_pvr || m_timeshift_enabled)
1346 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1347 RESULT eDVBServicePlay::getLength(pts_t &len)
1349 ePtr<iDVBPVRChannel> pvr_channel;
1351 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1354 return pvr_channel->getLength(len);
1357 RESULT eDVBServicePlay::pause()
1359 eDebug("eDVBServicePlay::pause");
1360 if (!m_is_paused && m_decoder)
1363 return m_decoder->freeze(0);
1368 RESULT eDVBServicePlay::unpause()
1370 eDebug("eDVBServicePlay::unpause");
1371 if (m_is_paused && m_decoder)
1374 return m_decoder->unfreeze();
1379 RESULT eDVBServicePlay::seekTo(pts_t to)
1381 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1383 if (!m_decode_demux)
1386 ePtr<iDVBPVRChannel> pvr_channel;
1388 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1394 m_cue->seekTo(0, to);
1395 m_dvb_subtitle_pages.clear();
1396 m_subtitle_pages.clear();
1401 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1403 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1405 if (!m_decode_demux)
1408 ePtr<iDVBPVRChannel> pvr_channel;
1410 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1415 /* HACK until we have skip-AP api */
1416 if ((to > 0) && (to < 100))
1424 m_cue->seekTo(mode, to);
1425 m_dvb_subtitle_pages.clear();
1426 m_subtitle_pages.clear();
1430 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1432 ePtr<iDVBPVRChannel> pvr_channel;
1434 if (!m_decode_demux)
1437 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1442 /* if there is a decoder, use audio or video PTS */
1445 r = m_decoder->getPTS(0, pos);
1451 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1454 RESULT eDVBServicePlay::setTrickmode(int trick)
1457 m_decoder->setTrickmode(trick);
1461 RESULT eDVBServicePlay::isCurrentlySeekable()
1463 return m_is_pvr || m_timeshift_active;
1466 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1472 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1478 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1484 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1490 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1496 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1499 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1500 (m_timeshift_enabled || !m_is_pvr))
1502 if (!m_timeshift_enabled)
1504 /* we need enough diskspace */
1506 if (statfs(TSPATH "/.", &fs) < 0)
1508 eDebug("statfs failed!");
1512 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1514 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1524 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1535 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1541 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1547 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1553 RESULT eDVBServicePlay::getName(std::string &name)
1557 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1558 return i->getName(m_reference, name);
1562 m_dvb_service->getName(m_reference, name);
1566 else if (!m_reference.name.empty())
1567 eStaticServiceDVBInformation().getName(m_reference, name);
1569 name = "DVB service";
1573 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1575 return m_event_handler.getEvent(evt, nownext);
1578 static int readMpegProc(char *str, int decoder)
1582 sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
1583 FILE *f = fopen(tmp, "r");
1586 fscanf(f, "%x", &val);
1592 int eDVBServicePlay::getInfo(int w)
1594 eDVBServicePMTHandler::program program;
1597 return resIsPyObject;
1599 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1601 int no_program_info = 0;
1603 if (h.getProgramInfo(program))
1604 no_program_info = 1;
1608 #if HAVE_DVB_API_VERSION >= 3
1610 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1611 return m_videoEventData.height;
1613 return readMpegProc("yres", !m_is_primary);
1615 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1616 return m_videoEventData.width;
1618 return readMpegProc("xres", !m_is_primary);
1620 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventFrameRateChanged)
1621 return m_videoEventData.framerate;
1623 return readMpegProc("framerate", !m_is_primary);
1625 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventProgressiveChanged)
1626 return m_videoEventData.progressive;
1627 return readMpegProc("progressive", !m_is_primary);
1629 #warning "FIXMEE implement sFrameRate, sProgressive, sVideoHeight, sVideoWidth for old DVB API"
1634 #if HAVE_DVB_API_VERSION >= 3
1635 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1636 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1637 else if ((val=readMpegProc("aspect", !m_is_primary)) != -1)
1641 #warning "FIXMEE implement sAspect for old DVB API"
1643 if (no_program_info)
1645 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1647 ePtr<eServiceEvent> evt;
1648 if (!m_event_handler.getEvent(evt, 0))
1650 ePtr<eComponentData> data;
1651 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1653 if ( data->getStreamContent() == 1 )
1655 switch(data->getComponentType())
1658 case 1: // 4:3 SD PAL
1660 case 3: // 16:9 SD PAL
1661 case 4: // > 16:9 PAL
1662 case 5: // 4:3 SD NTSC
1664 case 7: // 16:9 SD NTSC
1665 case 8: // > 16:9 NTSC
1668 case 9: // 4:3 HD PAL
1670 case 0xB: // 16:9 HD PAL
1671 case 0xC: // > 16:9 HD PAL
1672 case 0xD: // 4:3 HD NTSC
1674 case 0xF: // 16:9 HD NTSC
1675 case 0x10: // > 16:9 HD PAL
1676 return data->getComponentType();
1684 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1685 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1686 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1687 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1688 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1689 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1690 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1691 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1692 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1693 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1694 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1695 case sProvider: if (!m_dvb_service) return -1; return -2;
1696 case sServiceref: return resIsString;
1697 case sDVBState: return m_tune_state;
1703 std::string eDVBServicePlay::getInfoString(int w)
1708 if (!m_dvb_service) return "";
1709 return m_dvb_service->m_provider_name;
1711 return m_reference.toString();
1715 return iServiceInformation::getInfoString(w);
1718 PyObject *eDVBServicePlay::getInfoObject(int w)
1723 return m_service_handler.getCaIds();
1724 case sTransponderData:
1725 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1729 return iServiceInformation::getInfoObject(w);
1732 int eDVBServicePlay::getNumberOfTracks()
1734 eDVBServicePMTHandler::program program;
1735 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1736 if (h.getProgramInfo(program))
1738 return program.audioStreams.size();
1741 int eDVBServicePlay::getCurrentTrack()
1743 eDVBServicePMTHandler::program program;
1744 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1745 if (h.getProgramInfo(program))
1748 int max = program.audioStreams.size();
1751 for (i = 0; i < max; ++i)
1752 if (program.audioStreams[i].pid == m_current_audio_pid)
1758 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1760 int ret = selectAudioStream(i);
1762 if (m_decoder->start())
1768 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1770 eDVBServicePMTHandler::program program;
1771 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1773 if (h.getProgramInfo(program))
1776 if (i >= program.audioStreams.size())
1779 info.m_pid = program.audioStreams[i].pid;
1781 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1782 info.m_description = "MPEG";
1783 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1784 info.m_description = "AC3";
1785 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1786 info.m_description = "AAC";
1787 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1788 info.m_description = "DTS";
1790 info.m_description = "???";
1792 if (program.audioStreams[i].component_tag != -1)
1794 ePtr<eServiceEvent> evt;
1795 if (!m_event_handler.getEvent(evt, 0))
1797 ePtr<eComponentData> data;
1798 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1799 info.m_language = data->getText();
1803 if (info.m_language.empty())
1804 info.m_language = program.audioStreams[i].language_code;
1809 int eDVBServicePlay::selectAudioStream(int i)
1811 eDVBServicePMTHandler::program program;
1812 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1814 if (h.getProgramInfo(program))
1817 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1825 stream = program.defaultAudioStream;
1827 int apid = -1, apidtype = -1;
1829 if (((unsigned int)stream) < program.audioStreams.size())
1831 apid = program.audioStreams[stream].pid;
1832 apidtype = program.audioStreams[stream].type;
1835 m_current_audio_pid = apid;
1837 if (m_decoder->setAudioPID(apid, apidtype))
1839 eDebug("set audio pid failed");
1843 /* 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 */
1844 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1847 ePtr<iDVBDemux> data_demux;
1848 if (!h.getDataDemux(data_demux))
1850 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1851 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1855 /* if we decided that we need one, update the pid */
1857 m_rds_decoder->start(apid);
1859 /* store new pid as default only when:
1860 a.) we have an entry in the service db for the current service,
1861 b.) we are not playing back something,
1862 c.) we are not selecting the default entry. (we wouldn't change
1863 anything in the best case, or destroy the default setting in
1864 case the real default is not yet available.)
1866 if (m_dvb_service && !m_is_pvr && ((i != -1)
1867 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1869 if (apidtype == eDVBAudio::aMPEG)
1871 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1872 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1876 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1877 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1881 h.resetCachedProgram();
1886 int eDVBServicePlay::getCurrentChannel()
1888 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1891 RESULT eDVBServicePlay::selectChannel(int i)
1893 if (i < LEFT || i > RIGHT || i == STEREO)
1896 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1898 m_decoder->setAudioChannel(i);
1902 std::string eDVBServicePlay::getText(int x)
1908 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1910 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1915 void eDVBServicePlay::rdsDecoderEvent(int what)
1919 case eDVBRdsDecoder::RadioTextChanged:
1920 m_event((iPlayableService*)this, evUpdatedRadioText);
1922 case eDVBRdsDecoder::RtpTextChanged:
1923 m_event((iPlayableService*)this, evUpdatedRtpText);
1925 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1926 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1928 case eDVBRdsDecoder::RecvRassSlidePic:
1929 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1934 void eDVBServicePlay::showRassSlidePicture()
1940 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1941 if (rass_slide_pic.length())
1942 m_decoder->showSinglePic(rass_slide_pic.c_str());
1944 eDebug("empty filename for rass slide picture received!!");
1947 eDebug("no MPEG Decoder to show iframes avail");
1950 eDebug("showRassSlidePicture called.. but not decoder");
1953 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1959 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1960 if (rass_interactive_pic.length())
1961 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1963 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1966 eDebug("no MPEG Decoder to show iframes avail");
1969 eDebug("showRassInteractivePic called.. but not decoder");
1972 ePyObject eDVBServicePlay::getRassInteractiveMask()
1975 return m_rds_decoder->getRassPictureMask();
1979 int eDVBServiceBase::getFrontendInfo(int w)
1981 eUsePtr<iDVBChannel> channel;
1982 if(m_service_handler.getChannel(channel))
1984 ePtr<iDVBFrontend> fe;
1985 if(channel->getFrontend(fe))
1987 return fe->readFrontendData(w);
1990 PyObject *eDVBServiceBase::getFrontendData()
1992 ePyObject ret = PyDict_New();
1995 eUsePtr<iDVBChannel> channel;
1996 if(!m_service_handler.getChannel(channel))
1998 ePtr<iDVBFrontend> fe;
1999 if(!channel->getFrontend(fe))
2000 fe->getFrontendData(ret);
2008 PyObject *eDVBServiceBase::getFrontendStatus()
2010 ePyObject ret = PyDict_New();
2013 eUsePtr<iDVBChannel> channel;
2014 if(!m_service_handler.getChannel(channel))
2016 ePtr<iDVBFrontend> fe;
2017 if(!channel->getFrontend(fe))
2018 fe->getFrontendStatus(ret);
2026 PyObject *eDVBServiceBase::getTransponderData(bool original)
2028 ePyObject ret = PyDict_New();
2031 eUsePtr<iDVBChannel> channel;
2032 if(!m_service_handler.getChannel(channel))
2034 ePtr<iDVBFrontend> fe;
2035 if(!channel->getFrontend(fe))
2037 fe->getTransponderData(ret, original);
2038 ePtr<iDVBFrontendParameters> feparm;
2039 channel->getCurrentFrontendParameters(feparm);
2042 eDVBFrontendParametersSatellite osat;
2043 if (!feparm->getDVBS(osat))
2045 void PutToDict(ePyObject &, const char*, long);
2046 void PutToDict(ePyObject &, const char*, const char*);
2047 PutToDict(ret, "orbital_position", osat.orbital_position);
2048 const char *tmp = "UNKNOWN";
2049 switch(osat.polarisation)
2051 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2052 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2053 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2054 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2057 PutToDict(ret, "polarization", tmp);
2068 PyObject *eDVBServiceBase::getAll(bool original)
2070 ePyObject ret = getTransponderData(original);
2073 eUsePtr<iDVBChannel> channel;
2074 if(!m_service_handler.getChannel(channel))
2076 ePtr<iDVBFrontend> fe;
2077 if(!channel->getFrontend(fe))
2079 fe->getFrontendData(ret);
2080 fe->getFrontendStatus(ret);
2087 int eDVBServicePlay::getNumberOfSubservices()
2089 ePtr<eServiceEvent> evt;
2090 if (!m_event_handler.getEvent(evt, 0))
2091 return evt->getNumOfLinkageServices();
2095 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2097 ePtr<eServiceEvent> evt;
2098 if (!m_event_handler.getEvent(evt, 0))
2100 if (!evt->getLinkageService(sub, m_reference, n))
2103 sub.type=eServiceReference::idInvalid;
2107 RESULT eDVBServicePlay::startTimeshift()
2109 ePtr<iDVBDemux> demux;
2111 eDebug("Start timeshift!");
2113 if (m_timeshift_enabled)
2116 /* start recording with the data demux. */
2117 if (m_service_handler.getDataDemux(demux))
2120 demux->createTSRecorder(m_record);
2124 char templ[]=TSPATH "/timeshift.XXXXXX";
2125 m_timeshift_fd = mkstemp(templ);
2126 m_timeshift_file = templ;
2128 eDebug("recording to %s", templ);
2130 if (m_timeshift_fd < 0)
2136 m_record->setTargetFD(m_timeshift_fd);
2138 m_timeshift_enabled = 1;
2140 updateTimeshiftPids();
2146 RESULT eDVBServicePlay::stopTimeshift()
2148 if (!m_timeshift_enabled)
2153 m_timeshift_enabled = 0;
2158 close(m_timeshift_fd);
2159 eDebug("remove timeshift file");
2160 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2165 int eDVBServicePlay::isTimeshiftActive()
2167 return m_timeshift_enabled && m_timeshift_active;
2170 RESULT eDVBServicePlay::activateTimeshift()
2172 if (!m_timeshift_enabled)
2175 if (!m_timeshift_active)
2177 switchToTimeshift();
2184 PyObject *eDVBServicePlay::getCutList()
2186 ePyObject list = PyList_New(0);
2188 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2190 ePyObject tuple = PyTuple_New(2);
2191 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2192 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2193 PyList_Append(list, tuple);
2200 void eDVBServicePlay::setCutList(ePyObject list)
2202 if (!PyList_Check(list))
2204 int size = PyList_Size(list);
2207 m_cue_entries.clear();
2209 for (i=0; i<size; ++i)
2211 ePyObject tuple = PyList_GET_ITEM(list, i);
2212 if (!PyTuple_Check(tuple))
2214 eDebug("non-tuple in cutlist");
2217 if (PyTuple_Size(tuple) != 2)
2219 eDebug("cutlist entries need to be a 2-tuple");
2222 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2223 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2225 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2228 pts_t pts = PyLong_AsLongLong(ppts);
2229 int type = PyInt_AsLong(ptype);
2230 m_cue_entries.insert(cueEntry(pts, type));
2231 eDebug("adding %08llx, %d", pts, type);
2233 m_cuesheet_changed = 1;
2235 cutlistToCuesheet();
2236 m_event((iPlayableService*)this, evCuesheetChanged);
2239 void eDVBServicePlay::setCutListEnable(int enable)
2241 m_cutlist_enabled = enable;
2242 cutlistToCuesheet();
2245 void eDVBServicePlay::updateTimeshiftPids()
2250 eDVBServicePMTHandler::program program;
2251 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2253 if (h.getProgramInfo(program))
2257 std::set<int> pids_to_record;
2258 pids_to_record.insert(0); // PAT
2259 if (program.pmtPid != -1)
2260 pids_to_record.insert(program.pmtPid); // PMT
2262 if (program.textPid != -1)
2263 pids_to_record.insert(program.textPid); // Videotext
2265 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2266 i(program.videoStreams.begin());
2267 i != program.videoStreams.end(); ++i)
2268 pids_to_record.insert(i->pid);
2270 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2271 i(program.audioStreams.begin());
2272 i != program.audioStreams.end(); ++i)
2273 pids_to_record.insert(i->pid);
2275 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2276 i(program.subtitleStreams.begin());
2277 i != program.subtitleStreams.end(); ++i)
2278 pids_to_record.insert(i->pid);
2280 std::set<int> new_pids, obsolete_pids;
2282 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2283 m_pids_active.begin(), m_pids_active.end(),
2284 std::inserter(new_pids, new_pids.begin()));
2286 std::set_difference(
2287 m_pids_active.begin(), m_pids_active.end(),
2288 pids_to_record.begin(), pids_to_record.end(),
2289 std::inserter(new_pids, new_pids.begin())
2292 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2293 m_record->addPID(*i);
2295 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2296 m_record->removePID(*i);
2300 void eDVBServicePlay::switchToLive()
2302 if (!m_timeshift_active)
2308 m_teletext_parser = 0;
2310 m_subtitle_parser = 0;
2311 m_new_dvb_subtitle_page_connection = 0;
2312 m_new_subtitle_page_connection = 0;
2313 m_rds_decoder_event_connection = 0;
2314 m_video_event_connection = 0;
2316 /* free the timeshift service handler, we need the resources */
2317 m_service_handler_timeshift.free();
2318 m_timeshift_active = 0;
2320 m_event((iPlayableService*)this, evSeekableStatusChanged);
2325 void eDVBServicePlay::switchToTimeshift()
2327 if (m_timeshift_active)
2332 m_teletext_parser = 0;
2334 m_subtitle_parser = 0;
2335 m_new_subtitle_page_connection = 0;
2336 m_new_dvb_subtitle_page_connection = 0;
2337 m_rds_decoder_event_connection = 0;
2338 m_video_event_connection = 0;
2340 m_timeshift_active = 1;
2342 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2343 r.path = m_timeshift_file;
2345 m_cue = new eCueSheet();
2346 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2348 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2350 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2352 m_event((iPlayableService*)this, evSeekableStatusChanged);
2355 void eDVBServicePlay::updateDecoder()
2357 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2359 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2361 eDVBServicePMTHandler::program program;
2362 if (h.getProgramInfo(program))
2363 eDebug("getting program info failed.");
2366 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2367 if (!program.videoStreams.empty())
2369 eDebugNoNewLine(" (");
2370 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2371 i(program.videoStreams.begin());
2372 i != program.videoStreams.end(); ++i)
2379 if (i != program.videoStreams.begin())
2380 eDebugNoNewLine(", ");
2381 eDebugNoNewLine("%04x", i->pid);
2383 eDebugNoNewLine(")");
2385 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2386 if (!program.audioStreams.empty())
2388 eDebugNoNewLine(" (");
2389 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2390 i(program.audioStreams.begin());
2391 i != program.audioStreams.end(); ++i)
2393 if (i != program.audioStreams.begin())
2394 eDebugNoNewLine(", ");
2395 eDebugNoNewLine("%04x", i->pid);
2397 eDebugNoNewLine(")");
2399 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2400 pcrpid = program.pcrPid;
2401 eDebug(", and the text pid is %04x", program.textPid);
2402 tpid = program.textPid;
2407 h.getDecodeDemux(m_decode_demux);
2410 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2412 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2413 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2414 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2415 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2416 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2419 m_teletext_parser = 0;
2420 m_subtitle_parser = 0;
2424 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2431 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2432 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2433 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2435 else // subservice or recording
2437 eServiceReferenceDVB ref;
2438 m_service_handler.getServiceReference(ref);
2439 eServiceReferenceDVB parent = ref.getParentServiceReference();
2444 ePtr<eDVBResourceManager> res_mgr;
2445 if (!eDVBResourceManager::getInstance(res_mgr))
2447 ePtr<iDVBChannelList> db;
2448 if (!res_mgr->getChannelList(db))
2450 ePtr<eDVBService> origService;
2451 if (!db->getService(parent, origService))
2453 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2454 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2460 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2461 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2463 m_decoder->setVideoPID(vpid, vpidtype);
2464 selectAudioStream();
2466 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2467 m_decoder->setSyncPCR(pcrpid);
2469 m_decoder->setSyncPCR(-1);
2471 m_decoder->setTextPID(tpid);
2473 m_teletext_parser->start(program.textPid);
2476 m_decoder->setTrickmode(1);
2479 m_decoder->preroll();
2483 if (vpid > 0 && vpid < 0x2000)
2487 std::string radio_pic;
2488 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2489 m_decoder->setRadioPic(radio_pic);
2492 m_decoder->setAudioChannel(achannel);
2494 /* don't worry about non-existing services, nor pvr services */
2495 if (m_dvb_service && !m_is_pvr)
2497 /* (audio pid will be set in selectAudioTrack */
2498 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2499 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2500 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2501 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2504 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2507 void eDVBServicePlay::loadCuesheet()
2509 std::string filename = m_reference.path + ".cuts";
2511 m_cue_entries.clear();
2513 FILE *f = fopen(filename.c_str(), "rb");
2517 eDebug("loading cuts..");
2520 unsigned long long where;
2523 if (!fread(&where, sizeof(where), 1, f))
2525 if (!fread(&what, sizeof(what), 1, f))
2528 #if BYTE_ORDER == LITTLE_ENDIAN
2529 where = bswap_64(where);
2536 m_cue_entries.insert(cueEntry(where, what));
2539 eDebug("%d entries", m_cue_entries.size());
2541 eDebug("cutfile not found!");
2543 m_cuesheet_changed = 0;
2544 cutlistToCuesheet();
2545 m_event((iPlayableService*)this, evCuesheetChanged);
2548 void eDVBServicePlay::saveCuesheet()
2550 std::string filename = m_reference.path + ".cuts";
2552 FILE *f = fopen(filename.c_str(), "wb");
2556 unsigned long long where;
2559 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2561 #if BYTE_ORDER == BIG_ENDIAN
2564 where = bswap_64(i->where);
2566 what = htonl(i->what);
2567 fwrite(&where, sizeof(where), 1, f);
2568 fwrite(&what, sizeof(what), 1, f);
2574 m_cuesheet_changed = 0;
2577 void eDVBServicePlay::cutlistToCuesheet()
2581 eDebug("no cue sheet");
2586 if (!m_cutlist_enabled)
2588 m_cue->commitSpans();
2589 eDebug("cutlists were disabled");
2593 pts_t in = 0, out = 0, length = 0;
2597 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2601 if (i == m_cue_entries.end())
2604 if (i->what == 0) /* in */
2608 } else if (i->what == 1) /* out */
2610 else /* mark (2) or last play position (3) */
2627 m_cue->addSourceSpan(in, out);
2631 if (i == m_cue_entries.end())
2634 m_cue->commitSpans();
2637 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2639 if (m_subtitle_widget)
2640 disableSubtitles(parent);
2643 int tuplesize = PyTuple_Size(tuple);
2646 if (!PyTuple_Check(tuple))
2652 entry = PyTuple_GET_ITEM(tuple, 0);
2654 if (!PyInt_Check(entry))
2657 type = PyInt_AsLong(entry);
2659 if (type == 1) // teletext subtitles
2661 int page, magazine, pid;
2665 if (!m_teletext_parser)
2667 eDebug("enable teletext subtitles.. no parser !!!");
2671 entry = PyTuple_GET_ITEM(tuple, 1);
2672 if (!PyInt_Check(entry))
2674 pid = PyInt_AsLong(entry);
2676 entry = PyTuple_GET_ITEM(tuple, 2);
2677 if (!PyInt_Check(entry))
2679 page = PyInt_AsLong(entry);
2681 entry = PyTuple_GET_ITEM(tuple, 3);
2682 if (!PyInt_Check(entry))
2684 magazine = PyInt_AsLong(entry);
2686 m_subtitle_widget = new eSubtitleWidget(parent);
2687 m_subtitle_widget->resize(parent->size()); /* full size */
2688 m_teletext_parser->setPageAndMagazine(page, magazine);
2690 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2694 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2695 if (!m_subtitle_parser)
2697 eDebug("enable dvb subtitles.. no parser !!!");
2703 entry = PyTuple_GET_ITEM(tuple, 1);
2704 if (!PyInt_Check(entry))
2706 pid = PyInt_AsLong(entry);
2708 entry = PyTuple_GET_ITEM(tuple, 2);
2709 if (!PyInt_Check(entry))
2711 composition_page_id = PyInt_AsLong(entry);
2713 entry = PyTuple_GET_ITEM(tuple, 3);
2714 if (!PyInt_Check(entry))
2716 ancillary_page_id = PyInt_AsLong(entry);
2718 m_subtitle_widget = new eSubtitleWidget(parent);
2719 m_subtitle_widget->resize(parent->size()); /* full size */
2720 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2722 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2728 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2729 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2730 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2734 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2736 delete m_subtitle_widget;
2737 m_subtitle_widget = 0;
2738 if (m_subtitle_parser)
2740 m_subtitle_parser->stop();
2741 m_dvb_subtitle_pages.clear();
2743 if (m_teletext_parser)
2745 m_teletext_parser->setPageAndMagazine(-1, -1);
2746 m_subtitle_pages.clear();
2749 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2753 PyObject *eDVBServicePlay::getCachedSubtitle()
2757 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2760 unsigned int data = (unsigned int)tmp;
2761 int pid = (data&0xFFFF0000)>>16;
2762 ePyObject tuple = PyTuple_New(4);
2763 eDVBServicePMTHandler::program program;
2764 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2765 if (!h.getProgramInfo(program))
2767 if (program.textPid==pid) // teletext
2768 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2770 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2771 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2772 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2773 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2781 PyObject *eDVBServicePlay::getSubtitleList()
2783 if (!m_teletext_parser)
2786 ePyObject l = PyList_New(0);
2787 std::set<int> added_ttx_pages;
2789 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2790 m_teletext_parser->m_found_subtitle_pages;
2792 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2793 eDVBServicePMTHandler::program program;
2794 if (h.getProgramInfo(program))
2795 eDebug("getting program info failed.");
2798 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2799 it != program.subtitleStreams.end(); ++it)
2801 switch(it->subtitling_type)
2803 case 0x01: // ebu teletext subtitles
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(it->language_code.c_str()));
2816 PyList_Append(l, tuple);
2818 added_ttx_pages.insert(hash);
2823 case 0x20 ... 0x23: // dvb subtitles
2825 ePyObject tuple = PyTuple_New(5);
2826 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2827 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2828 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2829 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2830 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2831 PyList_Insert(l, 0, tuple);
2839 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2840 it != subs.end(); ++it)
2842 int page_number = it->teletext_page_number & 0xFF;
2843 int magazine_number = it->teletext_magazine_number & 7;
2844 int hash = magazine_number << 8 | page_number;
2845 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2847 ePyObject tuple = PyTuple_New(5);
2848 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2849 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2850 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2851 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2852 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2853 PyList_Append(l, tuple);
2861 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2863 if (m_subtitle_widget)
2867 m_decoder->getPTS(0, pos);
2868 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2869 m_subtitle_pages.push_back(page);
2870 checkSubtitleTiming();
2874 void eDVBServicePlay::checkSubtitleTiming()
2876 eDebug("checkSubtitleTiming");
2877 if (!m_subtitle_widget)
2881 enum { TELETEXT, DVB } type;
2882 eDVBTeletextSubtitlePage page;
2883 eDVBSubtitlePage dvb_page;
2885 if (!m_subtitle_pages.empty())
2887 page = m_subtitle_pages.front();
2889 show_time = page.m_pts;
2891 else if (!m_dvb_subtitle_pages.empty())
2893 dvb_page = m_dvb_subtitle_pages.front();
2895 show_time = dvb_page.m_show_time;
2903 m_decoder->getPTS(0, pos);
2905 eDebug("%lld %lld", pos, show_time);
2906 int diff = show_time - pos;
2909 eDebug("[late (%d ms)]", -diff / 90);
2912 // if (diff > 900000)
2914 // eDebug("[invalid]");
2920 if (type == TELETEXT)
2922 eDebug("display teletext subtitle page %lld", show_time);
2923 m_subtitle_widget->setPage(page);
2924 m_subtitle_pages.pop_front();
2928 eDebug("display dvb subtitle Page %lld", show_time);
2929 m_subtitle_widget->setPage(dvb_page);
2930 m_dvb_subtitle_pages.pop_front();
2934 eDebug("start subtitle delay %d", diff / 90);
2935 m_subtitle_sync_timer->start(diff / 90, 1);
2941 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2943 if (m_subtitle_widget)
2947 m_decoder->getPTS(0, pos);
2948 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2949 m_dvb_subtitle_pages.push_back(p);
2950 checkSubtitleTiming();
2954 int eDVBServicePlay::getAC3Delay()
2957 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2959 return m_decoder->getAC3Delay();
2964 int eDVBServicePlay::getPCMDelay()
2967 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2969 return m_decoder->getPCMDelay();
2974 void eDVBServicePlay::setAC3Delay(int delay)
2977 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2979 m_decoder->setAC3Delay(delay);
2982 void eDVBServicePlay::setPCMDelay(int delay)
2985 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2987 m_decoder->setPCMDelay(delay);
2990 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2992 memcpy(&m_videoEventData, &event, sizeof(event));
2993 switch(event.type) {
2994 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2995 m_event((iPlayableService*)this, evVideoSizeChanged);
2997 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2998 m_event((iPlayableService*)this, evVideoFramerateChanged);
3000 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3001 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3008 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3014 PyObject *eDVBServicePlay::getStreamingData()
3016 eDVBServicePMTHandler::program program;
3017 if (m_service_handler.getProgramInfo(program))
3023 PyObject *r = program.createPythonObject();
3024 ePtr<iDVBDemux> demux;
3025 if (!m_service_handler.getDataDemux(demux))
3028 demux->getCADemuxID(demux_id);
3030 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
3037 DEFINE_REF(eDVBServicePlay)
3039 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3043 case iServiceInformation::sTransponderData:
3044 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3048 return iStaticServiceInformation::getInfoObject(ref, w);
3051 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");