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 assert(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1285 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1286 setFastForward_internal(0);
1288 return m_decoder->setSlowMotion(ratio);
1293 RESULT eDVBServicePlay::setFastForward(int ratio)
1295 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1297 return setFastForward_internal(ratio);
1300 RESULT eDVBServicePlay::setFastForward_internal(int ratio)
1302 int skipmode, ffratio;
1308 } else if (ratio > 0)
1316 } else // if (ratio < 0)
1322 if (m_skipmode != skipmode)
1324 eDebug("setting cue skipmode to %d", skipmode);
1326 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1329 m_skipmode = skipmode;
1336 else if (ffratio != 1)
1337 return m_decoder->setFastForward(ffratio);
1339 return m_decoder->setTrickmode();
1342 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1344 if (m_is_pvr || m_timeshift_enabled)
1354 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1355 RESULT eDVBServicePlay::getLength(pts_t &len)
1357 ePtr<iDVBPVRChannel> pvr_channel;
1359 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1362 return pvr_channel->getLength(len);
1365 RESULT eDVBServicePlay::pause()
1367 eDebug("eDVBServicePlay::pause");
1368 setFastForward_internal(0);
1371 return m_decoder->pause();
1376 RESULT eDVBServicePlay::unpause()
1378 eDebug("eDVBServicePlay::unpause");
1379 setFastForward_internal(0);
1382 return m_decoder->play();
1387 RESULT eDVBServicePlay::seekTo(pts_t to)
1389 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1391 if (!m_decode_demux)
1394 ePtr<iDVBPVRChannel> pvr_channel;
1396 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1402 m_cue->seekTo(0, to);
1403 m_dvb_subtitle_pages.clear();
1404 m_subtitle_pages.clear();
1409 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1411 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1413 if (!m_decode_demux)
1416 ePtr<iDVBPVRChannel> pvr_channel;
1418 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1423 /* HACK until we have skip-AP api */
1424 if ((to > 0) && (to < 100))
1432 m_cue->seekTo(mode, to);
1433 m_dvb_subtitle_pages.clear();
1434 m_subtitle_pages.clear();
1438 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1440 ePtr<iDVBPVRChannel> pvr_channel;
1442 if (!m_decode_demux)
1445 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1450 /* if there is a decoder, use audio or video PTS */
1453 r = m_decoder->getPTS(0, pos);
1459 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1462 RESULT eDVBServicePlay::setTrickmode(int trick)
1464 /* currently unimplemented */
1468 RESULT eDVBServicePlay::isCurrentlySeekable()
1470 return m_is_pvr || m_timeshift_active;
1473 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1479 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1485 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1491 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1497 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1503 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1506 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1507 (m_timeshift_enabled || !m_is_pvr))
1509 if (!m_timeshift_enabled)
1511 /* query config path */
1513 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1514 eDebug("could not query ts path from config");
1518 /* we need enough diskspace */
1520 if (statfs(tspath.c_str(), &fs) < 0)
1522 eDebug("statfs failed!");
1526 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1528 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1538 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1549 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1555 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1561 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1567 RESULT eDVBServicePlay::getName(std::string &name)
1571 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1572 return i->getName(m_reference, name);
1576 m_dvb_service->getName(m_reference, name);
1580 else if (!m_reference.name.empty())
1581 eStaticServiceDVBInformation().getName(m_reference, name);
1583 name = "DVB service";
1587 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1589 return m_event_handler.getEvent(evt, nownext);
1592 static int readMpegProc(char *str, int decoder)
1596 sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
1597 FILE *f = fopen(tmp, "r");
1600 fscanf(f, "%x", &val);
1606 int eDVBServicePlay::getInfo(int w)
1608 eDVBServicePMTHandler::program program;
1611 return resIsPyObject;
1613 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1615 int no_program_info = 0;
1617 if (h.getProgramInfo(program))
1618 no_program_info = 1;
1622 #if HAVE_DVB_API_VERSION >= 3
1624 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1625 return m_videoEventData.height;
1627 return readMpegProc("yres", !m_is_primary);
1629 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1630 return m_videoEventData.width;
1632 return readMpegProc("xres", !m_is_primary);
1634 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventFrameRateChanged)
1635 return m_videoEventData.framerate;
1637 return readMpegProc("framerate", !m_is_primary);
1639 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventProgressiveChanged)
1640 return m_videoEventData.progressive;
1641 return readMpegProc("progressive", !m_is_primary);
1643 #warning "FIXMEE implement sFrameRate, sProgressive, sVideoHeight, sVideoWidth for old DVB API"
1648 #if HAVE_DVB_API_VERSION >= 3
1649 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1650 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1651 else if ((val=readMpegProc("aspect", !m_is_primary)) != -1)
1655 #warning "FIXMEE implement sAspect for old DVB API"
1657 if (no_program_info)
1659 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1661 ePtr<eServiceEvent> evt;
1662 if (!m_event_handler.getEvent(evt, 0))
1664 ePtr<eComponentData> data;
1665 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1667 if ( data->getStreamContent() == 1 )
1669 switch(data->getComponentType())
1672 case 1: // 4:3 SD PAL
1674 case 3: // 16:9 SD PAL
1675 case 4: // > 16:9 PAL
1676 case 5: // 4:3 SD NTSC
1678 case 7: // 16:9 SD NTSC
1679 case 8: // > 16:9 NTSC
1682 case 9: // 4:3 HD PAL
1684 case 0xB: // 16:9 HD PAL
1685 case 0xC: // > 16:9 HD PAL
1686 case 0xD: // 4:3 HD NTSC
1688 case 0xF: // 16:9 HD NTSC
1689 case 0x10: // > 16:9 HD PAL
1690 return data->getComponentType();
1698 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1699 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1700 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1701 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1702 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1703 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1704 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1705 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1706 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1707 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1708 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1709 case sProvider: if (!m_dvb_service) return -1; return -2;
1710 case sServiceref: return resIsString;
1711 case sDVBState: return m_tune_state;
1717 std::string eDVBServicePlay::getInfoString(int w)
1722 if (!m_dvb_service) return "";
1723 return m_dvb_service->m_provider_name;
1725 return m_reference.toString();
1729 return iServiceInformation::getInfoString(w);
1732 PyObject *eDVBServicePlay::getInfoObject(int w)
1737 return m_service_handler.getCaIds();
1738 case sTransponderData:
1739 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1743 return iServiceInformation::getInfoObject(w);
1746 int eDVBServicePlay::getNumberOfTracks()
1748 eDVBServicePMTHandler::program program;
1749 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1750 if (h.getProgramInfo(program))
1752 return program.audioStreams.size();
1755 int eDVBServicePlay::getCurrentTrack()
1757 eDVBServicePMTHandler::program program;
1758 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1759 if (h.getProgramInfo(program))
1762 int max = program.audioStreams.size();
1765 for (i = 0; i < max; ++i)
1766 if (program.audioStreams[i].pid == m_current_audio_pid)
1772 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1774 int ret = selectAudioStream(i);
1776 if (m_decoder->play())
1782 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1784 eDVBServicePMTHandler::program program;
1785 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1787 if (h.getProgramInfo(program))
1790 if (i >= program.audioStreams.size())
1793 info.m_pid = program.audioStreams[i].pid;
1795 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1796 info.m_description = "MPEG";
1797 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1798 info.m_description = "AC3";
1799 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1800 info.m_description = "AAC";
1801 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1802 info.m_description = "DTS";
1804 info.m_description = "???";
1806 if (program.audioStreams[i].component_tag != -1)
1808 ePtr<eServiceEvent> evt;
1809 if (!m_event_handler.getEvent(evt, 0))
1811 ePtr<eComponentData> data;
1812 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1813 info.m_language = data->getText();
1817 if (info.m_language.empty())
1818 info.m_language = program.audioStreams[i].language_code;
1823 int eDVBServicePlay::selectAudioStream(int i)
1825 eDVBServicePMTHandler::program program;
1826 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1828 if (h.getProgramInfo(program))
1831 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1839 stream = program.defaultAudioStream;
1841 int apid = -1, apidtype = -1;
1843 if (((unsigned int)stream) < program.audioStreams.size())
1845 apid = program.audioStreams[stream].pid;
1846 apidtype = program.audioStreams[stream].type;
1849 m_current_audio_pid = apid;
1851 if (m_decoder->setAudioPID(apid, apidtype))
1853 eDebug("set audio pid failed");
1857 /* 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 */
1858 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1861 ePtr<iDVBDemux> data_demux;
1862 if (!h.getDataDemux(data_demux))
1864 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1865 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1869 /* if we decided that we need one, update the pid */
1871 m_rds_decoder->start(apid);
1873 /* store new pid as default only when:
1874 a.) we have an entry in the service db for the current service,
1875 b.) we are not playing back something,
1876 c.) we are not selecting the default entry. (we wouldn't change
1877 anything in the best case, or destroy the default setting in
1878 case the real default is not yet available.)
1880 if (m_dvb_service && !m_is_pvr && ((i != -1)
1881 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1883 if (apidtype == eDVBAudio::aMPEG)
1885 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1886 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1890 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1891 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1895 h.resetCachedProgram();
1900 int eDVBServicePlay::getCurrentChannel()
1902 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1905 RESULT eDVBServicePlay::selectChannel(int i)
1907 if (i < LEFT || i > RIGHT || i == STEREO)
1910 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1912 m_decoder->setAudioChannel(i);
1916 std::string eDVBServicePlay::getText(int x)
1922 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1924 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1929 void eDVBServicePlay::rdsDecoderEvent(int what)
1933 case eDVBRdsDecoder::RadioTextChanged:
1934 m_event((iPlayableService*)this, evUpdatedRadioText);
1936 case eDVBRdsDecoder::RtpTextChanged:
1937 m_event((iPlayableService*)this, evUpdatedRtpText);
1939 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1940 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1942 case eDVBRdsDecoder::RecvRassSlidePic:
1943 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1948 void eDVBServicePlay::showRassSlidePicture()
1954 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1955 if (rass_slide_pic.length())
1956 m_decoder->showSinglePic(rass_slide_pic.c_str());
1958 eDebug("empty filename for rass slide picture received!!");
1961 eDebug("no MPEG Decoder to show iframes avail");
1964 eDebug("showRassSlidePicture called.. but not decoder");
1967 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1973 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1974 if (rass_interactive_pic.length())
1975 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1977 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1980 eDebug("no MPEG Decoder to show iframes avail");
1983 eDebug("showRassInteractivePic called.. but not decoder");
1986 ePyObject eDVBServicePlay::getRassInteractiveMask()
1989 return m_rds_decoder->getRassPictureMask();
1993 int eDVBServiceBase::getFrontendInfo(int w)
1995 eUsePtr<iDVBChannel> channel;
1996 if(m_service_handler.getChannel(channel))
1998 ePtr<iDVBFrontend> fe;
1999 if(channel->getFrontend(fe))
2001 return fe->readFrontendData(w);
2004 PyObject *eDVBServiceBase::getFrontendData()
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->getFrontendData(ret);
2022 PyObject *eDVBServiceBase::getFrontendStatus()
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))
2032 fe->getFrontendStatus(ret);
2040 PyObject *eDVBServiceBase::getTransponderData(bool original)
2042 ePyObject ret = PyDict_New();
2045 eUsePtr<iDVBChannel> channel;
2046 if(!m_service_handler.getChannel(channel))
2048 ePtr<iDVBFrontend> fe;
2049 if(!channel->getFrontend(fe))
2051 fe->getTransponderData(ret, original);
2052 ePtr<iDVBFrontendParameters> feparm;
2053 channel->getCurrentFrontendParameters(feparm);
2056 eDVBFrontendParametersSatellite osat;
2057 if (!feparm->getDVBS(osat))
2059 void PutToDict(ePyObject &, const char*, long);
2060 void PutToDict(ePyObject &, const char*, const char*);
2061 PutToDict(ret, "orbital_position", osat.orbital_position);
2062 const char *tmp = "UNKNOWN";
2063 switch(osat.polarisation)
2065 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2066 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2067 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2068 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2071 PutToDict(ret, "polarization", tmp);
2082 PyObject *eDVBServiceBase::getAll(bool original)
2084 ePyObject ret = getTransponderData(original);
2087 eUsePtr<iDVBChannel> channel;
2088 if(!m_service_handler.getChannel(channel))
2090 ePtr<iDVBFrontend> fe;
2091 if(!channel->getFrontend(fe))
2093 fe->getFrontendData(ret);
2094 fe->getFrontendStatus(ret);
2101 int eDVBServicePlay::getNumberOfSubservices()
2103 ePtr<eServiceEvent> evt;
2104 if (!m_event_handler.getEvent(evt, 0))
2105 return evt->getNumOfLinkageServices();
2109 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2111 ePtr<eServiceEvent> evt;
2112 if (!m_event_handler.getEvent(evt, 0))
2114 if (!evt->getLinkageService(sub, m_reference, n))
2117 sub.type=eServiceReference::idInvalid;
2121 RESULT eDVBServicePlay::startTimeshift()
2123 ePtr<iDVBDemux> demux;
2125 eDebug("Start timeshift!");
2127 if (m_timeshift_enabled)
2130 /* start recording with the data demux. */
2131 if (m_service_handler.getDataDemux(demux))
2134 demux->createTSRecorder(m_record);
2139 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2140 eDebug("could not query ts path");
2143 tspath.append("/timeshift.XXXXXX");
2145 templ = new char[tspath.length() + 1];
2146 strcpy(templ, tspath.c_str());
2148 m_timeshift_fd = mkstemp(templ);
2149 m_timeshift_file = std::string(templ);
2151 eDebug("recording to %s", templ);
2155 if (m_timeshift_fd < 0)
2161 m_record->setTargetFD(m_timeshift_fd);
2163 m_timeshift_enabled = 1;
2165 updateTimeshiftPids();
2171 RESULT eDVBServicePlay::stopTimeshift()
2173 if (!m_timeshift_enabled)
2178 m_timeshift_enabled = 0;
2183 close(m_timeshift_fd);
2184 eDebug("remove timeshift file");
2185 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2190 int eDVBServicePlay::isTimeshiftActive()
2192 return m_timeshift_enabled && m_timeshift_active;
2195 RESULT eDVBServicePlay::activateTimeshift()
2197 if (!m_timeshift_enabled)
2200 if (!m_timeshift_active)
2202 switchToTimeshift();
2209 PyObject *eDVBServicePlay::getCutList()
2211 ePyObject list = PyList_New(0);
2213 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2215 ePyObject tuple = PyTuple_New(2);
2216 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2217 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2218 PyList_Append(list, tuple);
2225 void eDVBServicePlay::setCutList(ePyObject list)
2227 if (!PyList_Check(list))
2229 int size = PyList_Size(list);
2232 m_cue_entries.clear();
2234 for (i=0; i<size; ++i)
2236 ePyObject tuple = PyList_GET_ITEM(list, i);
2237 if (!PyTuple_Check(tuple))
2239 eDebug("non-tuple in cutlist");
2242 if (PyTuple_Size(tuple) != 2)
2244 eDebug("cutlist entries need to be a 2-tuple");
2247 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2248 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2250 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2253 pts_t pts = PyLong_AsLongLong(ppts);
2254 int type = PyInt_AsLong(ptype);
2255 m_cue_entries.insert(cueEntry(pts, type));
2256 eDebug("adding %08llx, %d", pts, type);
2258 m_cuesheet_changed = 1;
2260 cutlistToCuesheet();
2261 m_event((iPlayableService*)this, evCuesheetChanged);
2264 void eDVBServicePlay::setCutListEnable(int enable)
2266 m_cutlist_enabled = enable;
2267 cutlistToCuesheet();
2270 void eDVBServicePlay::updateTimeshiftPids()
2275 eDVBServicePMTHandler::program program;
2276 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2278 if (h.getProgramInfo(program))
2282 std::set<int> pids_to_record;
2283 pids_to_record.insert(0); // PAT
2284 if (program.pmtPid != -1)
2285 pids_to_record.insert(program.pmtPid); // PMT
2287 if (program.textPid != -1)
2288 pids_to_record.insert(program.textPid); // Videotext
2290 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2291 i(program.videoStreams.begin());
2292 i != program.videoStreams.end(); ++i)
2293 pids_to_record.insert(i->pid);
2295 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2296 i(program.audioStreams.begin());
2297 i != program.audioStreams.end(); ++i)
2298 pids_to_record.insert(i->pid);
2300 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2301 i(program.subtitleStreams.begin());
2302 i != program.subtitleStreams.end(); ++i)
2303 pids_to_record.insert(i->pid);
2305 std::set<int> new_pids, obsolete_pids;
2307 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2308 m_pids_active.begin(), m_pids_active.end(),
2309 std::inserter(new_pids, new_pids.begin()));
2311 std::set_difference(
2312 m_pids_active.begin(), m_pids_active.end(),
2313 pids_to_record.begin(), pids_to_record.end(),
2314 std::inserter(new_pids, new_pids.begin())
2317 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2318 m_record->addPID(*i);
2320 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2321 m_record->removePID(*i);
2325 void eDVBServicePlay::switchToLive()
2327 if (!m_timeshift_active)
2333 m_teletext_parser = 0;
2335 m_subtitle_parser = 0;
2336 m_new_dvb_subtitle_page_connection = 0;
2337 m_new_subtitle_page_connection = 0;
2338 m_rds_decoder_event_connection = 0;
2339 m_video_event_connection = 0;
2341 /* free the timeshift service handler, we need the resources */
2342 m_service_handler_timeshift.free();
2343 m_timeshift_active = 0;
2345 m_event((iPlayableService*)this, evSeekableStatusChanged);
2350 void eDVBServicePlay::switchToTimeshift()
2352 if (m_timeshift_active)
2357 m_teletext_parser = 0;
2359 m_subtitle_parser = 0;
2360 m_new_subtitle_page_connection = 0;
2361 m_new_dvb_subtitle_page_connection = 0;
2362 m_rds_decoder_event_connection = 0;
2363 m_video_event_connection = 0;
2365 m_timeshift_active = 1;
2367 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2368 r.path = m_timeshift_file;
2370 m_cue = new eCueSheet();
2371 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2373 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2375 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2377 m_event((iPlayableService*)this, evSeekableStatusChanged);
2380 void eDVBServicePlay::updateDecoder()
2382 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2384 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2386 eDVBServicePMTHandler::program program;
2387 if (h.getProgramInfo(program))
2388 eDebug("getting program info failed.");
2391 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2392 if (!program.videoStreams.empty())
2394 eDebugNoNewLine(" (");
2395 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2396 i(program.videoStreams.begin());
2397 i != program.videoStreams.end(); ++i)
2404 if (i != program.videoStreams.begin())
2405 eDebugNoNewLine(", ");
2406 eDebugNoNewLine("%04x", i->pid);
2408 eDebugNoNewLine(")");
2410 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2411 if (!program.audioStreams.empty())
2413 eDebugNoNewLine(" (");
2414 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2415 i(program.audioStreams.begin());
2416 i != program.audioStreams.end(); ++i)
2418 if (i != program.audioStreams.begin())
2419 eDebugNoNewLine(", ");
2420 eDebugNoNewLine("%04x", i->pid);
2422 eDebugNoNewLine(")");
2424 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2425 pcrpid = program.pcrPid;
2426 eDebug(", and the text pid is %04x", program.textPid);
2427 tpid = program.textPid;
2432 h.getDecodeDemux(m_decode_demux);
2435 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2437 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2438 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2439 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2440 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2441 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2444 m_teletext_parser = 0;
2445 m_subtitle_parser = 0;
2449 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2456 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2457 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2458 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2460 else // subservice or recording
2462 eServiceReferenceDVB ref;
2463 m_service_handler.getServiceReference(ref);
2464 eServiceReferenceDVB parent = ref.getParentServiceReference();
2469 ePtr<eDVBResourceManager> res_mgr;
2470 if (!eDVBResourceManager::getInstance(res_mgr))
2472 ePtr<iDVBChannelList> db;
2473 if (!res_mgr->getChannelList(db))
2475 ePtr<eDVBService> origService;
2476 if (!db->getService(parent, origService))
2478 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2479 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2485 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2486 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2488 m_decoder->setVideoPID(vpid, vpidtype);
2489 selectAudioStream();
2491 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2492 m_decoder->setSyncPCR(pcrpid);
2494 m_decoder->setSyncPCR(-1);
2496 m_decoder->setTextPID(tpid);
2498 m_teletext_parser->start(program.textPid);
2501 m_decoder->setTrickmode();
2508 if (vpid > 0 && vpid < 0x2000)
2512 std::string radio_pic;
2513 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2514 m_decoder->setRadioPic(radio_pic);
2517 m_decoder->setAudioChannel(achannel);
2519 /* don't worry about non-existing services, nor pvr services */
2520 if (m_dvb_service && !m_is_pvr)
2522 /* (audio pid will be set in selectAudioTrack */
2523 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2524 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2525 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2526 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2529 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2532 void eDVBServicePlay::loadCuesheet()
2534 std::string filename = m_reference.path + ".cuts";
2536 m_cue_entries.clear();
2538 FILE *f = fopen(filename.c_str(), "rb");
2542 eDebug("loading cuts..");
2545 unsigned long long where;
2548 if (!fread(&where, sizeof(where), 1, f))
2550 if (!fread(&what, sizeof(what), 1, f))
2553 #if BYTE_ORDER == LITTLE_ENDIAN
2554 where = bswap_64(where);
2561 m_cue_entries.insert(cueEntry(where, what));
2564 eDebug("%d entries", m_cue_entries.size());
2566 eDebug("cutfile not found!");
2568 m_cuesheet_changed = 0;
2569 cutlistToCuesheet();
2570 m_event((iPlayableService*)this, evCuesheetChanged);
2573 void eDVBServicePlay::saveCuesheet()
2575 std::string filename = m_reference.path + ".cuts";
2577 FILE *f = fopen(filename.c_str(), "wb");
2581 unsigned long long where;
2584 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2586 #if BYTE_ORDER == BIG_ENDIAN
2589 where = bswap_64(i->where);
2591 what = htonl(i->what);
2592 fwrite(&where, sizeof(where), 1, f);
2593 fwrite(&what, sizeof(what), 1, f);
2599 m_cuesheet_changed = 0;
2602 void eDVBServicePlay::cutlistToCuesheet()
2606 eDebug("no cue sheet");
2611 if (!m_cutlist_enabled)
2613 m_cue->commitSpans();
2614 eDebug("cutlists were disabled");
2618 pts_t in = 0, out = 0, length = 0;
2622 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2626 if (i == m_cue_entries.end())
2629 if (i->what == 0) /* in */
2633 } else if (i->what == 1) /* out */
2635 else /* mark (2) or last play position (3) */
2652 m_cue->addSourceSpan(in, out);
2656 if (i == m_cue_entries.end())
2659 m_cue->commitSpans();
2662 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2664 if (m_subtitle_widget)
2665 disableSubtitles(parent);
2668 int tuplesize = PyTuple_Size(tuple);
2671 if (!PyTuple_Check(tuple))
2677 entry = PyTuple_GET_ITEM(tuple, 0);
2679 if (!PyInt_Check(entry))
2682 type = PyInt_AsLong(entry);
2684 if (type == 1) // teletext subtitles
2686 int page, magazine, pid;
2690 if (!m_teletext_parser)
2692 eDebug("enable teletext subtitles.. no parser !!!");
2696 entry = PyTuple_GET_ITEM(tuple, 1);
2697 if (!PyInt_Check(entry))
2699 pid = PyInt_AsLong(entry);
2701 entry = PyTuple_GET_ITEM(tuple, 2);
2702 if (!PyInt_Check(entry))
2704 page = PyInt_AsLong(entry);
2706 entry = PyTuple_GET_ITEM(tuple, 3);
2707 if (!PyInt_Check(entry))
2709 magazine = PyInt_AsLong(entry);
2711 m_subtitle_widget = new eSubtitleWidget(parent);
2712 m_subtitle_widget->resize(parent->size()); /* full size */
2713 m_teletext_parser->setPageAndMagazine(page, magazine);
2715 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2719 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2720 if (!m_subtitle_parser)
2722 eDebug("enable dvb subtitles.. no parser !!!");
2728 entry = PyTuple_GET_ITEM(tuple, 1);
2729 if (!PyInt_Check(entry))
2731 pid = PyInt_AsLong(entry);
2733 entry = PyTuple_GET_ITEM(tuple, 2);
2734 if (!PyInt_Check(entry))
2736 composition_page_id = PyInt_AsLong(entry);
2738 entry = PyTuple_GET_ITEM(tuple, 3);
2739 if (!PyInt_Check(entry))
2741 ancillary_page_id = PyInt_AsLong(entry);
2743 m_subtitle_widget = new eSubtitleWidget(parent);
2744 m_subtitle_widget->resize(parent->size()); /* full size */
2745 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2747 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2753 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2754 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2755 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2759 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2761 delete m_subtitle_widget;
2762 m_subtitle_widget = 0;
2763 if (m_subtitle_parser)
2765 m_subtitle_parser->stop();
2766 m_dvb_subtitle_pages.clear();
2768 if (m_teletext_parser)
2770 m_teletext_parser->setPageAndMagazine(-1, -1);
2771 m_subtitle_pages.clear();
2774 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2778 PyObject *eDVBServicePlay::getCachedSubtitle()
2782 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2785 unsigned int data = (unsigned int)tmp;
2786 int pid = (data&0xFFFF0000)>>16;
2787 ePyObject tuple = PyTuple_New(4);
2788 eDVBServicePMTHandler::program program;
2789 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2790 if (!h.getProgramInfo(program))
2792 if (program.textPid==pid) // teletext
2793 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2795 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2796 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2797 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2798 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2806 PyObject *eDVBServicePlay::getSubtitleList()
2808 if (!m_teletext_parser)
2811 ePyObject l = PyList_New(0);
2812 std::set<int> added_ttx_pages;
2814 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2815 m_teletext_parser->m_found_subtitle_pages;
2817 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2818 eDVBServicePMTHandler::program program;
2819 if (h.getProgramInfo(program))
2820 eDebug("getting program info failed.");
2823 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2824 it != program.subtitleStreams.end(); ++it)
2826 switch(it->subtitling_type)
2828 case 0x01: // ebu teletext subtitles
2830 int page_number = it->teletext_page_number & 0xFF;
2831 int magazine_number = it->teletext_magazine_number & 7;
2832 int hash = magazine_number << 8 | page_number;
2833 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2835 ePyObject tuple = PyTuple_New(5);
2836 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2837 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2838 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2839 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2840 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2841 PyList_Append(l, tuple);
2843 added_ttx_pages.insert(hash);
2848 case 0x20 ... 0x23: // dvb subtitles
2850 ePyObject tuple = PyTuple_New(5);
2851 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2852 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2853 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2854 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2855 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2856 PyList_Insert(l, 0, tuple);
2864 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2865 it != subs.end(); ++it)
2867 int page_number = it->teletext_page_number & 0xFF;
2868 int magazine_number = it->teletext_magazine_number & 7;
2869 int hash = magazine_number << 8 | page_number;
2870 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2872 ePyObject tuple = PyTuple_New(5);
2873 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2874 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2875 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2876 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2877 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2878 PyList_Append(l, tuple);
2886 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2888 if (m_subtitle_widget)
2892 m_decoder->getPTS(0, pos);
2893 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2894 m_subtitle_pages.push_back(page);
2895 checkSubtitleTiming();
2899 void eDVBServicePlay::checkSubtitleTiming()
2901 eDebug("checkSubtitleTiming");
2902 if (!m_subtitle_widget)
2906 enum { TELETEXT, DVB } type;
2907 eDVBTeletextSubtitlePage page;
2908 eDVBSubtitlePage dvb_page;
2910 if (!m_subtitle_pages.empty())
2912 page = m_subtitle_pages.front();
2914 show_time = page.m_pts;
2916 else if (!m_dvb_subtitle_pages.empty())
2918 dvb_page = m_dvb_subtitle_pages.front();
2920 show_time = dvb_page.m_show_time;
2928 m_decoder->getPTS(0, pos);
2930 eDebug("%lld %lld", pos, show_time);
2931 int diff = show_time - pos;
2934 eDebug("[late (%d ms)]", -diff / 90);
2937 // if (diff > 900000)
2939 // eDebug("[invalid]");
2945 if (type == TELETEXT)
2947 eDebug("display teletext subtitle page %lld", show_time);
2948 m_subtitle_widget->setPage(page);
2949 m_subtitle_pages.pop_front();
2953 eDebug("display dvb subtitle Page %lld", show_time);
2954 m_subtitle_widget->setPage(dvb_page);
2955 m_dvb_subtitle_pages.pop_front();
2959 eDebug("start subtitle delay %d", diff / 90);
2960 m_subtitle_sync_timer->start(diff / 90, 1);
2966 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2968 if (m_subtitle_widget)
2972 m_decoder->getPTS(0, pos);
2973 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2974 m_dvb_subtitle_pages.push_back(p);
2975 checkSubtitleTiming();
2979 int eDVBServicePlay::getAC3Delay()
2982 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2984 return m_decoder->getAC3Delay();
2989 int eDVBServicePlay::getPCMDelay()
2992 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2994 return m_decoder->getPCMDelay();
2999 void eDVBServicePlay::setAC3Delay(int delay)
3002 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3004 m_decoder->setAC3Delay(delay);
3007 void eDVBServicePlay::setPCMDelay(int delay)
3010 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3012 m_decoder->setPCMDelay(delay);
3015 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3017 memcpy(&m_videoEventData, &event, sizeof(event));
3018 switch(event.type) {
3019 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3020 m_event((iPlayableService*)this, evVideoSizeChanged);
3022 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3023 m_event((iPlayableService*)this, evVideoFramerateChanged);
3025 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3026 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3033 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3039 PyObject *eDVBServicePlay::getStreamingData()
3041 eDVBServicePMTHandler::program program;
3042 if (m_service_handler.getProgramInfo(program))
3048 PyObject *r = program.createPythonObject();
3049 ePtr<iDVBDemux> demux;
3050 if (!m_service_handler.getDataDemux(demux))
3053 demux->getCADemuxID(demux_id);
3055 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
3062 DEFINE_REF(eDVBServicePlay)
3064 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3068 case iServiceInformation::sTransponderData:
3069 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3073 return iStaticServiceInformation::getInfoObject(ref, w);
3076 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");