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, bool simulate)
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, simulate);
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)
1290 return m_decoder->setSlowMotion(ratio);
1295 RESULT eDVBServicePlay::setFastForward(int ratio)
1297 int skipmode, ffratio;
1303 } else if (ratio > 0)
1311 } else // if (ratio < 0)
1317 if (m_skipmode != skipmode)
1319 eDebug("setting cue skipmode to %d", skipmode);
1321 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1324 m_skipmode = skipmode;
1329 return m_decoder->setFastForward(ffratio);
1332 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1334 if (m_is_pvr || m_timeshift_enabled)
1344 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1345 RESULT eDVBServicePlay::getLength(pts_t &len)
1347 ePtr<iDVBPVRChannel> pvr_channel;
1349 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1352 return pvr_channel->getLength(len);
1355 RESULT eDVBServicePlay::pause()
1357 if (!m_is_paused && m_decoder)
1360 return m_decoder->freeze(0);
1365 RESULT eDVBServicePlay::unpause()
1367 if (m_is_paused && m_decoder)
1370 return m_decoder->unfreeze();
1375 RESULT eDVBServicePlay::seekTo(pts_t to)
1377 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1379 if (!m_decode_demux)
1382 ePtr<iDVBPVRChannel> pvr_channel;
1384 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1390 m_cue->seekTo(0, to);
1391 m_dvb_subtitle_pages.clear();
1392 m_subtitle_pages.clear();
1397 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1399 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1401 if (!m_decode_demux)
1404 ePtr<iDVBPVRChannel> pvr_channel;
1406 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1411 /* HACK until we have skip-AP api */
1412 if ((to > 0) && (to < 100))
1420 m_cue->seekTo(mode, to);
1421 m_dvb_subtitle_pages.clear();
1422 m_subtitle_pages.clear();
1426 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1428 ePtr<iDVBPVRChannel> pvr_channel;
1430 if (!m_decode_demux)
1433 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1438 /* if there is a decoder, use audio or video PTS */
1441 r = m_decoder->getPTS(0, pos);
1447 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1450 RESULT eDVBServicePlay::setTrickmode(int trick)
1453 m_decoder->setTrickmode(trick);
1457 RESULT eDVBServicePlay::isCurrentlySeekable()
1459 return m_is_pvr || m_timeshift_active;
1462 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1468 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1474 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1480 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1486 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1492 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1495 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1496 (m_timeshift_enabled || !m_is_pvr))
1498 if (!m_timeshift_enabled)
1500 /* we need enough diskspace */
1502 if (statfs(TSPATH "/.", &fs) < 0)
1504 eDebug("statfs failed!");
1508 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1510 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1520 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1531 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1537 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1543 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1549 RESULT eDVBServicePlay::getName(std::string &name)
1553 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1554 return i->getName(m_reference, name);
1558 m_dvb_service->getName(m_reference, name);
1562 else if (!m_reference.name.empty())
1563 eStaticServiceDVBInformation().getName(m_reference, name);
1565 name = "DVB service";
1569 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1571 return m_event_handler.getEvent(evt, nownext);
1574 static int readMpegProc(char *str, int decoder)
1578 sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
1579 FILE *f = fopen(tmp, "r");
1582 fscanf(f, "%x", &val);
1588 int eDVBServicePlay::getInfo(int w)
1590 eDVBServicePMTHandler::program program;
1593 return resIsPyObject;
1595 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1597 int no_program_info = 0;
1599 if (h.getProgramInfo(program))
1600 no_program_info = 1;
1604 #if HAVE_DVB_API_VERSION >= 3
1606 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1607 return m_videoEventData.height;
1609 return readMpegProc("yres", !m_is_primary);
1611 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1612 return m_videoEventData.width;
1614 return readMpegProc("xres", !m_is_primary);
1616 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventFrameRateChanged)
1617 return m_videoEventData.framerate;
1619 return readMpegProc("framerate", !m_is_primary);
1621 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventProgressiveChanged)
1622 return m_videoEventData.progressive;
1623 return readMpegProc("progressive", !m_is_primary);
1625 #warning "FIXMEE implement sFrameRate, sProgressive, sVideoHeight, sVideoWidth for old DVB API"
1630 #if HAVE_DVB_API_VERSION >= 3
1631 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1632 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1633 else if ((val=readMpegProc("aspect", !m_is_primary)) != -1)
1637 #warning "FIXMEE implement sAspect for old DVB API"
1639 if (no_program_info)
1641 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1643 ePtr<eServiceEvent> evt;
1644 if (!m_event_handler.getEvent(evt, 0))
1646 ePtr<eComponentData> data;
1647 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1649 if ( data->getStreamContent() == 1 )
1651 switch(data->getComponentType())
1654 case 1: // 4:3 SD PAL
1656 case 3: // 16:9 SD PAL
1657 case 4: // > 16:9 PAL
1658 case 5: // 4:3 SD NTSC
1660 case 7: // 16:9 SD NTSC
1661 case 8: // > 16:9 NTSC
1664 case 9: // 4:3 HD PAL
1666 case 0xB: // 16:9 HD PAL
1667 case 0xC: // > 16:9 HD PAL
1668 case 0xD: // 4:3 HD NTSC
1670 case 0xF: // 16:9 HD NTSC
1671 case 0x10: // > 16:9 HD PAL
1672 return data->getComponentType();
1680 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1681 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1682 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1683 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1684 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1685 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1686 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1687 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1688 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1689 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1690 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1691 case sProvider: if (!m_dvb_service) return -1; return -2;
1692 case sServiceref: return resIsString;
1693 case sDVBState: return m_tune_state;
1699 std::string eDVBServicePlay::getInfoString(int w)
1704 if (!m_dvb_service) return "";
1705 return m_dvb_service->m_provider_name;
1707 return m_reference.toString();
1711 return iServiceInformation::getInfoString(w);
1714 PyObject *eDVBServicePlay::getInfoObject(int w)
1719 return m_service_handler.getCaIds();
1720 case sTransponderData:
1721 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1725 return iServiceInformation::getInfoObject(w);
1728 int eDVBServicePlay::getNumberOfTracks()
1730 eDVBServicePMTHandler::program program;
1731 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1732 if (h.getProgramInfo(program))
1734 return program.audioStreams.size();
1737 int eDVBServicePlay::getCurrentTrack()
1739 eDVBServicePMTHandler::program program;
1740 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1741 if (h.getProgramInfo(program))
1744 int max = program.audioStreams.size();
1747 for (i = 0; i < max; ++i)
1748 if (program.audioStreams[i].pid == m_current_audio_pid)
1754 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1756 int ret = selectAudioStream(i);
1758 if (m_decoder->start())
1764 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1766 eDVBServicePMTHandler::program program;
1767 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1769 if (h.getProgramInfo(program))
1772 if (i >= program.audioStreams.size())
1775 info.m_pid = program.audioStreams[i].pid;
1777 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1778 info.m_description = "MPEG";
1779 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1780 info.m_description = "AC3";
1781 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1782 info.m_description = "AAC";
1783 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1784 info.m_description = "DTS";
1786 info.m_description = "???";
1788 if (program.audioStreams[i].component_tag != -1)
1790 ePtr<eServiceEvent> evt;
1791 if (!m_event_handler.getEvent(evt, 0))
1793 ePtr<eComponentData> data;
1794 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1795 info.m_language = data->getText();
1799 if (info.m_language.empty())
1800 info.m_language = program.audioStreams[i].language_code;
1805 int eDVBServicePlay::selectAudioStream(int i)
1807 eDVBServicePMTHandler::program program;
1808 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1810 if (h.getProgramInfo(program))
1813 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1821 stream = program.defaultAudioStream;
1823 int apid = -1, apidtype = -1;
1825 if (((unsigned int)stream) < program.audioStreams.size())
1827 apid = program.audioStreams[stream].pid;
1828 apidtype = program.audioStreams[stream].type;
1831 m_current_audio_pid = apid;
1833 if (m_decoder->setAudioPID(apid, apidtype))
1835 eDebug("set audio pid failed");
1839 /* 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 */
1840 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1843 ePtr<iDVBDemux> data_demux;
1844 if (!h.getDataDemux(data_demux))
1846 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1847 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1851 /* if we decided that we need one, update the pid */
1853 m_rds_decoder->start(apid);
1855 /* store new pid as default only when:
1856 a.) we have an entry in the service db for the current service,
1857 b.) we are not playing back something,
1858 c.) we are not selecting the default entry. (we wouldn't change
1859 anything in the best case, or destroy the default setting in
1860 case the real default is not yet available.)
1862 if (m_dvb_service && !m_is_pvr && ((i != -1)
1863 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1865 if (apidtype == eDVBAudio::aMPEG)
1867 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1868 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1872 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1873 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1877 h.resetCachedProgram();
1882 int eDVBServicePlay::getCurrentChannel()
1884 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1887 RESULT eDVBServicePlay::selectChannel(int i)
1889 if (i < LEFT || i > RIGHT || i == STEREO)
1892 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1894 m_decoder->setAudioChannel(i);
1898 std::string eDVBServicePlay::getText(int x)
1904 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1906 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1911 void eDVBServicePlay::rdsDecoderEvent(int what)
1915 case eDVBRdsDecoder::RadioTextChanged:
1916 m_event((iPlayableService*)this, evUpdatedRadioText);
1918 case eDVBRdsDecoder::RtpTextChanged:
1919 m_event((iPlayableService*)this, evUpdatedRtpText);
1921 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1922 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1924 case eDVBRdsDecoder::RecvRassSlidePic:
1925 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1930 void eDVBServicePlay::showRassSlidePicture()
1936 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1937 if (rass_slide_pic.length())
1938 m_decoder->showSinglePic(rass_slide_pic.c_str());
1940 eDebug("empty filename for rass slide picture received!!");
1943 eDebug("no MPEG Decoder to show iframes avail");
1946 eDebug("showRassSlidePicture called.. but not decoder");
1949 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1955 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1956 if (rass_interactive_pic.length())
1957 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1959 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1962 eDebug("no MPEG Decoder to show iframes avail");
1965 eDebug("showRassInteractivePic called.. but not decoder");
1968 ePyObject eDVBServicePlay::getRassInteractiveMask()
1971 return m_rds_decoder->getRassPictureMask();
1975 int eDVBServiceBase::getFrontendInfo(int w)
1977 eUsePtr<iDVBChannel> channel;
1978 if(m_service_handler.getChannel(channel))
1980 ePtr<iDVBFrontend> fe;
1981 if(channel->getFrontend(fe))
1983 return fe->readFrontendData(w);
1986 PyObject *eDVBServiceBase::getFrontendData()
1988 ePyObject ret = PyDict_New();
1991 eUsePtr<iDVBChannel> channel;
1992 if(!m_service_handler.getChannel(channel))
1994 ePtr<iDVBFrontend> fe;
1995 if(!channel->getFrontend(fe))
1996 fe->getFrontendData(ret);
2004 PyObject *eDVBServiceBase::getFrontendStatus()
2006 ePyObject ret = PyDict_New();
2009 eUsePtr<iDVBChannel> channel;
2010 if(!m_service_handler.getChannel(channel))
2012 ePtr<iDVBFrontend> fe;
2013 if(!channel->getFrontend(fe))
2014 fe->getFrontendStatus(ret);
2022 PyObject *eDVBServiceBase::getTransponderData(bool original)
2024 ePyObject ret = PyDict_New();
2027 eUsePtr<iDVBChannel> channel;
2028 if(!m_service_handler.getChannel(channel))
2030 ePtr<iDVBFrontend> fe;
2031 if(!channel->getFrontend(fe))
2033 fe->getTransponderData(ret, original);
2034 ePtr<iDVBFrontendParameters> feparm;
2035 channel->getCurrentFrontendParameters(feparm);
2038 eDVBFrontendParametersSatellite osat;
2039 if (!feparm->getDVBS(osat))
2041 void PutToDict(ePyObject &, const char*, long);
2042 void PutToDict(ePyObject &, const char*, const char*);
2043 PutToDict(ret, "orbital_position", osat.orbital_position);
2044 const char *tmp = "UNKNOWN";
2045 switch(osat.polarisation)
2047 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2048 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2049 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2050 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2053 PutToDict(ret, "polarization", tmp);
2064 PyObject *eDVBServiceBase::getAll(bool original)
2066 ePyObject ret = getTransponderData(original);
2069 eUsePtr<iDVBChannel> channel;
2070 if(!m_service_handler.getChannel(channel))
2072 ePtr<iDVBFrontend> fe;
2073 if(!channel->getFrontend(fe))
2075 fe->getFrontendData(ret);
2076 fe->getFrontendStatus(ret);
2083 int eDVBServicePlay::getNumberOfSubservices()
2085 ePtr<eServiceEvent> evt;
2086 if (!m_event_handler.getEvent(evt, 0))
2087 return evt->getNumOfLinkageServices();
2091 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2093 ePtr<eServiceEvent> evt;
2094 if (!m_event_handler.getEvent(evt, 0))
2096 if (!evt->getLinkageService(sub, m_reference, n))
2099 sub.type=eServiceReference::idInvalid;
2103 RESULT eDVBServicePlay::startTimeshift()
2105 ePtr<iDVBDemux> demux;
2107 eDebug("Start timeshift!");
2109 if (m_timeshift_enabled)
2112 /* start recording with the data demux. */
2113 if (m_service_handler.getDataDemux(demux))
2116 demux->createTSRecorder(m_record);
2120 char templ[]=TSPATH "/timeshift.XXXXXX";
2121 m_timeshift_fd = mkstemp(templ);
2122 m_timeshift_file = templ;
2124 eDebug("recording to %s", templ);
2126 if (m_timeshift_fd < 0)
2132 m_record->setTargetFD(m_timeshift_fd);
2134 m_timeshift_enabled = 1;
2136 updateTimeshiftPids();
2142 RESULT eDVBServicePlay::stopTimeshift()
2144 if (!m_timeshift_enabled)
2149 m_timeshift_enabled = 0;
2154 close(m_timeshift_fd);
2155 eDebug("remove timeshift file");
2156 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2161 int eDVBServicePlay::isTimeshiftActive()
2163 return m_timeshift_enabled && m_timeshift_active;
2166 RESULT eDVBServicePlay::activateTimeshift()
2168 if (!m_timeshift_enabled)
2171 if (!m_timeshift_active)
2173 switchToTimeshift();
2180 PyObject *eDVBServicePlay::getCutList()
2182 ePyObject list = PyList_New(0);
2184 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2186 ePyObject tuple = PyTuple_New(2);
2187 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2188 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2189 PyList_Append(list, tuple);
2196 void eDVBServicePlay::setCutList(ePyObject list)
2198 if (!PyList_Check(list))
2200 int size = PyList_Size(list);
2203 m_cue_entries.clear();
2205 for (i=0; i<size; ++i)
2207 ePyObject tuple = PyList_GET_ITEM(list, i);
2208 if (!PyTuple_Check(tuple))
2210 eDebug("non-tuple in cutlist");
2213 if (PyTuple_Size(tuple) != 2)
2215 eDebug("cutlist entries need to be a 2-tuple");
2218 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2219 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2221 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2224 pts_t pts = PyLong_AsLongLong(ppts);
2225 int type = PyInt_AsLong(ptype);
2226 m_cue_entries.insert(cueEntry(pts, type));
2227 eDebug("adding %08llx, %d", pts, type);
2229 m_cuesheet_changed = 1;
2231 cutlistToCuesheet();
2232 m_event((iPlayableService*)this, evCuesheetChanged);
2235 void eDVBServicePlay::setCutListEnable(int enable)
2237 m_cutlist_enabled = enable;
2238 cutlistToCuesheet();
2241 void eDVBServicePlay::updateTimeshiftPids()
2246 eDVBServicePMTHandler::program program;
2247 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2249 if (h.getProgramInfo(program))
2253 std::set<int> pids_to_record;
2254 pids_to_record.insert(0); // PAT
2255 if (program.pmtPid != -1)
2256 pids_to_record.insert(program.pmtPid); // PMT
2258 if (program.textPid != -1)
2259 pids_to_record.insert(program.textPid); // Videotext
2261 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2262 i(program.videoStreams.begin());
2263 i != program.videoStreams.end(); ++i)
2264 pids_to_record.insert(i->pid);
2266 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2267 i(program.audioStreams.begin());
2268 i != program.audioStreams.end(); ++i)
2269 pids_to_record.insert(i->pid);
2271 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2272 i(program.subtitleStreams.begin());
2273 i != program.subtitleStreams.end(); ++i)
2274 pids_to_record.insert(i->pid);
2276 std::set<int> new_pids, obsolete_pids;
2278 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2279 m_pids_active.begin(), m_pids_active.end(),
2280 std::inserter(new_pids, new_pids.begin()));
2282 std::set_difference(
2283 m_pids_active.begin(), m_pids_active.end(),
2284 pids_to_record.begin(), pids_to_record.end(),
2285 std::inserter(new_pids, new_pids.begin())
2288 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2289 m_record->addPID(*i);
2291 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2292 m_record->removePID(*i);
2296 void eDVBServicePlay::switchToLive()
2298 if (!m_timeshift_active)
2304 m_teletext_parser = 0;
2306 m_subtitle_parser = 0;
2307 m_new_dvb_subtitle_page_connection = 0;
2308 m_new_subtitle_page_connection = 0;
2309 m_rds_decoder_event_connection = 0;
2310 m_video_event_connection = 0;
2312 /* free the timeshift service handler, we need the resources */
2313 m_service_handler_timeshift.free();
2314 m_timeshift_active = 0;
2316 m_event((iPlayableService*)this, evSeekableStatusChanged);
2321 void eDVBServicePlay::switchToTimeshift()
2323 if (m_timeshift_active)
2328 m_teletext_parser = 0;
2330 m_subtitle_parser = 0;
2331 m_new_subtitle_page_connection = 0;
2332 m_new_dvb_subtitle_page_connection = 0;
2333 m_rds_decoder_event_connection = 0;
2334 m_video_event_connection = 0;
2336 m_timeshift_active = 1;
2338 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2339 r.path = m_timeshift_file;
2341 m_cue = new eCueSheet();
2342 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2344 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2346 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2348 m_event((iPlayableService*)this, evSeekableStatusChanged);
2351 void eDVBServicePlay::updateDecoder()
2353 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2355 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2357 eDVBServicePMTHandler::program program;
2358 if (h.getProgramInfo(program))
2359 eDebug("getting program info failed.");
2362 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2363 if (!program.videoStreams.empty())
2365 eDebugNoNewLine(" (");
2366 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2367 i(program.videoStreams.begin());
2368 i != program.videoStreams.end(); ++i)
2375 if (i != program.videoStreams.begin())
2376 eDebugNoNewLine(", ");
2377 eDebugNoNewLine("%04x", i->pid);
2379 eDebugNoNewLine(")");
2381 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2382 if (!program.audioStreams.empty())
2384 eDebugNoNewLine(" (");
2385 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2386 i(program.audioStreams.begin());
2387 i != program.audioStreams.end(); ++i)
2389 if (i != program.audioStreams.begin())
2390 eDebugNoNewLine(", ");
2391 eDebugNoNewLine("%04x", i->pid);
2393 eDebugNoNewLine(")");
2395 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2396 pcrpid = program.pcrPid;
2397 eDebug(", and the text pid is %04x", program.textPid);
2398 tpid = program.textPid;
2403 h.getDecodeDemux(m_decode_demux);
2406 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2408 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2409 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2410 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2411 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2412 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2415 m_teletext_parser = 0;
2416 m_subtitle_parser = 0;
2420 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2427 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2428 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2429 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2431 else // subservice or recording
2433 eServiceReferenceDVB ref;
2434 m_service_handler.getServiceReference(ref);
2435 eServiceReferenceDVB parent = ref.getParentServiceReference();
2440 ePtr<eDVBResourceManager> res_mgr;
2441 if (!eDVBResourceManager::getInstance(res_mgr))
2443 ePtr<iDVBChannelList> db;
2444 if (!res_mgr->getChannelList(db))
2446 ePtr<eDVBService> origService;
2447 if (!db->getService(parent, origService))
2449 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2450 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2456 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2457 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2459 m_decoder->setVideoPID(vpid, vpidtype);
2460 selectAudioStream();
2462 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2463 m_decoder->setSyncPCR(pcrpid);
2465 m_decoder->setSyncPCR(-1);
2467 m_decoder->setTextPID(tpid);
2469 m_teletext_parser->start(program.textPid);
2472 m_decoder->setTrickmode(1);
2475 m_decoder->preroll();
2479 if (vpid > 0 && vpid < 0x2000)
2483 std::string radio_pic;
2484 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2485 m_decoder->setRadioPic(radio_pic);
2488 m_decoder->setAudioChannel(achannel);
2490 /* don't worry about non-existing services, nor pvr services */
2491 if (m_dvb_service && !m_is_pvr)
2493 /* (audio pid will be set in selectAudioTrack */
2494 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2495 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2496 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2497 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2500 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2503 void eDVBServicePlay::loadCuesheet()
2505 std::string filename = m_reference.path + ".cuts";
2507 m_cue_entries.clear();
2509 FILE *f = fopen(filename.c_str(), "rb");
2513 eDebug("loading cuts..");
2516 unsigned long long where;
2519 if (!fread(&where, sizeof(where), 1, f))
2521 if (!fread(&what, sizeof(what), 1, f))
2524 #if BYTE_ORDER == LITTLE_ENDIAN
2525 where = bswap_64(where);
2532 m_cue_entries.insert(cueEntry(where, what));
2535 eDebug("%d entries", m_cue_entries.size());
2537 eDebug("cutfile not found!");
2539 m_cuesheet_changed = 0;
2540 cutlistToCuesheet();
2541 m_event((iPlayableService*)this, evCuesheetChanged);
2544 void eDVBServicePlay::saveCuesheet()
2546 std::string filename = m_reference.path + ".cuts";
2548 FILE *f = fopen(filename.c_str(), "wb");
2552 unsigned long long where;
2555 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2557 #if BYTE_ORDER == BIG_ENDIAN
2560 where = bswap_64(i->where);
2562 what = htonl(i->what);
2563 fwrite(&where, sizeof(where), 1, f);
2564 fwrite(&what, sizeof(what), 1, f);
2570 m_cuesheet_changed = 0;
2573 void eDVBServicePlay::cutlistToCuesheet()
2577 eDebug("no cue sheet");
2582 if (!m_cutlist_enabled)
2584 m_cue->commitSpans();
2585 eDebug("cutlists were disabled");
2589 pts_t in = 0, out = 0, length = 0;
2593 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2597 if (i == m_cue_entries.end())
2600 if (i->what == 0) /* in */
2604 } else if (i->what == 1) /* out */
2606 else /* mark (2) or last play position (3) */
2623 m_cue->addSourceSpan(in, out);
2627 if (i == m_cue_entries.end())
2630 m_cue->commitSpans();
2633 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2635 if (m_subtitle_widget)
2636 disableSubtitles(parent);
2639 int tuplesize = PyTuple_Size(tuple);
2642 if (!PyTuple_Check(tuple))
2648 entry = PyTuple_GET_ITEM(tuple, 0);
2650 if (!PyInt_Check(entry))
2653 type = PyInt_AsLong(entry);
2655 if (type == 1) // teletext subtitles
2657 int page, magazine, pid;
2661 if (!m_teletext_parser)
2663 eDebug("enable teletext subtitles.. no parser !!!");
2667 entry = PyTuple_GET_ITEM(tuple, 1);
2668 if (!PyInt_Check(entry))
2670 pid = PyInt_AsLong(entry);
2672 entry = PyTuple_GET_ITEM(tuple, 2);
2673 if (!PyInt_Check(entry))
2675 page = PyInt_AsLong(entry);
2677 entry = PyTuple_GET_ITEM(tuple, 3);
2678 if (!PyInt_Check(entry))
2680 magazine = PyInt_AsLong(entry);
2682 m_subtitle_widget = new eSubtitleWidget(parent);
2683 m_subtitle_widget->resize(parent->size()); /* full size */
2684 m_teletext_parser->setPageAndMagazine(page, magazine);
2686 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2690 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2691 if (!m_subtitle_parser)
2693 eDebug("enable dvb subtitles.. no parser !!!");
2699 entry = PyTuple_GET_ITEM(tuple, 1);
2700 if (!PyInt_Check(entry))
2702 pid = PyInt_AsLong(entry);
2704 entry = PyTuple_GET_ITEM(tuple, 2);
2705 if (!PyInt_Check(entry))
2707 composition_page_id = PyInt_AsLong(entry);
2709 entry = PyTuple_GET_ITEM(tuple, 3);
2710 if (!PyInt_Check(entry))
2712 ancillary_page_id = PyInt_AsLong(entry);
2714 m_subtitle_widget = new eSubtitleWidget(parent);
2715 m_subtitle_widget->resize(parent->size()); /* full size */
2716 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2718 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2724 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2725 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2726 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2730 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2732 delete m_subtitle_widget;
2733 m_subtitle_widget = 0;
2734 if (m_subtitle_parser)
2736 m_subtitle_parser->stop();
2737 m_dvb_subtitle_pages.clear();
2739 if (m_teletext_parser)
2741 m_teletext_parser->setPageAndMagazine(-1, -1);
2742 m_subtitle_pages.clear();
2745 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2749 PyObject *eDVBServicePlay::getCachedSubtitle()
2753 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2756 unsigned int data = (unsigned int)tmp;
2757 int pid = (data&0xFFFF0000)>>16;
2758 ePyObject tuple = PyTuple_New(4);
2759 eDVBServicePMTHandler::program program;
2760 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2761 if (!h.getProgramInfo(program))
2763 if (program.textPid==pid) // teletext
2764 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2766 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2767 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2768 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2769 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2777 PyObject *eDVBServicePlay::getSubtitleList()
2779 if (!m_teletext_parser)
2782 ePyObject l = PyList_New(0);
2783 std::set<int> added_ttx_pages;
2785 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2786 m_teletext_parser->m_found_subtitle_pages;
2788 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2789 eDVBServicePMTHandler::program program;
2790 if (h.getProgramInfo(program))
2791 eDebug("getting program info failed.");
2794 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2795 it != program.subtitleStreams.end(); ++it)
2797 switch(it->subtitling_type)
2799 case 0x01: // ebu teletext subtitles
2801 int page_number = it->teletext_page_number & 0xFF;
2802 int magazine_number = it->teletext_magazine_number & 7;
2803 int hash = magazine_number << 8 | page_number;
2804 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2806 ePyObject tuple = PyTuple_New(5);
2807 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2808 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2809 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2810 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2811 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2812 PyList_Append(l, tuple);
2814 added_ttx_pages.insert(hash);
2819 case 0x20 ... 0x23: // dvb subtitles
2821 ePyObject tuple = PyTuple_New(5);
2822 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2823 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2824 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2825 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2826 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2827 PyList_Insert(l, 0, tuple);
2835 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2836 it != subs.end(); ++it)
2838 int page_number = it->teletext_page_number & 0xFF;
2839 int magazine_number = it->teletext_magazine_number & 7;
2840 int hash = magazine_number << 8 | page_number;
2841 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2843 ePyObject tuple = PyTuple_New(5);
2844 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2845 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2846 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2847 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2848 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2849 PyList_Append(l, tuple);
2857 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2859 if (m_subtitle_widget)
2863 m_decoder->getPTS(0, pos);
2864 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2865 m_subtitle_pages.push_back(page);
2866 checkSubtitleTiming();
2870 void eDVBServicePlay::checkSubtitleTiming()
2872 eDebug("checkSubtitleTiming");
2873 if (!m_subtitle_widget)
2877 enum { TELETEXT, DVB } type;
2878 eDVBTeletextSubtitlePage page;
2879 eDVBSubtitlePage dvb_page;
2881 if (!m_subtitle_pages.empty())
2883 page = m_subtitle_pages.front();
2885 show_time = page.m_pts;
2887 else if (!m_dvb_subtitle_pages.empty())
2889 dvb_page = m_dvb_subtitle_pages.front();
2891 show_time = dvb_page.m_show_time;
2899 m_decoder->getPTS(0, pos);
2901 eDebug("%lld %lld", pos, show_time);
2902 int diff = show_time - pos;
2905 eDebug("[late (%d ms)]", -diff / 90);
2908 // if (diff > 900000)
2910 // eDebug("[invalid]");
2916 if (type == TELETEXT)
2918 eDebug("display teletext subtitle page %lld", show_time);
2919 m_subtitle_widget->setPage(page);
2920 m_subtitle_pages.pop_front();
2924 eDebug("display dvb subtitle Page %lld", show_time);
2925 m_subtitle_widget->setPage(dvb_page);
2926 m_dvb_subtitle_pages.pop_front();
2930 eDebug("start subtitle delay %d", diff / 90);
2931 m_subtitle_sync_timer->start(diff / 90, 1);
2937 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2939 if (m_subtitle_widget)
2943 m_decoder->getPTS(0, pos);
2944 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2945 m_dvb_subtitle_pages.push_back(p);
2946 checkSubtitleTiming();
2950 int eDVBServicePlay::getAC3Delay()
2953 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2955 return m_decoder->getAC3Delay();
2960 int eDVBServicePlay::getPCMDelay()
2963 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2965 return m_decoder->getPCMDelay();
2970 void eDVBServicePlay::setAC3Delay(int delay)
2973 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2975 m_decoder->setAC3Delay(delay);
2978 void eDVBServicePlay::setPCMDelay(int delay)
2981 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2983 m_decoder->setPCMDelay(delay);
2986 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2988 memcpy(&m_videoEventData, &event, sizeof(event));
2989 switch(event.type) {
2990 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2991 m_event((iPlayableService*)this, evVideoSizeChanged);
2993 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2994 m_event((iPlayableService*)this, evVideoFramerateChanged);
2996 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2997 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3004 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3010 PyObject *eDVBServicePlay::getStreamingData()
3012 eDVBServicePMTHandler::program program;
3013 if (m_service_handler.getProgramInfo(program))
3019 PyObject *r = program.createPythonObject();
3020 ePtr<iDVBDemux> demux;
3021 if (!m_service_handler.getDataDemux(demux))
3024 demux->getCADemuxID(demux_id);
3026 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
3033 DEFINE_REF(eDVBServicePlay)
3035 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3039 case iServiceInformation::sTransponderData:
3040 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3044 return iStaticServiceInformation::getInfoObject(ref, w);
3047 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");