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 class eStaticServiceDVBInformation: public iStaticServiceInformation
36 DECLARE_REF(eStaticServiceDVBInformation);
38 RESULT getName(const eServiceReference &ref, std::string &name);
39 int getLength(const eServiceReference &ref);
40 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41 PyObject *getInfoObject(const eServiceReference &ref, int);
44 DEFINE_REF(eStaticServiceDVBInformation);
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
48 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49 if ( !ref.name.empty() )
51 if (service.getParentTransportStreamID().get()) // linkage subservice
53 ePtr<iServiceHandler> service_center;
54 if (!eServiceCenter::getInstance(service_center))
56 eServiceReferenceDVB parent = service;
57 parent.setTransportStreamID( service.getParentTransportStreamID() );
58 parent.setServiceID( service.getParentServiceID() );
59 parent.setParentTransportStreamID(eTransportStreamID(0));
60 parent.setParentServiceID(eServiceID(0));
62 ePtr<iStaticServiceInformation> service_info;
63 if (!service_center->info(parent, service_info))
65 if (!service_info->getName(parent, name))
66 name=buildShortName(name) + " - ";
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
86 ePtr<eDVBResourceManager> res_mgr;
87 if ( eDVBResourceManager::getInstance( res_mgr ) )
88 eDebug("isPlayable... no res manager!!");
91 eDVBChannelID chid, chid_ignore;
92 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94 return res_mgr->canAllocateChannel(chid, chid_ignore);
99 static void PutToDict(ePyObject &dict, const char*key, long value)
101 ePyObject item = PyString_FromFormat("%d", value);
104 if (PyDict_SetItemString(dict, key, item))
105 eDebug("put %s to dict failed", key);
109 eDebug("could not create PyObject for %s", key);
112 extern void PutToDict(ePyObject &dict, const char*key, const char *value);
114 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
117 PutToDict(dict, "type", "Satellite");
118 PutToDict(dict, "frequency", feparm.frequency);
119 PutToDict(dict, "symbolrate", feparm.symbol_rate);
120 PutToDict(dict, "orbital position", feparm.orbital_position);
121 switch (feparm.inversion)
123 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
124 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
126 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
128 PutToDict(dict, "inversion", tmp);
131 case eDVBFrontendParametersSatellite::FEC::fNone: tmp="NONE"; break;
132 case eDVBFrontendParametersSatellite::FEC::f1_2: tmp="1/2"; break;
133 case eDVBFrontendParametersSatellite::FEC::f2_3: tmp="2/3"; break;
134 case eDVBFrontendParametersSatellite::FEC::f3_4: tmp="3/4"; break;
135 case eDVBFrontendParametersSatellite::FEC::f5_6: tmp="5/6"; break;
136 case eDVBFrontendParametersSatellite::FEC::f7_8: tmp="7/8"; break;
137 case eDVBFrontendParametersSatellite::FEC::f3_5: tmp="3/5"; break;
138 case eDVBFrontendParametersSatellite::FEC::f4_5: tmp="4/5"; break;
139 case eDVBFrontendParametersSatellite::FEC::f8_9: tmp="8/9"; break;
140 case eDVBFrontendParametersSatellite::FEC::f9_10: tmp="9/10"; break;
142 case eDVBFrontendParametersSatellite::FEC::fAuto: tmp="AUTO"; break;
144 PutToDict(dict, "fec inner", tmp);
145 switch (feparm.modulation)
147 case eDVBFrontendParametersSatellite::Modulation::Auto: tmp="AUTO"; break;
148 case eDVBFrontendParametersSatellite::Modulation::QPSK: tmp="QPSK"; break;
149 case eDVBFrontendParametersSatellite::Modulation::M8PSK: tmp="8PSK"; break;
150 case eDVBFrontendParametersSatellite::Modulation::QAM_16: tmp="QAM16"; break;
152 PutToDict(dict, "modulation", tmp);
153 switch(feparm.polarisation)
155 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
156 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
157 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR LEFT"; break;
159 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR RIGHT"; break;
161 PutToDict(dict, "polarization", tmp);
162 switch(feparm.system)
165 case eDVBFrontendParametersSatellite::System::DVB_S: tmp="DVB-S"; break;
166 case eDVBFrontendParametersSatellite::System::DVB_S2:
167 switch(feparm.rolloff)
170 case eDVBFrontendParametersSatellite::RollOff::alpha_0_35: tmp="0.35"; break;
171 case eDVBFrontendParametersSatellite::RollOff::alpha_0_25: tmp="0.25"; break;
172 case eDVBFrontendParametersSatellite::RollOff::alpha_0_20: tmp="0.20"; break;
174 PutToDict(dict, "roll off", tmp);
177 case eDVBFrontendParametersSatellite::Pilot::On: tmp="ON"; break;
178 case eDVBFrontendParametersSatellite::Pilot::Off: tmp="OFF"; break;
180 case eDVBFrontendParametersSatellite::Pilot::Unknown: tmp="AUTO"; break;
182 PutToDict(dict, "pilot", tmp);
186 PutToDict(dict, "system", tmp);
189 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
191 PutToDict(dict, "type", "Terrestrial");
192 PutToDict(dict, "frequency", feparm.frequency);
194 switch (feparm.bandwidth)
196 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz: tmp="8 MHz"; break;
197 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz: tmp="7 MHz"; break;
198 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz: tmp="6 MHz"; break;
200 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto: tmp="AUTO"; break;
202 PutToDict(dict, "bandwidth", tmp);
203 switch (feparm.code_rate_LP)
205 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
206 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
207 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
208 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
209 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
211 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
213 PutToDict(dict, "code rate lp", tmp);
214 switch (feparm.code_rate_HP)
216 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
217 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
218 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
219 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
220 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
222 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
224 PutToDict(dict, "code rate hp", tmp);
225 switch (feparm.modulation)
227 case eDVBFrontendParametersTerrestrial::Modulation::QPSK: tmp="QPSK"; break;
228 case eDVBFrontendParametersTerrestrial::Modulation::QAM16: tmp="QAM16"; break;
229 case eDVBFrontendParametersTerrestrial::Modulation::QAM64: tmp="QAM64"; break;
231 case eDVBFrontendParametersTerrestrial::Modulation::Auto: tmp="AUTO"; break;
233 PutToDict(dict, "constellation", tmp);
234 switch (feparm.transmission_mode)
236 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k: tmp="2k"; break;
237 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k: tmp="8k"; break;
239 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto: tmp="AUTO"; break;
241 PutToDict(dict, "transmission mode", tmp);
242 switch (feparm.guard_interval)
244 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32: tmp="1/32"; break;
245 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16: tmp="1/16"; break;
246 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8: tmp="1/8"; break;
247 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4: tmp="1/4"; break;
249 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto: tmp="AUTO"; break;
251 PutToDict(dict, "guard interval", tmp);
252 switch (feparm.hierarchy)
254 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone: tmp="NONE"; break;
255 case eDVBFrontendParametersTerrestrial::Hierarchy::H1: tmp="1"; break;
256 case eDVBFrontendParametersTerrestrial::Hierarchy::H2: tmp="2"; break;
257 case eDVBFrontendParametersTerrestrial::Hierarchy::H4: tmp="4"; break;
259 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto: tmp="AUTO"; break;
261 PutToDict(dict, "hierarchy", tmp);
262 switch (feparm.inversion)
264 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
265 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
267 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
269 PutToDict(dict, "inversion", tmp);
272 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
275 PutToDict(dict, "type", "Cable");
276 PutToDict(dict, "frequency", feparm.frequency);
277 PutToDict(dict, "symbolrate", feparm.symbol_rate);
278 switch (feparm.modulation)
280 case eDVBFrontendParametersCable::Modulation::QAM16: tmp="QAM16"; break;
281 case eDVBFrontendParametersCable::Modulation::QAM32: tmp="QAM32"; break;
282 case eDVBFrontendParametersCable::Modulation::QAM64: tmp="QAM64"; break;
283 case eDVBFrontendParametersCable::Modulation::QAM128: tmp="QAM128"; break;
284 case eDVBFrontendParametersCable::Modulation::QAM256: tmp="QAM256"; break;
286 case eDVBFrontendParametersCable::Modulation::Auto: tmp="AUTO"; break;
288 PutToDict(dict, "modulation", tmp);
289 switch (feparm.inversion)
291 case eDVBFrontendParametersCable::Inversion::On: tmp="ON"; break;
292 case eDVBFrontendParametersCable::Inversion::Off: tmp="OFF"; break;
294 case eDVBFrontendParametersCable::Inversion::Unknown: tmp="AUTO"; break;
296 PutToDict(dict, "inversion", tmp);
297 switch (feparm.fec_inner)
299 case eDVBFrontendParametersCable::FEC::fNone: tmp="NONE"; break;
300 case eDVBFrontendParametersCable::FEC::f1_2: tmp="1/2"; break;
301 case eDVBFrontendParametersCable::FEC::f2_3: tmp="2/3"; break;
302 case eDVBFrontendParametersCable::FEC::f3_4: tmp="3/4"; break;
303 case eDVBFrontendParametersCable::FEC::f5_6: tmp="5/6"; break;
304 case eDVBFrontendParametersCable::FEC::f7_8: tmp="7/8"; break;
305 case eDVBFrontendParametersCable::FEC::f8_9: tmp="8/9"; break;
307 case eDVBFrontendParametersCable::FEC::fAuto: tmp="AUTO"; break;
309 PutToDict(dict, "fec inner", tmp);
312 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
314 if (r.type == eServiceReference::idDVB)
316 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
319 case iServiceInformation::sTransponderData:
321 ePtr<eDVBResourceManager> res;
322 if (!eDVBResourceManager::getInstance(res))
324 ePtr<iDVBChannelList> db;
325 if (!res->getChannelList(db))
328 ref.getChannelID(chid);
329 ePtr<iDVBFrontendParameters> feparm;
330 if (!db->getChannelFrontendData(chid, feparm))
333 if (!feparm->getSystem(system))
335 ePyObject dict = PyDict_New();
338 case iDVBFrontend::feSatellite:
340 eDVBFrontendParametersSatellite s;
342 PutSatelliteDataToDict(dict, s);
345 case iDVBFrontend::feTerrestrial:
347 eDVBFrontendParametersTerrestrial t;
349 PutTerrestrialDataToDict(dict, t);
352 case iDVBFrontend::feCable:
354 eDVBFrontendParametersCable c;
356 PutCableDataToDict(dict, c);
360 eDebug("unknown frontend type %d", system);
375 DEFINE_REF(eStaticServiceDVBBouquetInformation);
377 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
379 ePtr<iDVBChannelList> db;
380 ePtr<eDVBResourceManager> res;
383 if ((err = eDVBResourceManager::getInstance(res)) != 0)
385 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
388 if ((err = res->getChannelList(db)) != 0)
390 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
395 if ((err = db->getBouquet(ref, bouquet)) != 0)
397 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
401 if ( bouquet && bouquet->m_bouquet_name.length() )
403 name = bouquet->m_bouquet_name;
410 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
412 if (ref.flags & eServiceReference::isGroup)
414 ePtr<iDVBChannelList> db;
415 ePtr<eDVBResourceManager> res;
417 if (eDVBResourceManager::getInstance(res))
419 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
423 if (res->getChannelList(db))
425 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
430 if (db->getBouquet(ref, bouquet))
432 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
436 int prio_order = eDVBFrontend::getTypePriorityOrder();
438 eDVBChannelID chid, chid_ignore;
439 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
440 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
442 static unsigned char prio_map[6][3] = {
443 { 3, 2, 1 }, // -S -C -T
444 { 3, 1, 2 }, // -S -T -C
445 { 2, 3, 1 }, // -C -S -T
446 { 1, 3, 2 }, // -C -T -S
447 { 1, 2, 3 }, // -T -C -S
448 { 2, 1, 3 } // -T -S -C
450 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
451 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
456 case 30000: // cached DVB-T channel
457 case 1: // DVB-T frontend
458 tmp = prio_map[prio_order][2];
460 case 40000: // cached DVB-C channel
462 tmp = prio_map[prio_order][1];
465 tmp = prio_map[prio_order][0];
470 m_playable_service = *it;
477 m_playable_service = eServiceReference();
481 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
486 #include <lib/dvb/epgcache.h>
488 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
490 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
493 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
495 DECLARE_REF(eStaticServiceDVBPVRInformation);
496 eServiceReference m_ref;
497 eDVBMetaParser m_parser;
499 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
500 RESULT getName(const eServiceReference &ref, std::string &name);
501 int getLength(const eServiceReference &ref);
502 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
503 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
504 int getInfo(const eServiceReference &ref, int w);
505 std::string getInfoString(const eServiceReference &ref,int w);
508 DEFINE_REF(eStaticServiceDVBPVRInformation);
510 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
513 m_parser.parseFile(ref.path);
516 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
518 ASSERT(ref == m_ref);
519 if (m_parser.m_name.size())
520 name = m_parser.m_name;
524 size_t n = name.rfind('/');
525 if (n != std::string::npos)
526 name = name.substr(n + 1);
531 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
533 ASSERT(ref == m_ref);
537 if (tstools.openFile(ref.path.c_str()))
541 if (tstools.calcLen(len))
547 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
551 case iServiceInformation::sDescription:
552 return iServiceInformation::resIsString;
553 case iServiceInformation::sServiceref:
554 return iServiceInformation::resIsString;
555 case iServiceInformation::sTimeCreate:
556 if (m_parser.m_time_create)
557 return m_parser.m_time_create;
559 return iServiceInformation::resNA;
561 return iServiceInformation::resNA;
565 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
569 case iServiceInformation::sDescription:
570 return m_parser.m_description;
571 case iServiceInformation::sServiceref:
572 return m_parser.m_ref.toString();
573 case iServiceInformation::sTags:
574 return m_parser.m_tags;
580 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
582 if (!ref.path.empty())
584 ePtr<eServiceEvent> event = new eServiceEvent;
585 std::string filename = ref.path;
586 filename.erase(filename.length()-2, 2);
588 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
598 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
600 DECLARE_REF(eDVBPVRServiceOfflineOperations);
601 eServiceReferenceDVB m_ref;
603 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
605 RESULT deleteFromDisk(int simulate);
606 RESULT getListOfFilenames(std::list<std::string> &);
609 DEFINE_REF(eDVBPVRServiceOfflineOperations);
611 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
615 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
621 std::list<std::string> res;
622 if (getListOfFilenames(res))
625 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
627 eDebug("FATAL !! can't get background file eraser");
629 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
631 eDebug("Removing %s...", i->c_str());
633 eraser->erase(i->c_str());
635 ::unlink(i->c_str());
642 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
645 res.push_back(m_ref.path);
647 // handling for old splitted recordings (enigma 1)
652 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
654 if (stat(buf, &s) < 0)
659 res.push_back(m_ref.path + ".meta");
660 res.push_back(m_ref.path + ".ap");
661 res.push_back(m_ref.path + ".cuts");
662 std::string tmp = m_ref.path;
663 tmp.erase(m_ref.path.length()-3);
664 res.push_back(tmp + ".eit");
668 DEFINE_REF(eServiceFactoryDVB)
670 eServiceFactoryDVB::eServiceFactoryDVB()
672 ePtr<eServiceCenter> sc;
674 eServiceCenter::getPrivInstance(sc);
677 std::list<std::string> extensions;
678 extensions.push_back("ts");
679 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
682 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
683 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
686 eServiceFactoryDVB::~eServiceFactoryDVB()
688 ePtr<eServiceCenter> sc;
690 eServiceCenter::getPrivInstance(sc);
692 sc->removeServiceFactory(eServiceFactoryDVB::id);
695 DEFINE_REF(eDVBServiceList);
697 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
701 eDVBServiceList::~eDVBServiceList()
705 RESULT eDVBServiceList::startQuery()
707 ePtr<iDVBChannelList> db;
708 ePtr<eDVBResourceManager> res;
711 if ((err = eDVBResourceManager::getInstance(res)) != 0)
713 eDebug("no resource manager");
716 if ((err = res->getChannelList(db)) != 0)
718 eDebug("no channel list");
722 ePtr<eDVBChannelQuery> q;
724 if (!m_parent.path.empty())
726 eDVBChannelQuery::compile(q, m_parent.path);
729 eDebug("compile query failed");
734 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
736 eDebug("startQuery failed");
743 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
745 eServiceReferenceDVB ref;
750 while (!m_query->getNextResult(ref))
754 list.sort(iListableServiceCompare(this));
759 // The first argument of this function is a format string to specify the order and
760 // the content of the returned list
761 // useable format options are
762 // R = Service Reference (as swig object .. this is very slow)
763 // S = Service Reference (as python string object .. same as ref.toString())
764 // C = Service Reference (as python string object .. same as ref.toCompareString())
765 // N = Service Name (as python string object)
766 // n = Short Service Name (short name brakets used) (as python string object)
767 // when exactly one return value per service is selected in the format string,
768 // then each value is directly a list entry
769 // when more than one value is returned per service, then the list is a list of
771 // unknown format string chars are returned as python None values !
772 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
775 std::list<eServiceReference> tmplist;
778 if (!format || !(retcount=strlen(format)))
779 format = "R"; // just return service reference swig object ...
781 if (!getContent(tmplist, sorted))
783 int services=tmplist.size();
784 ePtr<iStaticServiceInformation> sptr;
785 eServiceCenterPtr service_center;
787 if (strchr(format, 'N') || strchr(format, 'n'))
788 eServiceCenter::getPrivInstance(service_center);
790 ret = PyList_New(services);
791 std::list<eServiceReference>::iterator it(tmplist.begin());
793 for (int cnt=0; cnt < services; ++cnt)
795 eServiceReference &ref=*it++;
796 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
797 for (int i=0; i < retcount; ++i)
802 case 'R': // service reference (swig)object
803 tmp = NEW_eServiceReference(ref);
805 case 'C': // service reference compare string
806 tmp = PyString_FromString(ref.toCompareString().c_str());
808 case 'S': // service reference string
809 tmp = PyString_FromString(ref.toString().c_str());
811 case 'N': // service name
814 service_center->info(ref, sptr);
818 sptr->getName(ref, name);
820 // filter short name brakets
822 while((pos = name.find("\xc2\x86")) != std::string::npos)
824 while((pos = name.find("\xc2\x87")) != std::string::npos)
828 tmp = PyString_FromString(name.c_str());
832 tmp = PyString_FromString("<n/a>");
834 case 'n': // short service name
837 service_center->info(ref, sptr);
841 sptr->getName(ref, name);
842 name = buildShortName(name);
844 tmp = PyString_FromString(name.c_str());
848 tmp = PyString_FromString("<n/a>");
861 PyTuple_SET_ITEM(tuple, i, tmp);
863 PyList_SET_ITEM(ret, cnt, tmp);
867 PyList_SET_ITEM(ret, cnt, tuple);
870 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
873 RESULT eDVBServiceList::getNext(eServiceReference &ref)
878 return m_query->getNextResult((eServiceReferenceDVB&)ref);
881 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
883 if (m_parent.flags & eServiceReference::canDescent) // bouquet
885 ePtr<iDVBChannelList> db;
886 ePtr<eDVBResourceManager> resm;
888 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
891 if (db->getBouquet(m_parent, m_bouquet) != 0)
902 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
906 return m_bouquet->addService(ref, before);
909 RESULT eDVBServiceList::removeService(eServiceReference &ref)
913 return m_bouquet->removeService(ref);
916 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
920 return m_bouquet->moveService(ref, pos);
923 RESULT eDVBServiceList::flushChanges()
927 return m_bouquet->flushChanges();
930 RESULT eDVBServiceList::setListName(const std::string &name)
934 return m_bouquet->setListName(name);
937 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
939 ePtr<eDVBService> service;
940 int r = lookupService(service, ref);
943 // check resources...
944 ptr = new eDVBServicePlay(ref, service);
948 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
950 if (ref.path.empty())
952 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
961 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
963 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
964 if (list->startQuery())
974 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
976 /* is a listable service? */
977 if (ref.flags & eServiceReference::canDescent) // bouquet
979 if ( !ref.name.empty() ) // satellites or providers list
980 ptr = m_StaticServiceDVBInfo;
981 else // a dvb bouquet
982 ptr = m_StaticServiceDVBBouquetInfo;
984 else if (!ref.path.empty()) /* do we have a PVR service? */
985 ptr = new eStaticServiceDVBPVRInformation(ref);
986 else // normal dvb service
988 ePtr<eDVBService> service;
989 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
990 ptr = m_StaticServiceDVBInfo;
992 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
998 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
1000 if (ref.path.empty())
1006 ptr = new eDVBPVRServiceOfflineOperations(ref);
1011 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
1013 // TODO: handle the listing itself
1014 // if (ref.... == -1) .. return "... bouquets ...";
1015 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
1017 ePtr<iDVBChannelList> db;
1018 ePtr<eDVBResourceManager> res;
1021 if ((err = eDVBResourceManager::getInstance(res)) != 0)
1023 eDebug("no resource manager");
1026 if ((err = res->getChannelList(db)) != 0)
1028 eDebug("no channel list");
1032 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
1033 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
1035 eDebug("getService failed!");
1042 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
1043 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
1045 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
1047 m_is_pvr = !m_reference.path.empty();
1049 m_timeshift_enabled = m_timeshift_active = 0;
1052 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
1053 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
1054 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
1056 m_cuesheet_changed = 0;
1057 m_cutlist_enabled = 1;
1059 m_subtitle_widget = 0;
1063 m_subtitle_sync_timer = eTimer::create(eApp);
1065 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
1068 eDVBServicePlay::~eDVBServicePlay()
1070 delete m_subtitle_widget;
1073 void eDVBServicePlay::gotNewEvent()
1077 ePtr<eServiceEvent> m_event_now, m_event_next;
1078 getEvent(m_event_now, 0);
1079 getEvent(m_event_next, 1);
1082 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1084 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1086 m_event((iPlayableService*)this, evUpdatedEventInfo);
1089 void eDVBServicePlay::serviceEvent(int event)
1091 m_tune_state = event;
1095 case eDVBServicePMTHandler::eventTuned:
1097 ePtr<iDVBDemux> m_demux;
1098 if (!m_service_handler.getDataDemux(m_demux))
1100 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1101 int sid = ref.getParentServiceID().get();
1103 sid = ref.getServiceID().get();
1104 if ( ref.getParentTransportStreamID().get() &&
1105 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1106 m_event_handler.startOther(m_demux, sid);
1108 m_event_handler.start(m_demux, sid);
1110 m_event((iPlayableService*)this, evTunedIn);
1113 case eDVBServicePMTHandler::eventNoResources:
1114 case eDVBServicePMTHandler::eventNoPAT:
1115 case eDVBServicePMTHandler::eventNoPATEntry:
1116 case eDVBServicePMTHandler::eventNoPMT:
1117 case eDVBServicePMTHandler::eventTuneFailed:
1118 case eDVBServicePMTHandler::eventMisconfiguration:
1120 eDebug("DVB service failed to tune - error %d", event);
1121 m_event((iPlayableService*)this, evTuneFailed);
1124 case eDVBServicePMTHandler::eventNewProgramInfo:
1126 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1127 if (m_timeshift_enabled)
1128 updateTimeshiftPids();
1129 if (!m_timeshift_active)
1131 if (m_first_program_info && m_is_pvr)
1133 m_first_program_info = 0;
1136 m_event((iPlayableService*)this, evUpdatedInfo);
1139 case eDVBServicePMTHandler::eventEOF:
1140 m_event((iPlayableService*)this, evEOF);
1142 case eDVBServicePMTHandler::eventSOF:
1143 m_event((iPlayableService*)this, evSOF);
1148 void eDVBServicePlay::serviceEventTimeshift(int event)
1152 case eDVBServicePMTHandler::eventNewProgramInfo:
1153 if (m_timeshift_active)
1156 case eDVBServicePMTHandler::eventSOF:
1157 m_event((iPlayableService*)this, evSOF);
1159 case eDVBServicePMTHandler::eventEOF:
1160 if ((!m_is_paused) && (m_skipmode >= 0))
1166 RESULT eDVBServicePlay::start()
1169 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1170 two (one for decoding, one for data source), as we must be prepared
1171 to start recording from the data demux. */
1173 m_cue = new eCueSheet();
1175 m_event(this, evStart);
1177 m_first_program_info = 1;
1178 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1179 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1181 /* inject EIT if there is a stored one */
1184 std::string filename = service.path;
1185 filename.erase(filename.length()-2, 2);
1187 ePtr<eServiceEvent> event = new eServiceEvent;
1188 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1190 ePtr<eServiceEvent> empty;
1191 m_event_handler.inject(event, 0);
1192 m_event_handler.inject(empty, 1);
1199 m_event(this, evStart);
1204 RESULT eDVBServicePlay::stop()
1206 /* add bookmark for last play position */
1209 pts_t play_position, length;
1210 if (!getPlayPosition(play_position))
1212 /* remove last position */
1213 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1215 if (i->what == 3) /* current play position */
1217 m_cue_entries.erase(i);
1218 i = m_cue_entries.begin();
1224 if (getLength(length))
1229 int perc = play_position * 100LL / length;
1231 /* only store last play position when between 1% and 99% */
1232 if ((1 < perc) && (perc < 99))
1233 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1235 m_cuesheet_changed = 1;
1239 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1241 m_service_handler_timeshift.free();
1242 m_service_handler.free();
1244 if (m_is_pvr && m_cuesheet_changed)
1247 /* save cuesheet only when main file is accessible. */
1248 if (!::stat(m_reference.path.c_str(), &s))
1251 m_event((iPlayableService*)this, evStopped);
1255 RESULT eDVBServicePlay::setTarget(int target)
1257 m_is_primary = !target;
1261 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1263 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1267 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1269 /* note: we check for timeshift to be enabled,
1270 not neccessary active. if you pause when timeshift
1271 is not active, you should activate it when unpausing */
1272 if ((!m_is_pvr) && (!m_timeshift_enabled))
1282 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1284 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1286 return m_decoder->setSlowMotion(ratio);
1291 RESULT eDVBServicePlay::setFastForward(int ratio)
1293 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1294 int skipmode, ffratio;
1300 } else if (ratio > 0)
1308 } else // if (ratio < 0)
1314 if (m_skipmode != skipmode)
1316 eDebug("setting cue skipmode to %d", skipmode);
1318 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1321 m_skipmode = skipmode;
1326 return m_decoder->setFastForward(ffratio);
1329 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1331 if (m_is_pvr || m_timeshift_enabled)
1341 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1342 RESULT eDVBServicePlay::getLength(pts_t &len)
1344 ePtr<iDVBPVRChannel> pvr_channel;
1346 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1349 return pvr_channel->getLength(len);
1352 RESULT eDVBServicePlay::pause()
1354 eDebug("eDVBServicePlay::pause");
1355 if (!m_is_paused && m_decoder)
1358 return m_decoder->freeze(0);
1363 RESULT eDVBServicePlay::unpause()
1365 eDebug("eDVBServicePlay::unpause");
1366 if (m_is_paused && m_decoder)
1369 return m_decoder->unfreeze();
1374 RESULT eDVBServicePlay::seekTo(pts_t to)
1376 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1378 if (!m_decode_demux)
1381 ePtr<iDVBPVRChannel> pvr_channel;
1383 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1389 m_cue->seekTo(0, to);
1390 m_dvb_subtitle_pages.clear();
1391 m_subtitle_pages.clear();
1396 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1398 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1400 if (!m_decode_demux)
1403 ePtr<iDVBPVRChannel> pvr_channel;
1405 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1410 /* HACK until we have skip-AP api */
1411 if ((to > 0) && (to < 100))
1419 m_cue->seekTo(mode, to);
1420 m_dvb_subtitle_pages.clear();
1421 m_subtitle_pages.clear();
1425 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1427 ePtr<iDVBPVRChannel> pvr_channel;
1429 if (!m_decode_demux)
1432 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1437 /* if there is a decoder, use audio or video PTS */
1440 r = m_decoder->getPTS(0, pos);
1446 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1449 RESULT eDVBServicePlay::setTrickmode(int trick)
1452 m_decoder->setTrickmode(trick);
1456 RESULT eDVBServicePlay::isCurrentlySeekable()
1458 return m_is_pvr || m_timeshift_active;
1461 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1467 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1473 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1479 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1485 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1491 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1494 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1495 (m_timeshift_enabled || !m_is_pvr))
1497 if (!m_timeshift_enabled)
1499 /* query config path */
1501 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1502 eDebug("could not query ts path from config");
1506 /* we need enough diskspace */
1508 if (statfs(tspath.c_str(), &fs) < 0)
1510 eDebug("statfs failed!");
1514 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1516 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1526 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1537 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1543 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1549 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1555 RESULT eDVBServicePlay::getName(std::string &name)
1559 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1560 return i->getName(m_reference, name);
1564 m_dvb_service->getName(m_reference, name);
1568 else if (!m_reference.name.empty())
1569 eStaticServiceDVBInformation().getName(m_reference, name);
1571 name = "DVB service";
1575 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1577 return m_event_handler.getEvent(evt, nownext);
1580 static int readMpegProc(char *str, int decoder)
1584 sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
1585 FILE *f = fopen(tmp, "r");
1588 fscanf(f, "%x", &val);
1594 int eDVBServicePlay::getInfo(int w)
1596 eDVBServicePMTHandler::program program;
1599 return resIsPyObject;
1601 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1603 int no_program_info = 0;
1605 if (h.getProgramInfo(program))
1606 no_program_info = 1;
1610 #if HAVE_DVB_API_VERSION >= 3
1612 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1613 return m_videoEventData.height;
1615 return readMpegProc("yres", !m_is_primary);
1617 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1618 return m_videoEventData.width;
1620 return readMpegProc("xres", !m_is_primary);
1622 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventFrameRateChanged)
1623 return m_videoEventData.framerate;
1625 return readMpegProc("framerate", !m_is_primary);
1627 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventProgressiveChanged)
1628 return m_videoEventData.progressive;
1629 return readMpegProc("progressive", !m_is_primary);
1631 #warning "FIXMEE implement sFrameRate, sProgressive, sVideoHeight, sVideoWidth for old DVB API"
1636 #if HAVE_DVB_API_VERSION >= 3
1637 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1638 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1639 else if ((val=readMpegProc("aspect", !m_is_primary)) != -1)
1643 #warning "FIXMEE implement sAspect for old DVB API"
1645 if (no_program_info)
1647 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1649 ePtr<eServiceEvent> evt;
1650 if (!m_event_handler.getEvent(evt, 0))
1652 ePtr<eComponentData> data;
1653 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1655 if ( data->getStreamContent() == 1 )
1657 switch(data->getComponentType())
1660 case 1: // 4:3 SD PAL
1662 case 3: // 16:9 SD PAL
1663 case 4: // > 16:9 PAL
1664 case 5: // 4:3 SD NTSC
1666 case 7: // 16:9 SD NTSC
1667 case 8: // > 16:9 NTSC
1670 case 9: // 4:3 HD PAL
1672 case 0xB: // 16:9 HD PAL
1673 case 0xC: // > 16:9 HD PAL
1674 case 0xD: // 4:3 HD NTSC
1676 case 0xF: // 16:9 HD NTSC
1677 case 0x10: // > 16:9 HD PAL
1678 return data->getComponentType();
1686 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1687 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1688 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1689 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1690 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1691 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1692 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1693 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1694 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1695 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1696 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1697 case sProvider: if (!m_dvb_service) return -1; return -2;
1698 case sServiceref: return resIsString;
1699 case sDVBState: return m_tune_state;
1705 std::string eDVBServicePlay::getInfoString(int w)
1710 if (!m_dvb_service) return "";
1711 return m_dvb_service->m_provider_name;
1713 return m_reference.toString();
1717 return iServiceInformation::getInfoString(w);
1720 PyObject *eDVBServicePlay::getInfoObject(int w)
1725 return m_service_handler.getCaIds();
1726 case sTransponderData:
1727 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1731 return iServiceInformation::getInfoObject(w);
1734 int eDVBServicePlay::getNumberOfTracks()
1736 eDVBServicePMTHandler::program program;
1737 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1738 if (h.getProgramInfo(program))
1740 return program.audioStreams.size();
1743 int eDVBServicePlay::getCurrentTrack()
1745 eDVBServicePMTHandler::program program;
1746 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1747 if (h.getProgramInfo(program))
1750 int max = program.audioStreams.size();
1753 for (i = 0; i < max; ++i)
1754 if (program.audioStreams[i].pid == m_current_audio_pid)
1760 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1762 int ret = selectAudioStream(i);
1764 if (m_decoder->start())
1770 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1772 eDVBServicePMTHandler::program program;
1773 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1775 if (h.getProgramInfo(program))
1778 if (i >= program.audioStreams.size())
1781 info.m_pid = program.audioStreams[i].pid;
1783 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1784 info.m_description = "MPEG";
1785 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1786 info.m_description = "AC3";
1787 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1788 info.m_description = "AAC";
1789 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1790 info.m_description = "DTS";
1792 info.m_description = "???";
1794 if (program.audioStreams[i].component_tag != -1)
1796 ePtr<eServiceEvent> evt;
1797 if (!m_event_handler.getEvent(evt, 0))
1799 ePtr<eComponentData> data;
1800 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1801 info.m_language = data->getText();
1805 if (info.m_language.empty())
1806 info.m_language = program.audioStreams[i].language_code;
1811 int eDVBServicePlay::selectAudioStream(int i)
1813 eDVBServicePMTHandler::program program;
1814 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1816 if (h.getProgramInfo(program))
1819 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1827 stream = program.defaultAudioStream;
1829 int apid = -1, apidtype = -1;
1831 if (((unsigned int)stream) < program.audioStreams.size())
1833 apid = program.audioStreams[stream].pid;
1834 apidtype = program.audioStreams[stream].type;
1837 m_current_audio_pid = apid;
1839 if (m_decoder->setAudioPID(apid, apidtype))
1841 eDebug("set audio pid failed");
1845 /* 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 */
1846 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1849 ePtr<iDVBDemux> data_demux;
1850 if (!h.getDataDemux(data_demux))
1852 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1853 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1857 /* if we decided that we need one, update the pid */
1859 m_rds_decoder->start(apid);
1861 /* store new pid as default only when:
1862 a.) we have an entry in the service db for the current service,
1863 b.) we are not playing back something,
1864 c.) we are not selecting the default entry. (we wouldn't change
1865 anything in the best case, or destroy the default setting in
1866 case the real default is not yet available.)
1868 if (m_dvb_service && !m_is_pvr && ((i != -1)
1869 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1871 if (apidtype == eDVBAudio::aMPEG)
1873 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1874 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1878 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1879 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1883 h.resetCachedProgram();
1888 int eDVBServicePlay::getCurrentChannel()
1890 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1893 RESULT eDVBServicePlay::selectChannel(int i)
1895 if (i < LEFT || i > RIGHT || i == STEREO)
1898 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1900 m_decoder->setAudioChannel(i);
1904 std::string eDVBServicePlay::getText(int x)
1910 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1912 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1917 void eDVBServicePlay::rdsDecoderEvent(int what)
1921 case eDVBRdsDecoder::RadioTextChanged:
1922 m_event((iPlayableService*)this, evUpdatedRadioText);
1924 case eDVBRdsDecoder::RtpTextChanged:
1925 m_event((iPlayableService*)this, evUpdatedRtpText);
1927 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1928 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1930 case eDVBRdsDecoder::RecvRassSlidePic:
1931 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1936 void eDVBServicePlay::showRassSlidePicture()
1942 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1943 if (rass_slide_pic.length())
1944 m_decoder->showSinglePic(rass_slide_pic.c_str());
1946 eDebug("empty filename for rass slide picture received!!");
1949 eDebug("no MPEG Decoder to show iframes avail");
1952 eDebug("showRassSlidePicture called.. but not decoder");
1955 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1961 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1962 if (rass_interactive_pic.length())
1963 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1965 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1968 eDebug("no MPEG Decoder to show iframes avail");
1971 eDebug("showRassInteractivePic called.. but not decoder");
1974 ePyObject eDVBServicePlay::getRassInteractiveMask()
1977 return m_rds_decoder->getRassPictureMask();
1981 int eDVBServiceBase::getFrontendInfo(int w)
1983 eUsePtr<iDVBChannel> channel;
1984 if(m_service_handler.getChannel(channel))
1986 ePtr<iDVBFrontend> fe;
1987 if(channel->getFrontend(fe))
1989 return fe->readFrontendData(w);
1992 PyObject *eDVBServiceBase::getFrontendData()
1994 ePyObject ret = PyDict_New();
1997 eUsePtr<iDVBChannel> channel;
1998 if(!m_service_handler.getChannel(channel))
2000 ePtr<iDVBFrontend> fe;
2001 if(!channel->getFrontend(fe))
2002 fe->getFrontendData(ret);
2010 PyObject *eDVBServiceBase::getFrontendStatus()
2012 ePyObject ret = PyDict_New();
2015 eUsePtr<iDVBChannel> channel;
2016 if(!m_service_handler.getChannel(channel))
2018 ePtr<iDVBFrontend> fe;
2019 if(!channel->getFrontend(fe))
2020 fe->getFrontendStatus(ret);
2028 PyObject *eDVBServiceBase::getTransponderData(bool original)
2030 ePyObject ret = PyDict_New();
2033 eUsePtr<iDVBChannel> channel;
2034 if(!m_service_handler.getChannel(channel))
2036 ePtr<iDVBFrontend> fe;
2037 if(!channel->getFrontend(fe))
2039 fe->getTransponderData(ret, original);
2040 ePtr<iDVBFrontendParameters> feparm;
2041 channel->getCurrentFrontendParameters(feparm);
2044 eDVBFrontendParametersSatellite osat;
2045 if (!feparm->getDVBS(osat))
2047 void PutToDict(ePyObject &, const char*, long);
2048 void PutToDict(ePyObject &, const char*, const char*);
2049 PutToDict(ret, "orbital_position", osat.orbital_position);
2050 const char *tmp = "UNKNOWN";
2051 switch(osat.polarisation)
2053 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2054 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2055 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2056 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2059 PutToDict(ret, "polarization", tmp);
2070 PyObject *eDVBServiceBase::getAll(bool original)
2072 ePyObject ret = getTransponderData(original);
2075 eUsePtr<iDVBChannel> channel;
2076 if(!m_service_handler.getChannel(channel))
2078 ePtr<iDVBFrontend> fe;
2079 if(!channel->getFrontend(fe))
2081 fe->getFrontendData(ret);
2082 fe->getFrontendStatus(ret);
2089 int eDVBServicePlay::getNumberOfSubservices()
2091 ePtr<eServiceEvent> evt;
2092 if (!m_event_handler.getEvent(evt, 0))
2093 return evt->getNumOfLinkageServices();
2097 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2099 ePtr<eServiceEvent> evt;
2100 if (!m_event_handler.getEvent(evt, 0))
2102 if (!evt->getLinkageService(sub, m_reference, n))
2105 sub.type=eServiceReference::idInvalid;
2109 RESULT eDVBServicePlay::startTimeshift()
2111 ePtr<iDVBDemux> demux;
2113 eDebug("Start timeshift!");
2115 if (m_timeshift_enabled)
2118 /* start recording with the data demux. */
2119 if (m_service_handler.getDataDemux(demux))
2122 demux->createTSRecorder(m_record);
2127 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2128 eDebug("could not query ts path");
2131 tspath.append("/timeshift.XXXXXX");
2133 templ = new char[tspath.length() + 1];
2134 strcpy(templ, tspath.c_str());
2136 m_timeshift_fd = mkstemp(templ);
2137 m_timeshift_file = std::string(templ);
2139 eDebug("recording to %s", templ);
2143 if (m_timeshift_fd < 0)
2149 m_record->setTargetFD(m_timeshift_fd);
2151 m_timeshift_enabled = 1;
2153 updateTimeshiftPids();
2159 RESULT eDVBServicePlay::stopTimeshift()
2161 if (!m_timeshift_enabled)
2166 m_timeshift_enabled = 0;
2171 close(m_timeshift_fd);
2172 eDebug("remove timeshift file");
2173 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2178 int eDVBServicePlay::isTimeshiftActive()
2180 return m_timeshift_enabled && m_timeshift_active;
2183 RESULT eDVBServicePlay::activateTimeshift()
2185 if (!m_timeshift_enabled)
2188 if (!m_timeshift_active)
2190 switchToTimeshift();
2197 PyObject *eDVBServicePlay::getCutList()
2199 ePyObject list = PyList_New(0);
2201 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2203 ePyObject tuple = PyTuple_New(2);
2204 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2205 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2206 PyList_Append(list, tuple);
2213 void eDVBServicePlay::setCutList(ePyObject list)
2215 if (!PyList_Check(list))
2217 int size = PyList_Size(list);
2220 m_cue_entries.clear();
2222 for (i=0; i<size; ++i)
2224 ePyObject tuple = PyList_GET_ITEM(list, i);
2225 if (!PyTuple_Check(tuple))
2227 eDebug("non-tuple in cutlist");
2230 if (PyTuple_Size(tuple) != 2)
2232 eDebug("cutlist entries need to be a 2-tuple");
2235 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2236 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2238 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2241 pts_t pts = PyLong_AsLongLong(ppts);
2242 int type = PyInt_AsLong(ptype);
2243 m_cue_entries.insert(cueEntry(pts, type));
2244 eDebug("adding %08llx, %d", pts, type);
2246 m_cuesheet_changed = 1;
2248 cutlistToCuesheet();
2249 m_event((iPlayableService*)this, evCuesheetChanged);
2252 void eDVBServicePlay::setCutListEnable(int enable)
2254 m_cutlist_enabled = enable;
2255 cutlistToCuesheet();
2258 void eDVBServicePlay::updateTimeshiftPids()
2263 eDVBServicePMTHandler::program program;
2264 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2266 if (h.getProgramInfo(program))
2270 std::set<int> pids_to_record;
2271 pids_to_record.insert(0); // PAT
2272 if (program.pmtPid != -1)
2273 pids_to_record.insert(program.pmtPid); // PMT
2275 if (program.textPid != -1)
2276 pids_to_record.insert(program.textPid); // Videotext
2278 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2279 i(program.videoStreams.begin());
2280 i != program.videoStreams.end(); ++i)
2281 pids_to_record.insert(i->pid);
2283 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2284 i(program.audioStreams.begin());
2285 i != program.audioStreams.end(); ++i)
2286 pids_to_record.insert(i->pid);
2288 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2289 i(program.subtitleStreams.begin());
2290 i != program.subtitleStreams.end(); ++i)
2291 pids_to_record.insert(i->pid);
2293 std::set<int> new_pids, obsolete_pids;
2295 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2296 m_pids_active.begin(), m_pids_active.end(),
2297 std::inserter(new_pids, new_pids.begin()));
2299 std::set_difference(
2300 m_pids_active.begin(), m_pids_active.end(),
2301 pids_to_record.begin(), pids_to_record.end(),
2302 std::inserter(new_pids, new_pids.begin())
2305 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2306 m_record->addPID(*i);
2308 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2309 m_record->removePID(*i);
2313 void eDVBServicePlay::switchToLive()
2315 if (!m_timeshift_active)
2321 m_teletext_parser = 0;
2323 m_subtitle_parser = 0;
2324 m_new_dvb_subtitle_page_connection = 0;
2325 m_new_subtitle_page_connection = 0;
2326 m_rds_decoder_event_connection = 0;
2327 m_video_event_connection = 0;
2329 /* free the timeshift service handler, we need the resources */
2330 m_service_handler_timeshift.free();
2331 m_timeshift_active = 0;
2333 m_event((iPlayableService*)this, evSeekableStatusChanged);
2338 void eDVBServicePlay::switchToTimeshift()
2340 if (m_timeshift_active)
2345 m_teletext_parser = 0;
2347 m_subtitle_parser = 0;
2348 m_new_subtitle_page_connection = 0;
2349 m_new_dvb_subtitle_page_connection = 0;
2350 m_rds_decoder_event_connection = 0;
2351 m_video_event_connection = 0;
2353 m_timeshift_active = 1;
2355 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2356 r.path = m_timeshift_file;
2358 m_cue = new eCueSheet();
2359 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2361 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2363 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2365 m_event((iPlayableService*)this, evSeekableStatusChanged);
2368 void eDVBServicePlay::updateDecoder()
2370 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2372 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2374 eDVBServicePMTHandler::program program;
2375 if (h.getProgramInfo(program))
2376 eDebug("getting program info failed.");
2379 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2380 if (!program.videoStreams.empty())
2382 eDebugNoNewLine(" (");
2383 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2384 i(program.videoStreams.begin());
2385 i != program.videoStreams.end(); ++i)
2392 if (i != program.videoStreams.begin())
2393 eDebugNoNewLine(", ");
2394 eDebugNoNewLine("%04x", i->pid);
2396 eDebugNoNewLine(")");
2398 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2399 if (!program.audioStreams.empty())
2401 eDebugNoNewLine(" (");
2402 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2403 i(program.audioStreams.begin());
2404 i != program.audioStreams.end(); ++i)
2406 if (i != program.audioStreams.begin())
2407 eDebugNoNewLine(", ");
2408 eDebugNoNewLine("%04x", i->pid);
2410 eDebugNoNewLine(")");
2412 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2413 pcrpid = program.pcrPid;
2414 eDebug(", and the text pid is %04x", program.textPid);
2415 tpid = program.textPid;
2420 h.getDecodeDemux(m_decode_demux);
2423 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2425 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2426 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2427 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2428 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2429 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2432 m_teletext_parser = 0;
2433 m_subtitle_parser = 0;
2437 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2444 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2445 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2446 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2448 else // subservice or recording
2450 eServiceReferenceDVB ref;
2451 m_service_handler.getServiceReference(ref);
2452 eServiceReferenceDVB parent = ref.getParentServiceReference();
2457 ePtr<eDVBResourceManager> res_mgr;
2458 if (!eDVBResourceManager::getInstance(res_mgr))
2460 ePtr<iDVBChannelList> db;
2461 if (!res_mgr->getChannelList(db))
2463 ePtr<eDVBService> origService;
2464 if (!db->getService(parent, origService))
2466 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2467 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2473 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2474 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2476 m_decoder->setVideoPID(vpid, vpidtype);
2477 selectAudioStream();
2479 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2480 m_decoder->setSyncPCR(pcrpid);
2482 m_decoder->setSyncPCR(-1);
2484 m_decoder->setTextPID(tpid);
2486 m_teletext_parser->start(program.textPid);
2489 m_decoder->setTrickmode(1);
2492 m_decoder->preroll();
2496 if (vpid > 0 && vpid < 0x2000)
2500 std::string radio_pic;
2501 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2502 m_decoder->setRadioPic(radio_pic);
2505 m_decoder->setAudioChannel(achannel);
2507 /* don't worry about non-existing services, nor pvr services */
2508 if (m_dvb_service && !m_is_pvr)
2510 /* (audio pid will be set in selectAudioTrack */
2511 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2512 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2513 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2514 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2517 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2520 void eDVBServicePlay::loadCuesheet()
2522 std::string filename = m_reference.path + ".cuts";
2524 m_cue_entries.clear();
2526 FILE *f = fopen(filename.c_str(), "rb");
2530 eDebug("loading cuts..");
2533 unsigned long long where;
2536 if (!fread(&where, sizeof(where), 1, f))
2538 if (!fread(&what, sizeof(what), 1, f))
2541 #if BYTE_ORDER == LITTLE_ENDIAN
2542 where = bswap_64(where);
2549 m_cue_entries.insert(cueEntry(where, what));
2552 eDebug("%d entries", m_cue_entries.size());
2554 eDebug("cutfile not found!");
2556 m_cuesheet_changed = 0;
2557 cutlistToCuesheet();
2558 m_event((iPlayableService*)this, evCuesheetChanged);
2561 void eDVBServicePlay::saveCuesheet()
2563 std::string filename = m_reference.path + ".cuts";
2565 FILE *f = fopen(filename.c_str(), "wb");
2569 unsigned long long where;
2572 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2574 #if BYTE_ORDER == BIG_ENDIAN
2577 where = bswap_64(i->where);
2579 what = htonl(i->what);
2580 fwrite(&where, sizeof(where), 1, f);
2581 fwrite(&what, sizeof(what), 1, f);
2587 m_cuesheet_changed = 0;
2590 void eDVBServicePlay::cutlistToCuesheet()
2594 eDebug("no cue sheet");
2599 if (!m_cutlist_enabled)
2601 m_cue->commitSpans();
2602 eDebug("cutlists were disabled");
2606 pts_t in = 0, out = 0, length = 0;
2610 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2614 if (i == m_cue_entries.end())
2617 if (i->what == 0) /* in */
2621 } else if (i->what == 1) /* out */
2623 else /* mark (2) or last play position (3) */
2640 m_cue->addSourceSpan(in, out);
2644 if (i == m_cue_entries.end())
2647 m_cue->commitSpans();
2650 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2652 if (m_subtitle_widget)
2653 disableSubtitles(parent);
2656 int tuplesize = PyTuple_Size(tuple);
2659 if (!PyTuple_Check(tuple))
2665 entry = PyTuple_GET_ITEM(tuple, 0);
2667 if (!PyInt_Check(entry))
2670 type = PyInt_AsLong(entry);
2672 if (type == 1) // teletext subtitles
2674 int page, magazine, pid;
2678 if (!m_teletext_parser)
2680 eDebug("enable teletext subtitles.. no parser !!!");
2684 entry = PyTuple_GET_ITEM(tuple, 1);
2685 if (!PyInt_Check(entry))
2687 pid = PyInt_AsLong(entry);
2689 entry = PyTuple_GET_ITEM(tuple, 2);
2690 if (!PyInt_Check(entry))
2692 page = PyInt_AsLong(entry);
2694 entry = PyTuple_GET_ITEM(tuple, 3);
2695 if (!PyInt_Check(entry))
2697 magazine = PyInt_AsLong(entry);
2699 m_subtitle_widget = new eSubtitleWidget(parent);
2700 m_subtitle_widget->resize(parent->size()); /* full size */
2701 m_teletext_parser->setPageAndMagazine(page, magazine);
2703 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2707 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2708 if (!m_subtitle_parser)
2710 eDebug("enable dvb subtitles.. no parser !!!");
2716 entry = PyTuple_GET_ITEM(tuple, 1);
2717 if (!PyInt_Check(entry))
2719 pid = PyInt_AsLong(entry);
2721 entry = PyTuple_GET_ITEM(tuple, 2);
2722 if (!PyInt_Check(entry))
2724 composition_page_id = PyInt_AsLong(entry);
2726 entry = PyTuple_GET_ITEM(tuple, 3);
2727 if (!PyInt_Check(entry))
2729 ancillary_page_id = PyInt_AsLong(entry);
2731 m_subtitle_widget = new eSubtitleWidget(parent);
2732 m_subtitle_widget->resize(parent->size()); /* full size */
2733 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2735 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2741 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2742 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2743 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2747 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2749 delete m_subtitle_widget;
2750 m_subtitle_widget = 0;
2751 if (m_subtitle_parser)
2753 m_subtitle_parser->stop();
2754 m_dvb_subtitle_pages.clear();
2756 if (m_teletext_parser)
2758 m_teletext_parser->setPageAndMagazine(-1, -1);
2759 m_subtitle_pages.clear();
2762 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2766 PyObject *eDVBServicePlay::getCachedSubtitle()
2770 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2773 unsigned int data = (unsigned int)tmp;
2774 int pid = (data&0xFFFF0000)>>16;
2775 ePyObject tuple = PyTuple_New(4);
2776 eDVBServicePMTHandler::program program;
2777 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2778 if (!h.getProgramInfo(program))
2780 if (program.textPid==pid) // teletext
2781 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2783 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2784 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2785 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2786 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2794 PyObject *eDVBServicePlay::getSubtitleList()
2796 if (!m_teletext_parser)
2799 ePyObject l = PyList_New(0);
2800 std::set<int> added_ttx_pages;
2802 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2803 m_teletext_parser->m_found_subtitle_pages;
2805 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2806 eDVBServicePMTHandler::program program;
2807 if (h.getProgramInfo(program))
2808 eDebug("getting program info failed.");
2811 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2812 it != program.subtitleStreams.end(); ++it)
2814 switch(it->subtitling_type)
2816 case 0x01: // ebu teletext subtitles
2818 int page_number = it->teletext_page_number & 0xFF;
2819 int magazine_number = it->teletext_magazine_number & 7;
2820 int hash = magazine_number << 8 | page_number;
2821 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2823 ePyObject tuple = PyTuple_New(5);
2824 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2825 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2826 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2827 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2828 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2829 PyList_Append(l, tuple);
2831 added_ttx_pages.insert(hash);
2836 case 0x20 ... 0x23: // dvb subtitles
2838 ePyObject tuple = PyTuple_New(5);
2839 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2840 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2841 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2842 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2843 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2844 PyList_Insert(l, 0, tuple);
2852 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2853 it != subs.end(); ++it)
2855 int page_number = it->teletext_page_number & 0xFF;
2856 int magazine_number = it->teletext_magazine_number & 7;
2857 int hash = magazine_number << 8 | page_number;
2858 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2860 ePyObject tuple = PyTuple_New(5);
2861 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2862 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2863 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2864 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2865 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2866 PyList_Append(l, tuple);
2874 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2876 if (m_subtitle_widget)
2880 m_decoder->getPTS(0, pos);
2881 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2882 m_subtitle_pages.push_back(page);
2883 checkSubtitleTiming();
2887 void eDVBServicePlay::checkSubtitleTiming()
2889 eDebug("checkSubtitleTiming");
2890 if (!m_subtitle_widget)
2894 enum { TELETEXT, DVB } type;
2895 eDVBTeletextSubtitlePage page;
2896 eDVBSubtitlePage dvb_page;
2898 if (!m_subtitle_pages.empty())
2900 page = m_subtitle_pages.front();
2902 show_time = page.m_pts;
2904 else if (!m_dvb_subtitle_pages.empty())
2906 dvb_page = m_dvb_subtitle_pages.front();
2908 show_time = dvb_page.m_show_time;
2916 m_decoder->getPTS(0, pos);
2918 eDebug("%lld %lld", pos, show_time);
2919 int diff = show_time - pos;
2922 eDebug("[late (%d ms)]", -diff / 90);
2925 // if (diff > 900000)
2927 // eDebug("[invalid]");
2933 if (type == TELETEXT)
2935 eDebug("display teletext subtitle page %lld", show_time);
2936 m_subtitle_widget->setPage(page);
2937 m_subtitle_pages.pop_front();
2941 eDebug("display dvb subtitle Page %lld", show_time);
2942 m_subtitle_widget->setPage(dvb_page);
2943 m_dvb_subtitle_pages.pop_front();
2947 eDebug("start subtitle delay %d", diff / 90);
2948 m_subtitle_sync_timer->start(diff / 90, 1);
2954 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2956 if (m_subtitle_widget)
2960 m_decoder->getPTS(0, pos);
2961 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2962 m_dvb_subtitle_pages.push_back(p);
2963 checkSubtitleTiming();
2967 int eDVBServicePlay::getAC3Delay()
2970 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2972 return m_decoder->getAC3Delay();
2977 int eDVBServicePlay::getPCMDelay()
2980 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2982 return m_decoder->getPCMDelay();
2987 void eDVBServicePlay::setAC3Delay(int delay)
2990 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2992 m_decoder->setAC3Delay(delay);
2995 void eDVBServicePlay::setPCMDelay(int delay)
2998 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3000 m_decoder->setPCMDelay(delay);
3003 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3005 memcpy(&m_videoEventData, &event, sizeof(event));
3006 switch(event.type) {
3007 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3008 m_event((iPlayableService*)this, evVideoSizeChanged);
3010 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3011 m_event((iPlayableService*)this, evVideoFramerateChanged);
3013 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3014 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3021 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3027 PyObject *eDVBServicePlay::getStreamingData()
3029 eDVBServicePMTHandler::program program;
3030 if (m_service_handler.getProgramInfo(program))
3036 PyObject *r = program.createPythonObject();
3037 ePtr<iDVBDemux> demux;
3038 if (!m_service_handler.getDataDemux(demux))
3041 demux->getCADemuxID(demux_id);
3043 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
3050 DEFINE_REF(eDVBServicePlay)
3052 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3056 case iServiceInformation::sTransponderData:
3057 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3061 return iStaticServiceInformation::getInfoObject(ref, w);
3064 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");