1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 #define TSPATH "/media/hdd"
36 class eStaticServiceDVBInformation: public iStaticServiceInformation
38 DECLARE_REF(eStaticServiceDVBInformation);
40 RESULT getName(const eServiceReference &ref, std::string &name);
41 int getLength(const eServiceReference &ref);
42 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
43 PyObject *getInfoObject(const eServiceReference &ref, int);
46 DEFINE_REF(eStaticServiceDVBInformation);
48 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
50 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
51 if ( !ref.name.empty() )
53 if (service.getParentTransportStreamID().get()) // linkage subservice
55 ePtr<iServiceHandler> service_center;
56 if (!eServiceCenter::getInstance(service_center))
58 eServiceReferenceDVB parent = service;
59 parent.setTransportStreamID( service.getParentTransportStreamID() );
60 parent.setServiceID( service.getParentServiceID() );
61 parent.setParentTransportStreamID(eTransportStreamID(0));
62 parent.setParentServiceID(eServiceID(0));
64 ePtr<iStaticServiceInformation> service_info;
65 if (!service_center->info(parent, service_info))
67 if (!service_info->getName(parent, name))
68 name=buildShortName(name) + " - ";
81 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
86 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
88 ePtr<eDVBResourceManager> res_mgr;
89 if ( eDVBResourceManager::getInstance( res_mgr ) )
90 eDebug("isPlayable... no res manager!!");
93 eDVBChannelID chid, chid_ignore;
94 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
95 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
96 return res_mgr->canAllocateChannel(chid, chid_ignore);
101 static void PutToDict(ePyObject &dict, const char*key, long value)
103 ePyObject item = PyString_FromFormat("%d", value);
106 if (PyDict_SetItemString(dict, key, item))
107 eDebug("put %s to dict failed", key);
111 eDebug("could not create PyObject for %s", key);
114 extern void PutToDict(ePyObject &dict, const char*key, const char *value);
116 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
119 PutToDict(dict, "type", "Satellite");
120 PutToDict(dict, "frequency", feparm.frequency);
121 PutToDict(dict, "symbolrate", feparm.symbol_rate);
122 PutToDict(dict, "orbital position", feparm.orbital_position);
123 switch (feparm.inversion)
125 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
126 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
128 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
130 PutToDict(dict, "inversion", tmp);
133 case eDVBFrontendParametersSatellite::FEC::fNone: tmp="NONE"; break;
134 case eDVBFrontendParametersSatellite::FEC::f1_2: tmp="1/2"; break;
135 case eDVBFrontendParametersSatellite::FEC::f2_3: tmp="2/3"; break;
136 case eDVBFrontendParametersSatellite::FEC::f3_4: tmp="3/4"; break;
137 case eDVBFrontendParametersSatellite::FEC::f5_6: tmp="5/6"; break;
138 case eDVBFrontendParametersSatellite::FEC::f7_8: tmp="7/8"; break;
139 case eDVBFrontendParametersSatellite::FEC::f3_5: tmp="3/5"; break;
140 case eDVBFrontendParametersSatellite::FEC::f4_5: tmp="4/5"; break;
141 case eDVBFrontendParametersSatellite::FEC::f8_9: tmp="8/9"; break;
142 case eDVBFrontendParametersSatellite::FEC::f9_10: tmp="9/10"; break;
144 case eDVBFrontendParametersSatellite::FEC::fAuto: tmp="AUTO"; break;
146 PutToDict(dict, "fec inner", tmp);
147 switch (feparm.modulation)
149 case eDVBFrontendParametersSatellite::Modulation::Auto: tmp="AUTO"; break;
150 case eDVBFrontendParametersSatellite::Modulation::QPSK: tmp="QPSK"; break;
151 case eDVBFrontendParametersSatellite::Modulation::M8PSK: tmp="8PSK"; break;
152 case eDVBFrontendParametersSatellite::Modulation::QAM_16: tmp="QAM16"; break;
154 PutToDict(dict, "modulation", tmp);
155 switch(feparm.polarisation)
157 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
158 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
159 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR LEFT"; break;
161 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR RIGHT"; break;
163 PutToDict(dict, "polarization", tmp);
164 switch(feparm.system)
167 case eDVBFrontendParametersSatellite::System::DVB_S: tmp="DVB-S"; break;
168 case eDVBFrontendParametersSatellite::System::DVB_S2:
169 switch(feparm.roll_off)
171 case eDVBFrontendParametersSatellite::RollOff::alpha_0_35: tmp="0.35"; break;
172 case eDVBFrontendParametersSatellite::RollOff::alpha_0_25: tmp="0.25"; break;
173 case eDVBFrontendParametersSatellite::RollOff::alpha_0_20: tmp="0.20"; break;
175 case eDVBFrontendParametersSatellite::RollOff::alpha_auto: tmp="AUTO"; break;
177 PutToDict(dict, "roll off", tmp);
181 PutToDict(dict, "system", tmp);
184 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
186 PutToDict(dict, "type", "Terrestrial");
187 PutToDict(dict, "frequency", feparm.frequency);
189 switch (feparm.bandwidth)
191 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz: tmp="8 MHz"; break;
192 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz: tmp="7 MHz"; break;
193 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz: tmp="6 MHz"; break;
195 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto: tmp="AUTO"; break;
197 PutToDict(dict, "bandwidth", tmp);
198 switch (feparm.code_rate_LP)
200 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
201 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
202 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
203 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
204 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
206 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
208 PutToDict(dict, "code rate lp", tmp);
209 switch (feparm.code_rate_HP)
211 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
212 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
213 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
214 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
215 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
217 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
219 PutToDict(dict, "code rate hp", tmp);
220 switch (feparm.modulation)
222 case eDVBFrontendParametersTerrestrial::Modulation::QPSK: tmp="QPSK"; break;
223 case eDVBFrontendParametersTerrestrial::Modulation::QAM16: tmp="QAM16"; break;
224 case eDVBFrontendParametersTerrestrial::Modulation::QAM64: tmp="QAM64"; break;
226 case eDVBFrontendParametersTerrestrial::Modulation::Auto: tmp="AUTO"; break;
228 PutToDict(dict, "constellation", tmp);
229 switch (feparm.transmission_mode)
231 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k: tmp="2k"; break;
232 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k: tmp="8k"; break;
234 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto: tmp="AUTO"; break;
236 PutToDict(dict, "transmission mode", tmp);
237 switch (feparm.guard_interval)
239 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32: tmp="1/32"; break;
240 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16: tmp="1/16"; break;
241 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8: tmp="1/8"; break;
242 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4: tmp="1/4"; break;
244 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto: tmp="AUTO"; break;
246 PutToDict(dict, "guard interval", tmp);
247 switch (feparm.hierarchy)
249 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone: tmp="NONE"; break;
250 case eDVBFrontendParametersTerrestrial::Hierarchy::H1: tmp="1"; break;
251 case eDVBFrontendParametersTerrestrial::Hierarchy::H2: tmp="2"; break;
252 case eDVBFrontendParametersTerrestrial::Hierarchy::H4: tmp="4"; break;
254 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto: tmp="AUTO"; break;
256 PutToDict(dict, "hierarchy", tmp);
257 switch (feparm.inversion)
259 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
260 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
262 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
264 PutToDict(dict, "inversion", tmp);
267 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
270 PutToDict(dict, "type", "Cable");
271 PutToDict(dict, "frequency", feparm.frequency);
272 PutToDict(dict, "symbolrate", feparm.symbol_rate);
273 switch (feparm.modulation)
275 case eDVBFrontendParametersCable::Modulation::QAM16: tmp="QAM16"; break;
276 case eDVBFrontendParametersCable::Modulation::QAM32: tmp="QAM32"; break;
277 case eDVBFrontendParametersCable::Modulation::QAM64: tmp="QAM64"; break;
278 case eDVBFrontendParametersCable::Modulation::QAM128: tmp="QAM128"; break;
279 case eDVBFrontendParametersCable::Modulation::QAM256: tmp="QAM256"; break;
281 case eDVBFrontendParametersCable::Modulation::Auto: tmp="AUTO"; break;
283 PutToDict(dict, "modulation", tmp);
284 switch (feparm.inversion)
286 case eDVBFrontendParametersCable::Inversion::On: tmp="ON"; break;
287 case eDVBFrontendParametersCable::Inversion::Off: tmp="OFF"; break;
289 case eDVBFrontendParametersCable::Inversion::Unknown: tmp="AUTO"; break;
291 PutToDict(dict, "inversion", tmp);
292 switch (feparm.fec_inner)
294 case eDVBFrontendParametersCable::FEC::fNone: tmp="NONE"; break;
295 case eDVBFrontendParametersCable::FEC::f1_2: tmp="1/2"; break;
296 case eDVBFrontendParametersCable::FEC::f2_3: tmp="2/3"; break;
297 case eDVBFrontendParametersCable::FEC::f3_4: tmp="3/4"; break;
298 case eDVBFrontendParametersCable::FEC::f5_6: tmp="5/6"; break;
299 case eDVBFrontendParametersCable::FEC::f7_8: tmp="7/8"; break;
300 case eDVBFrontendParametersCable::FEC::f8_9: tmp="8/9"; break;
302 case eDVBFrontendParametersCable::FEC::fAuto: tmp="AUTO"; break;
304 PutToDict(dict, "fec inner", tmp);
307 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
309 if (r.type == eServiceReference::idDVB)
311 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
314 case iServiceInformation::sTransponderData:
316 ePtr<eDVBResourceManager> res;
317 if (!eDVBResourceManager::getInstance(res))
319 ePtr<iDVBChannelList> db;
320 if (!res->getChannelList(db))
323 ref.getChannelID(chid);
324 ePtr<iDVBFrontendParameters> feparm;
325 if (!db->getChannelFrontendData(chid, feparm))
328 if (!feparm->getSystem(system))
330 ePyObject dict = PyDict_New();
333 case iDVBFrontend::feSatellite:
335 eDVBFrontendParametersSatellite s;
337 PutSatelliteDataToDict(dict, s);
340 case iDVBFrontend::feTerrestrial:
342 eDVBFrontendParametersTerrestrial t;
344 PutTerrestrialDataToDict(dict, t);
347 case iDVBFrontend::feCable:
349 eDVBFrontendParametersCable c;
351 PutCableDataToDict(dict, c);
355 eDebug("unknown frontend type %d", system);
370 DEFINE_REF(eStaticServiceDVBBouquetInformation);
372 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
374 ePtr<iDVBChannelList> db;
375 ePtr<eDVBResourceManager> res;
378 if ((err = eDVBResourceManager::getInstance(res)) != 0)
380 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
383 if ((err = res->getChannelList(db)) != 0)
385 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
390 if ((err = db->getBouquet(ref, bouquet)) != 0)
392 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
396 if ( bouquet && bouquet->m_bouquet_name.length() )
398 name = bouquet->m_bouquet_name;
405 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
407 if (ref.flags & eServiceReference::isGroup)
409 ePtr<iDVBChannelList> db;
410 ePtr<eDVBResourceManager> res;
412 if (eDVBResourceManager::getInstance(res))
414 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
418 if (res->getChannelList(db))
420 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
425 if (db->getBouquet(ref, bouquet))
427 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
431 int prio_order = eDVBFrontend::getTypePriorityOrder();
433 eDVBChannelID chid, chid_ignore;
434 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
435 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
437 static unsigned char prio_map[6][3] = {
438 { 3, 2, 1 }, // -S -C -T
439 { 3, 1, 2 }, // -S -T -C
440 { 2, 3, 1 }, // -C -S -T
441 { 1, 3, 2 }, // -C -T -S
442 { 1, 2, 3 }, // -T -C -S
443 { 2, 1, 3 } // -T -S -C
445 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
446 int tmp=res->canAllocateChannel(chid, chid_ignore);
451 case 30000: // cached DVB-T channel
452 case 1: // DVB-T frontend
453 tmp = prio_map[prio_order][2];
455 case 40000: // cached DVB-C channel
457 tmp = prio_map[prio_order][1];
460 tmp = prio_map[prio_order][0];
465 m_playable_service = *it;
472 m_playable_service = eServiceReference();
476 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
481 #include <lib/dvb/epgcache.h>
483 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
485 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
488 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
490 DECLARE_REF(eStaticServiceDVBPVRInformation);
491 eServiceReference m_ref;
492 eDVBMetaParser m_parser;
494 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
495 RESULT getName(const eServiceReference &ref, std::string &name);
496 int getLength(const eServiceReference &ref);
497 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
498 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
499 int getInfo(const eServiceReference &ref, int w);
500 std::string getInfoString(const eServiceReference &ref,int w);
503 DEFINE_REF(eStaticServiceDVBPVRInformation);
505 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
508 m_parser.parseFile(ref.path);
511 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
513 ASSERT(ref == m_ref);
514 if (m_parser.m_name.size())
515 name = m_parser.m_name;
519 size_t n = name.rfind('/');
520 if (n != std::string::npos)
521 name = name.substr(n + 1);
526 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
528 ASSERT(ref == m_ref);
532 if (tstools.openFile(ref.path.c_str()))
536 if (tstools.calcLen(len))
542 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
546 case iServiceInformation::sDescription:
547 return iServiceInformation::resIsString;
548 case iServiceInformation::sServiceref:
549 return iServiceInformation::resIsString;
550 case iServiceInformation::sTimeCreate:
551 if (m_parser.m_time_create)
552 return m_parser.m_time_create;
554 return iServiceInformation::resNA;
556 return iServiceInformation::resNA;
560 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
564 case iServiceInformation::sDescription:
565 return m_parser.m_description;
566 case iServiceInformation::sServiceref:
567 return m_parser.m_ref.toString();
568 case iServiceInformation::sTags:
569 return m_parser.m_tags;
575 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
577 if (!ref.path.empty())
579 ePtr<eServiceEvent> event = new eServiceEvent;
580 std::string filename = ref.path;
581 filename.erase(filename.length()-2, 2);
583 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
593 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
595 DECLARE_REF(eDVBPVRServiceOfflineOperations);
596 eServiceReferenceDVB m_ref;
598 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
600 RESULT deleteFromDisk(int simulate);
601 RESULT getListOfFilenames(std::list<std::string> &);
604 DEFINE_REF(eDVBPVRServiceOfflineOperations);
606 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
610 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
616 std::list<std::string> res;
617 if (getListOfFilenames(res))
620 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
622 eDebug("FATAL !! can't get background file eraser");
624 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
626 eDebug("Removing %s...", i->c_str());
628 eraser->erase(i->c_str());
630 ::unlink(i->c_str());
637 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
640 res.push_back(m_ref.path);
642 // handling for old splitted recordings (enigma 1)
647 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
649 if (stat(buf, &s) < 0)
654 res.push_back(m_ref.path + ".meta");
655 res.push_back(m_ref.path + ".ap");
656 res.push_back(m_ref.path + ".cuts");
657 std::string tmp = m_ref.path;
658 tmp.erase(m_ref.path.length()-3);
659 res.push_back(tmp + ".eit");
663 DEFINE_REF(eServiceFactoryDVB)
665 eServiceFactoryDVB::eServiceFactoryDVB()
667 ePtr<eServiceCenter> sc;
669 eServiceCenter::getPrivInstance(sc);
671 sc->addServiceFactory(eServiceFactoryDVB::id, this);
673 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
674 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
677 eServiceFactoryDVB::~eServiceFactoryDVB()
679 ePtr<eServiceCenter> sc;
681 eServiceCenter::getPrivInstance(sc);
683 sc->removeServiceFactory(eServiceFactoryDVB::id);
686 DEFINE_REF(eDVBServiceList);
688 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
692 eDVBServiceList::~eDVBServiceList()
696 RESULT eDVBServiceList::startQuery()
698 ePtr<iDVBChannelList> db;
699 ePtr<eDVBResourceManager> res;
702 if ((err = eDVBResourceManager::getInstance(res)) != 0)
704 eDebug("no resource manager");
707 if ((err = res->getChannelList(db)) != 0)
709 eDebug("no channel list");
713 ePtr<eDVBChannelQuery> q;
715 if (!m_parent.path.empty())
717 eDVBChannelQuery::compile(q, m_parent.path);
720 eDebug("compile query failed");
725 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
727 eDebug("startQuery failed");
734 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
736 eServiceReferenceDVB ref;
741 while (!m_query->getNextResult(ref))
745 list.sort(iListableServiceCompare(this));
750 // The first argument of this function is a format string to specify the order and
751 // the content of the returned list
752 // useable format options are
753 // R = Service Reference (as swig object .. this is very slow)
754 // S = Service Reference (as python string object .. same as ref.toString())
755 // C = Service Reference (as python string object .. same as ref.toCompareString())
756 // N = Service Name (as python string object)
757 // n = Short Service Name (short name brakets used) (as python string object)
758 // when exactly one return value per service is selected in the format string,
759 // then each value is directly a list entry
760 // when more than one value is returned per service, then the list is a list of
762 // unknown format string chars are returned as python None values !
763 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
766 std::list<eServiceReference> tmplist;
769 if (!format || !(retcount=strlen(format)))
770 format = "R"; // just return service reference swig object ...
772 if (!getContent(tmplist, sorted))
774 int services=tmplist.size();
775 ePtr<iStaticServiceInformation> sptr;
776 eServiceCenterPtr service_center;
778 if (strchr(format, 'N') || strchr(format, 'n'))
779 eServiceCenter::getPrivInstance(service_center);
781 ret = PyList_New(services);
782 std::list<eServiceReference>::iterator it(tmplist.begin());
784 for (int cnt=0; cnt < services; ++cnt)
786 eServiceReference &ref=*it++;
787 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
788 for (int i=0; i < retcount; ++i)
793 case 'R': // service reference (swig)object
794 tmp = NEW_eServiceReference(ref);
796 case 'C': // service reference compare string
797 tmp = PyString_FromString(ref.toCompareString().c_str());
799 case 'S': // service reference string
800 tmp = PyString_FromString(ref.toString().c_str());
802 case 'N': // service name
805 service_center->info(ref, sptr);
809 sptr->getName(ref, name);
811 // filter short name brakets
813 while((pos = name.find("\xc2\x86")) != std::string::npos)
815 while((pos = name.find("\xc2\x87")) != std::string::npos)
819 tmp = PyString_FromString(name.c_str());
823 tmp = PyString_FromString("<n/a>");
825 case 'n': // short service name
828 service_center->info(ref, sptr);
832 sptr->getName(ref, name);
833 name = buildShortName(name);
835 tmp = PyString_FromString(name.c_str());
839 tmp = PyString_FromString("<n/a>");
852 PyTuple_SET_ITEM(tuple, i, tmp);
854 PyList_SET_ITEM(ret, cnt, tmp);
858 PyList_SET_ITEM(ret, cnt, tuple);
861 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
864 RESULT eDVBServiceList::getNext(eServiceReference &ref)
869 return m_query->getNextResult((eServiceReferenceDVB&)ref);
872 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
874 if (m_parent.flags & eServiceReference::canDescent) // bouquet
876 ePtr<iDVBChannelList> db;
877 ePtr<eDVBResourceManager> resm;
879 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
882 if (db->getBouquet(m_parent, m_bouquet) != 0)
893 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
897 return m_bouquet->addService(ref, before);
900 RESULT eDVBServiceList::removeService(eServiceReference &ref)
904 return m_bouquet->removeService(ref);
907 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
911 return m_bouquet->moveService(ref, pos);
914 RESULT eDVBServiceList::flushChanges()
918 return m_bouquet->flushChanges();
921 RESULT eDVBServiceList::setListName(const std::string &name)
925 return m_bouquet->setListName(name);
928 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
930 ePtr<eDVBService> service;
931 int r = lookupService(service, ref);
934 // check resources...
935 ptr = new eDVBServicePlay(ref, service);
939 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
941 if (ref.path.empty())
943 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
952 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
954 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
955 if (list->startQuery())
965 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
967 /* is a listable service? */
968 if (ref.flags & eServiceReference::canDescent) // bouquet
970 if ( !ref.name.empty() ) // satellites or providers list
971 ptr = m_StaticServiceDVBInfo;
972 else // a dvb bouquet
973 ptr = m_StaticServiceDVBBouquetInfo;
975 else if (!ref.path.empty()) /* do we have a PVR service? */
976 ptr = new eStaticServiceDVBPVRInformation(ref);
977 else // normal dvb service
979 ePtr<eDVBService> service;
980 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
981 ptr = m_StaticServiceDVBInfo;
983 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
989 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
991 if (ref.path.empty())
997 ptr = new eDVBPVRServiceOfflineOperations(ref);
1002 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
1004 // TODO: handle the listing itself
1005 // if (ref.... == -1) .. return "... bouquets ...";
1006 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
1008 ePtr<iDVBChannelList> db;
1009 ePtr<eDVBResourceManager> res;
1012 if ((err = eDVBResourceManager::getInstance(res)) != 0)
1014 eDebug("no resource manager");
1017 if ((err = res->getChannelList(db)) != 0)
1019 eDebug("no channel list");
1023 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
1024 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
1026 eDebug("getService failed!");
1033 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
1034 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
1036 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
1038 m_is_pvr = !m_reference.path.empty();
1040 m_timeshift_enabled = m_timeshift_active = 0;
1043 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
1044 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
1045 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
1047 m_cuesheet_changed = 0;
1048 m_cutlist_enabled = 1;
1050 m_subtitle_widget = 0;
1054 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
1057 eDVBServicePlay::~eDVBServicePlay()
1059 delete m_subtitle_widget;
1062 void eDVBServicePlay::gotNewEvent()
1066 ePtr<eServiceEvent> m_event_now, m_event_next;
1067 getEvent(m_event_now, 0);
1068 getEvent(m_event_next, 1);
1071 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1073 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1075 m_event((iPlayableService*)this, evUpdatedEventInfo);
1078 void eDVBServicePlay::serviceEvent(int event)
1080 m_tune_state = event;
1084 case eDVBServicePMTHandler::eventTuned:
1086 ePtr<iDVBDemux> m_demux;
1087 if (!m_service_handler.getDataDemux(m_demux))
1089 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1090 int sid = ref.getParentServiceID().get();
1092 sid = ref.getServiceID().get();
1093 if ( ref.getParentTransportStreamID().get() &&
1094 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1095 m_event_handler.startOther(m_demux, sid);
1097 m_event_handler.start(m_demux, sid);
1101 case eDVBServicePMTHandler::eventNoResources:
1102 case eDVBServicePMTHandler::eventNoPAT:
1103 case eDVBServicePMTHandler::eventNoPATEntry:
1104 case eDVBServicePMTHandler::eventNoPMT:
1105 case eDVBServicePMTHandler::eventTuneFailed:
1106 case eDVBServicePMTHandler::eventMisconfiguration:
1108 eDebug("DVB service failed to tune - error %d", event);
1109 m_event((iPlayableService*)this, evTuneFailed);
1112 case eDVBServicePMTHandler::eventNewProgramInfo:
1114 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1115 if (m_timeshift_enabled)
1116 updateTimeshiftPids();
1117 if (!m_timeshift_active)
1119 if (m_first_program_info && m_is_pvr)
1121 m_first_program_info = 0;
1124 m_event((iPlayableService*)this, evUpdatedInfo);
1127 case eDVBServicePMTHandler::eventEOF:
1128 m_event((iPlayableService*)this, evEOF);
1130 case eDVBServicePMTHandler::eventSOF:
1131 m_event((iPlayableService*)this, evSOF);
1136 void eDVBServicePlay::serviceEventTimeshift(int event)
1140 case eDVBServicePMTHandler::eventNewProgramInfo:
1141 if (m_timeshift_active)
1144 case eDVBServicePMTHandler::eventSOF:
1145 m_event((iPlayableService*)this, evSOF);
1147 case eDVBServicePMTHandler::eventEOF:
1148 if ((!m_is_paused) && (m_skipmode >= 0))
1154 RESULT eDVBServicePlay::start()
1157 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1158 two (one for decoding, one for data source), as we must be prepared
1159 to start recording from the data demux. */
1161 m_cue = new eCueSheet();
1163 m_event(this, evStart);
1165 m_first_program_info = 1;
1166 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1167 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1169 /* inject EIT if there is a stored one */
1172 std::string filename = service.path;
1173 filename.erase(filename.length()-2, 2);
1175 ePtr<eServiceEvent> event = new eServiceEvent;
1176 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1178 ePtr<eServiceEvent> empty;
1179 m_event_handler.inject(event, 0);
1180 m_event_handler.inject(empty, 1);
1187 m_event(this, evStart);
1192 RESULT eDVBServicePlay::stop()
1194 /* add bookmark for last play position */
1197 pts_t play_position, length;
1198 if (!getPlayPosition(play_position))
1200 /* remove last position */
1201 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1203 if (i->what == 3) /* current play position */
1205 m_cue_entries.erase(i);
1206 i = m_cue_entries.begin();
1212 if (getLength(length))
1217 int perc = play_position * 100LL / length;
1219 /* only store last play position when between 5% and 95% */
1220 if ((5 < perc) && (perc < 95))
1221 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1223 m_cuesheet_changed = 1;
1227 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1229 m_service_handler_timeshift.free();
1230 m_service_handler.free();
1232 if (m_is_pvr && m_cuesheet_changed)
1235 /* save cuesheet only when main file is accessible. */
1236 if (!::stat(m_reference.path.c_str(), &s))
1239 m_event((iPlayableService*)this, evStopped);
1243 RESULT eDVBServicePlay::setTarget(int target)
1245 m_is_primary = !target;
1249 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1251 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1255 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1257 /* note: we check for timeshift to be enabled,
1258 not neccessary active. if you pause when timeshift
1259 is not active, you should activate it when unpausing */
1260 if ((!m_is_pvr) && (!m_timeshift_enabled))
1270 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1273 return m_decoder->setSlowMotion(ratio);
1278 RESULT eDVBServicePlay::setFastForward(int ratio)
1280 int skipmode, ffratio;
1286 } else if (ratio > 0)
1294 } else // if (ratio < 0)
1300 if (m_skipmode != skipmode)
1302 eDebug("setting cue skipmode to %d", skipmode);
1304 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1307 m_skipmode = skipmode;
1312 return m_decoder->setFastForward(ffratio);
1315 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1317 if (m_is_pvr || m_timeshift_enabled)
1327 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1328 RESULT eDVBServicePlay::getLength(pts_t &len)
1330 ePtr<iDVBPVRChannel> pvr_channel;
1332 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1335 return pvr_channel->getLength(len);
1338 RESULT eDVBServicePlay::pause()
1340 if (!m_is_paused && m_decoder)
1343 return m_decoder->freeze(0);
1348 RESULT eDVBServicePlay::unpause()
1350 if (m_is_paused && m_decoder)
1353 return m_decoder->unfreeze();
1358 RESULT eDVBServicePlay::seekTo(pts_t to)
1360 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1362 if (!m_decode_demux)
1365 ePtr<iDVBPVRChannel> pvr_channel;
1367 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1373 m_cue->seekTo(0, to);
1374 m_dvb_subtitle_pages.clear();
1375 m_subtitle_pages.clear();
1380 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1382 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1384 if (!m_decode_demux)
1387 ePtr<iDVBPVRChannel> pvr_channel;
1389 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1394 /* HACK until we have skip-AP api */
1395 if ((to > 0) && (to < 100))
1403 m_cue->seekTo(mode, to);
1404 m_dvb_subtitle_pages.clear();
1405 m_subtitle_pages.clear();
1409 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1411 ePtr<iDVBPVRChannel> pvr_channel;
1413 if (!m_decode_demux)
1416 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1421 /* if there is a decoder, use audio or video PTS */
1424 r = m_decoder->getPTS(0, pos);
1430 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1433 RESULT eDVBServicePlay::setTrickmode(int trick)
1436 m_decoder->setTrickmode(trick);
1440 RESULT eDVBServicePlay::isCurrentlySeekable()
1442 return m_is_pvr || m_timeshift_active;
1445 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1451 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1457 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1463 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1469 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1475 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1478 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1479 (m_timeshift_enabled || !m_is_pvr))
1481 if (!m_timeshift_enabled)
1483 /* we need enough diskspace */
1485 if (statfs(TSPATH "/.", &fs) < 0)
1487 eDebug("statfs failed!");
1491 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1493 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1503 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1514 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1520 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1526 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1532 RESULT eDVBServicePlay::getName(std::string &name)
1536 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1537 return i->getName(m_reference, name);
1541 m_dvb_service->getName(m_reference, name);
1545 else if (!m_reference.name.empty())
1546 eStaticServiceDVBInformation().getName(m_reference, name);
1548 name = "DVB service";
1552 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1554 return m_event_handler.getEvent(evt, nownext);
1557 int eDVBServicePlay::getInfo(int w)
1559 eDVBServicePMTHandler::program program;
1562 return resIsPyObject;
1564 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1566 int no_program_info = 0;
1568 if (h.getProgramInfo(program))
1569 no_program_info = 1;
1573 #if HAVE_DVB_API_VERSION >= 3
1575 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1576 return m_videoEventData.height;
1579 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1580 return m_videoEventData.width;
1583 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1586 #if HAVE_DVB_API_VERSION >= 3
1587 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1588 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1591 #warning "FIXMEE implement sAspect for old DVB API"
1593 if (no_program_info)
1595 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1597 ePtr<eServiceEvent> evt;
1598 if (!m_event_handler.getEvent(evt, 0))
1600 ePtr<eComponentData> data;
1601 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1603 if ( data->getStreamContent() == 1 )
1605 switch(data->getComponentType())
1608 case 1: // 4:3 SD PAL
1610 case 3: // 16:9 SD PAL
1611 case 4: // > 16:9 PAL
1612 case 5: // 4:3 SD NTSC
1614 case 7: // 16:9 SD NTSC
1615 case 8: // > 16:9 NTSC
1618 case 9: // 4:3 HD PAL
1620 case 0xB: // 16:9 HD PAL
1621 case 0xC: // > 16:9 HD PAL
1622 case 0xD: // 4:3 HD NTSC
1624 case 0xF: // 16:9 HD NTSC
1625 case 0x10: // > 16:9 HD PAL
1626 return data->getComponentType();
1633 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1634 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1635 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1636 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1637 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1638 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1639 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1640 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1641 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1642 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1643 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1644 case sProvider: if (!m_dvb_service) return -1; return -2;
1645 case sServiceref: return resIsString;
1646 case sDVBState: return m_tune_state;
1652 std::string eDVBServicePlay::getInfoString(int w)
1657 if (!m_dvb_service) return "";
1658 return m_dvb_service->m_provider_name;
1660 return m_reference.toString();
1664 return iServiceInformation::getInfoString(w);
1667 PyObject *eDVBServicePlay::getInfoObject(int w)
1672 return m_service_handler.getCaIds();
1673 case sTransponderData:
1674 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1678 return iServiceInformation::getInfoObject(w);
1681 int eDVBServicePlay::getNumberOfTracks()
1683 eDVBServicePMTHandler::program program;
1684 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1685 if (h.getProgramInfo(program))
1687 return program.audioStreams.size();
1690 int eDVBServicePlay::getCurrentTrack()
1692 eDVBServicePMTHandler::program program;
1693 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1694 if (h.getProgramInfo(program))
1697 int max = program.audioStreams.size();
1700 for (i = 0; i < max; ++i)
1701 if (program.audioStreams[i].pid == m_current_audio_pid)
1707 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1709 int ret = selectAudioStream(i);
1711 if (m_decoder->start())
1717 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1719 eDVBServicePMTHandler::program program;
1720 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1722 if (h.getProgramInfo(program))
1725 if (i >= program.audioStreams.size())
1728 info.m_pid = program.audioStreams[i].pid;
1730 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1731 info.m_description = "MPEG";
1732 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1733 info.m_description = "AC3";
1734 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1735 info.m_description = "AAC";
1736 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1737 info.m_description = "DTS";
1739 info.m_description = "???";
1741 if (program.audioStreams[i].component_tag != -1)
1743 ePtr<eServiceEvent> evt;
1744 if (!m_event_handler.getEvent(evt, 0))
1746 ePtr<eComponentData> data;
1747 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1748 info.m_language = data->getText();
1752 if (info.m_language.empty())
1753 info.m_language = program.audioStreams[i].language_code;
1758 int eDVBServicePlay::selectAudioStream(int i)
1760 eDVBServicePMTHandler::program program;
1761 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1763 if (h.getProgramInfo(program))
1766 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1774 stream = program.defaultAudioStream;
1776 int apid = -1, apidtype = -1;
1778 if (((unsigned int)stream) < program.audioStreams.size())
1780 apid = program.audioStreams[stream].pid;
1781 apidtype = program.audioStreams[stream].type;
1784 m_current_audio_pid = apid;
1786 if (m_decoder->setAudioPID(apid, apidtype))
1788 eDebug("set audio pid failed");
1792 /* 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 */
1793 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1796 ePtr<iDVBDemux> data_demux;
1797 if (!h.getDataDemux(data_demux))
1799 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1800 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1804 /* if we decided that we need one, update the pid */
1806 m_rds_decoder->start(apid);
1808 /* store new pid as default only when:
1809 a.) we have an entry in the service db for the current service,
1810 b.) we are not playing back something,
1811 c.) we are not selecting the default entry. (we wouldn't change
1812 anything in the best case, or destroy the default setting in
1813 case the real default is not yet available.)
1815 if (m_dvb_service && !m_is_pvr && ((i != -1)
1816 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1818 if (apidtype == eDVBAudio::aMPEG)
1820 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1821 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1825 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1826 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1830 h.resetCachedProgram();
1835 int eDVBServicePlay::getCurrentChannel()
1837 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1840 RESULT eDVBServicePlay::selectChannel(int i)
1842 if (i < LEFT || i > RIGHT || i == STEREO)
1845 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1847 m_decoder->setAudioChannel(i);
1851 std::string eDVBServicePlay::getText(int x)
1857 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1859 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1864 void eDVBServicePlay::rdsDecoderEvent(int what)
1868 case eDVBRdsDecoder::RadioTextChanged:
1869 m_event((iPlayableService*)this, evUpdatedRadioText);
1871 case eDVBRdsDecoder::RtpTextChanged:
1872 m_event((iPlayableService*)this, evUpdatedRtpText);
1874 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1875 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1877 case eDVBRdsDecoder::RecvRassSlidePic:
1878 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1883 void eDVBServicePlay::showRassSlidePicture()
1889 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1890 if (rass_slide_pic.length())
1891 m_decoder->showSinglePic(rass_slide_pic.c_str());
1893 eDebug("empty filename for rass slide picture received!!");
1896 eDebug("no MPEG Decoder to show iframes avail");
1899 eDebug("showRassSlidePicture called.. but not decoder");
1902 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1908 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1909 if (rass_interactive_pic.length())
1910 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1912 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1915 eDebug("no MPEG Decoder to show iframes avail");
1918 eDebug("showRassInteractivePic called.. but not decoder");
1921 ePyObject eDVBServicePlay::getRassInteractiveMask()
1924 return m_rds_decoder->getRassPictureMask();
1928 int eDVBServiceBase::getFrontendInfo(int w)
1930 eUsePtr<iDVBChannel> channel;
1931 if(m_service_handler.getChannel(channel))
1933 ePtr<iDVBFrontend> fe;
1934 if(channel->getFrontend(fe))
1936 return fe->readFrontendData(w);
1939 PyObject *eDVBServiceBase::getFrontendData()
1941 ePyObject ret = PyDict_New();
1944 eUsePtr<iDVBChannel> channel;
1945 if(!m_service_handler.getChannel(channel))
1947 ePtr<iDVBFrontend> fe;
1948 if(!channel->getFrontend(fe))
1949 fe->getFrontendData(ret);
1957 PyObject *eDVBServiceBase::getFrontendStatus()
1959 ePyObject ret = PyDict_New();
1962 eUsePtr<iDVBChannel> channel;
1963 if(!m_service_handler.getChannel(channel))
1965 ePtr<iDVBFrontend> fe;
1966 if(!channel->getFrontend(fe))
1967 fe->getFrontendStatus(ret);
1975 PyObject *eDVBServiceBase::getTransponderData(bool original)
1977 ePyObject ret = PyDict_New();
1980 eUsePtr<iDVBChannel> channel;
1981 if(!m_service_handler.getChannel(channel))
1983 ePtr<iDVBFrontend> fe;
1984 if(!channel->getFrontend(fe))
1986 fe->getTransponderData(ret, original);
1987 ePtr<iDVBFrontendParameters> feparm;
1988 channel->getCurrentFrontendParameters(feparm);
1991 eDVBFrontendParametersSatellite osat;
1992 if (!feparm->getDVBS(osat))
1994 void PutToDict(ePyObject &, const char*, long);
1995 void PutToDict(ePyObject &, const char*, const char*);
1996 PutToDict(ret, "orbital_position", osat.orbital_position);
1997 const char *tmp = "UNKNOWN";
1998 switch(osat.polarisation)
2000 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2001 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2002 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2003 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2006 PutToDict(ret, "polarization", tmp);
2017 PyObject *eDVBServiceBase::getAll(bool original)
2019 ePyObject ret = getTransponderData(original);
2022 eUsePtr<iDVBChannel> channel;
2023 if(!m_service_handler.getChannel(channel))
2025 ePtr<iDVBFrontend> fe;
2026 if(!channel->getFrontend(fe))
2028 fe->getFrontendData(ret);
2029 fe->getFrontendStatus(ret);
2036 int eDVBServicePlay::getNumberOfSubservices()
2038 ePtr<eServiceEvent> evt;
2039 if (!m_event_handler.getEvent(evt, 0))
2040 return evt->getNumOfLinkageServices();
2044 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2046 ePtr<eServiceEvent> evt;
2047 if (!m_event_handler.getEvent(evt, 0))
2049 if (!evt->getLinkageService(sub, m_reference, n))
2052 sub.type=eServiceReference::idInvalid;
2056 RESULT eDVBServicePlay::startTimeshift()
2058 ePtr<iDVBDemux> demux;
2060 eDebug("Start timeshift!");
2062 if (m_timeshift_enabled)
2065 /* start recording with the data demux. */
2066 if (m_service_handler.getDataDemux(demux))
2069 demux->createTSRecorder(m_record);
2073 char templ[]=TSPATH "/timeshift.XXXXXX";
2074 m_timeshift_fd = mkstemp(templ);
2075 m_timeshift_file = templ;
2077 eDebug("recording to %s", templ);
2079 if (m_timeshift_fd < 0)
2085 m_record->setTargetFD(m_timeshift_fd);
2087 m_timeshift_enabled = 1;
2089 updateTimeshiftPids();
2095 RESULT eDVBServicePlay::stopTimeshift()
2097 if (!m_timeshift_enabled)
2102 m_timeshift_enabled = 0;
2107 close(m_timeshift_fd);
2108 eDebug("remove timeshift file");
2109 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2114 int eDVBServicePlay::isTimeshiftActive()
2116 return m_timeshift_enabled && m_timeshift_active;
2119 RESULT eDVBServicePlay::activateTimeshift()
2121 if (!m_timeshift_enabled)
2124 if (!m_timeshift_active)
2126 switchToTimeshift();
2133 PyObject *eDVBServicePlay::getCutList()
2135 ePyObject list = PyList_New(0);
2137 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2139 ePyObject tuple = PyTuple_New(2);
2140 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2141 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2142 PyList_Append(list, tuple);
2149 void eDVBServicePlay::setCutList(ePyObject list)
2151 if (!PyList_Check(list))
2153 int size = PyList_Size(list);
2156 m_cue_entries.clear();
2158 for (i=0; i<size; ++i)
2160 ePyObject tuple = PyList_GET_ITEM(list, i);
2161 if (!PyTuple_Check(tuple))
2163 eDebug("non-tuple in cutlist");
2166 if (PyTuple_Size(tuple) != 2)
2168 eDebug("cutlist entries need to be a 2-tuple");
2171 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2172 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2174 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2177 pts_t pts = PyLong_AsLongLong(ppts);
2178 int type = PyInt_AsLong(ptype);
2179 m_cue_entries.insert(cueEntry(pts, type));
2180 eDebug("adding %08llx, %d", pts, type);
2182 m_cuesheet_changed = 1;
2184 cutlistToCuesheet();
2185 m_event((iPlayableService*)this, evCuesheetChanged);
2188 void eDVBServicePlay::setCutListEnable(int enable)
2190 m_cutlist_enabled = enable;
2191 cutlistToCuesheet();
2194 void eDVBServicePlay::updateTimeshiftPids()
2199 eDVBServicePMTHandler::program program;
2200 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2202 if (h.getProgramInfo(program))
2206 std::set<int> pids_to_record;
2207 pids_to_record.insert(0); // PAT
2208 if (program.pmtPid != -1)
2209 pids_to_record.insert(program.pmtPid); // PMT
2211 if (program.textPid != -1)
2212 pids_to_record.insert(program.textPid); // Videotext
2214 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2215 i(program.videoStreams.begin());
2216 i != program.videoStreams.end(); ++i)
2217 pids_to_record.insert(i->pid);
2219 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2220 i(program.audioStreams.begin());
2221 i != program.audioStreams.end(); ++i)
2222 pids_to_record.insert(i->pid);
2224 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2225 i(program.subtitleStreams.begin());
2226 i != program.subtitleStreams.end(); ++i)
2227 pids_to_record.insert(i->pid);
2229 std::set<int> new_pids, obsolete_pids;
2231 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2232 m_pids_active.begin(), m_pids_active.end(),
2233 std::inserter(new_pids, new_pids.begin()));
2235 std::set_difference(
2236 m_pids_active.begin(), m_pids_active.end(),
2237 pids_to_record.begin(), pids_to_record.end(),
2238 std::inserter(new_pids, new_pids.begin())
2241 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2242 m_record->addPID(*i);
2244 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2245 m_record->removePID(*i);
2249 void eDVBServicePlay::switchToLive()
2251 if (!m_timeshift_active)
2257 m_teletext_parser = 0;
2259 m_subtitle_parser = 0;
2260 m_new_dvb_subtitle_page_connection = 0;
2261 m_new_subtitle_page_connection = 0;
2262 m_rds_decoder_event_connection = 0;
2263 m_video_event_connection = 0;
2265 /* free the timeshift service handler, we need the resources */
2266 m_service_handler_timeshift.free();
2267 m_timeshift_active = 0;
2269 m_event((iPlayableService*)this, evSeekableStatusChanged);
2274 void eDVBServicePlay::switchToTimeshift()
2276 if (m_timeshift_active)
2281 m_teletext_parser = 0;
2283 m_subtitle_parser = 0;
2284 m_new_subtitle_page_connection = 0;
2285 m_new_dvb_subtitle_page_connection = 0;
2286 m_rds_decoder_event_connection = 0;
2287 m_video_event_connection = 0;
2289 m_timeshift_active = 1;
2291 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2292 r.path = m_timeshift_file;
2294 m_cue = new eCueSheet();
2295 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2297 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2299 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2301 m_event((iPlayableService*)this, evSeekableStatusChanged);
2304 void eDVBServicePlay::updateDecoder()
2306 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2308 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2310 eDVBServicePMTHandler::program program;
2311 if (h.getProgramInfo(program))
2312 eDebug("getting program info failed.");
2315 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2316 if (!program.videoStreams.empty())
2318 eDebugNoNewLine(" (");
2319 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2320 i(program.videoStreams.begin());
2321 i != program.videoStreams.end(); ++i)
2328 if (i != program.videoStreams.begin())
2329 eDebugNoNewLine(", ");
2330 eDebugNoNewLine("%04x", i->pid);
2332 eDebugNoNewLine(")");
2334 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2335 if (!program.audioStreams.empty())
2337 eDebugNoNewLine(" (");
2338 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2339 i(program.audioStreams.begin());
2340 i != program.audioStreams.end(); ++i)
2342 if (i != program.audioStreams.begin())
2343 eDebugNoNewLine(", ");
2344 eDebugNoNewLine("%04x", i->pid);
2346 eDebugNoNewLine(")");
2348 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2349 pcrpid = program.pcrPid;
2350 eDebug(", and the text pid is %04x", program.textPid);
2351 tpid = program.textPid;
2356 h.getDecodeDemux(m_decode_demux);
2359 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2361 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2362 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2363 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2364 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2365 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2368 m_teletext_parser = 0;
2369 m_subtitle_parser = 0;
2373 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2380 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2381 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2382 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2384 else // subservice or recording
2386 eServiceReferenceDVB ref;
2387 m_service_handler.getServiceReference(ref);
2388 eServiceReferenceDVB parent = ref.getParentServiceReference();
2393 ePtr<eDVBResourceManager> res_mgr;
2394 if (!eDVBResourceManager::getInstance(res_mgr))
2396 ePtr<iDVBChannelList> db;
2397 if (!res_mgr->getChannelList(db))
2399 ePtr<eDVBService> origService;
2400 if (!db->getService(parent, origService))
2402 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2403 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2409 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2410 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2412 m_decoder->setVideoPID(vpid, vpidtype);
2413 selectAudioStream();
2415 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2416 m_decoder->setSyncPCR(pcrpid);
2418 m_decoder->setSyncPCR(-1);
2420 m_decoder->setTextPID(tpid);
2422 m_teletext_parser->start(program.textPid);
2425 m_decoder->setTrickmode(1);
2428 m_decoder->preroll();
2432 if (vpid > 0 && vpid < 0x2000)
2436 std::string radio_pic;
2437 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2438 m_decoder->setRadioPic(radio_pic);
2441 m_decoder->setAudioChannel(achannel);
2443 /* don't worry about non-existing services, nor pvr services */
2444 if (m_dvb_service && !m_is_pvr)
2446 /* (audio pid will be set in selectAudioTrack */
2447 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2448 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2449 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2450 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2453 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2456 void eDVBServicePlay::loadCuesheet()
2458 std::string filename = m_reference.path + ".cuts";
2460 m_cue_entries.clear();
2462 FILE *f = fopen(filename.c_str(), "rb");
2466 eDebug("loading cuts..");
2469 unsigned long long where;
2472 if (!fread(&where, sizeof(where), 1, f))
2474 if (!fread(&what, sizeof(what), 1, f))
2477 #if BYTE_ORDER == LITTLE_ENDIAN
2478 where = bswap_64(where);
2485 m_cue_entries.insert(cueEntry(where, what));
2488 eDebug("%d entries", m_cue_entries.size());
2490 eDebug("cutfile not found!");
2492 m_cuesheet_changed = 0;
2493 cutlistToCuesheet();
2494 m_event((iPlayableService*)this, evCuesheetChanged);
2497 void eDVBServicePlay::saveCuesheet()
2499 std::string filename = m_reference.path + ".cuts";
2501 FILE *f = fopen(filename.c_str(), "wb");
2505 unsigned long long where;
2508 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2510 #if BYTE_ORDER == BIG_ENDIAN
2513 where = bswap_64(i->where);
2515 what = htonl(i->what);
2516 fwrite(&where, sizeof(where), 1, f);
2517 fwrite(&what, sizeof(what), 1, f);
2523 m_cuesheet_changed = 0;
2526 void eDVBServicePlay::cutlistToCuesheet()
2530 eDebug("no cue sheet");
2535 if (!m_cutlist_enabled)
2537 m_cue->commitSpans();
2538 eDebug("cutlists were disabled");
2542 pts_t in = 0, out = 0, length = 0;
2546 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2550 if (i == m_cue_entries.end())
2553 if (i->what == 0) /* in */
2557 } else if (i->what == 1) /* out */
2559 else /* mark (2) or last play position (3) */
2567 m_cue->addSourceSpan(in, out);
2571 if (i == m_cue_entries.end())
2574 m_cue->commitSpans();
2577 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2579 if (m_subtitle_widget)
2580 disableSubtitles(parent);
2583 int tuplesize = PyTuple_Size(tuple);
2586 if (!PyTuple_Check(tuple))
2592 entry = PyTuple_GET_ITEM(tuple, 0);
2594 if (!PyInt_Check(entry))
2597 type = PyInt_AsLong(entry);
2599 if (type == 1) // teletext subtitles
2601 int page, magazine, pid;
2605 if (!m_teletext_parser)
2607 eDebug("enable teletext subtitles.. no parser !!!");
2611 entry = PyTuple_GET_ITEM(tuple, 1);
2612 if (!PyInt_Check(entry))
2614 pid = PyInt_AsLong(entry);
2616 entry = PyTuple_GET_ITEM(tuple, 2);
2617 if (!PyInt_Check(entry))
2619 page = PyInt_AsLong(entry);
2621 entry = PyTuple_GET_ITEM(tuple, 3);
2622 if (!PyInt_Check(entry))
2624 magazine = PyInt_AsLong(entry);
2626 m_subtitle_widget = new eSubtitleWidget(parent);
2627 m_subtitle_widget->resize(parent->size()); /* full size */
2628 m_teletext_parser->setPageAndMagazine(page, magazine);
2630 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2634 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2635 if (!m_subtitle_parser)
2637 eDebug("enable dvb subtitles.. no parser !!!");
2643 entry = PyTuple_GET_ITEM(tuple, 1);
2644 if (!PyInt_Check(entry))
2646 pid = PyInt_AsLong(entry);
2648 entry = PyTuple_GET_ITEM(tuple, 2);
2649 if (!PyInt_Check(entry))
2651 composition_page_id = PyInt_AsLong(entry);
2653 entry = PyTuple_GET_ITEM(tuple, 3);
2654 if (!PyInt_Check(entry))
2656 ancillary_page_id = PyInt_AsLong(entry);
2658 m_subtitle_widget = new eSubtitleWidget(parent);
2659 m_subtitle_widget->resize(parent->size()); /* full size */
2660 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2662 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2668 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2669 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2670 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2674 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2676 delete m_subtitle_widget;
2677 m_subtitle_widget = 0;
2678 if (m_subtitle_parser)
2680 m_subtitle_parser->stop();
2681 m_dvb_subtitle_pages.clear();
2683 if (m_teletext_parser)
2685 m_teletext_parser->setPageAndMagazine(-1, -1);
2686 m_subtitle_pages.clear();
2689 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2693 PyObject *eDVBServicePlay::getCachedSubtitle()
2697 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2700 unsigned int data = (unsigned int)tmp;
2701 int pid = (data&0xFFFF0000)>>16;
2702 ePyObject tuple = PyTuple_New(4);
2703 eDVBServicePMTHandler::program program;
2704 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2705 if (!h.getProgramInfo(program))
2707 if (program.textPid==pid) // teletext
2708 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2710 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2711 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2712 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2713 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2721 PyObject *eDVBServicePlay::getSubtitleList()
2723 if (!m_teletext_parser)
2726 ePyObject l = PyList_New(0);
2727 std::set<int> added_ttx_pages;
2729 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2730 m_teletext_parser->m_found_subtitle_pages;
2732 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2733 eDVBServicePMTHandler::program program;
2734 if (h.getProgramInfo(program))
2735 eDebug("getting program info failed.");
2738 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2739 it != program.subtitleStreams.end(); ++it)
2741 switch(it->subtitling_type)
2743 case 0x01: // ebu teletext subtitles
2745 int page_number = it->teletext_page_number & 0xFF;
2746 int magazine_number = it->teletext_magazine_number & 7;
2747 int hash = magazine_number << 8 | page_number;
2748 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2750 ePyObject tuple = PyTuple_New(5);
2751 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2752 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2753 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2754 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2755 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2756 PyList_Append(l, tuple);
2758 added_ttx_pages.insert(hash);
2763 case 0x20 ... 0x23: // dvb subtitles
2765 ePyObject tuple = PyTuple_New(5);
2766 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2767 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2768 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2769 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2770 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2771 PyList_Insert(l, 0, tuple);
2779 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2780 it != subs.end(); ++it)
2782 int page_number = it->teletext_page_number & 0xFF;
2783 int magazine_number = it->teletext_magazine_number & 7;
2784 int hash = magazine_number << 8 | page_number;
2785 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2787 ePyObject tuple = PyTuple_New(5);
2788 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2789 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2790 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2791 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2792 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2793 PyList_Append(l, tuple);
2801 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2803 if (m_subtitle_widget)
2807 m_decoder->getPTS(0, pos);
2808 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2809 m_subtitle_pages.push_back(page);
2810 checkSubtitleTiming();
2814 void eDVBServicePlay::checkSubtitleTiming()
2816 eDebug("checkSubtitleTiming");
2817 if (!m_subtitle_widget)
2821 enum { TELETEXT, DVB } type;
2822 eDVBTeletextSubtitlePage page;
2823 eDVBSubtitlePage dvb_page;
2825 if (!m_subtitle_pages.empty())
2827 page = m_subtitle_pages.front();
2829 show_time = page.m_pts;
2831 else if (!m_dvb_subtitle_pages.empty())
2833 dvb_page = m_dvb_subtitle_pages.front();
2835 show_time = dvb_page.m_show_time;
2843 m_decoder->getPTS(0, pos);
2845 eDebug("%lld %lld", pos, show_time);
2846 int diff = show_time - pos;
2849 eDebug("[late (%d ms)]", -diff / 90);
2852 // if (diff > 900000)
2854 // eDebug("[invalid]");
2860 if (type == TELETEXT)
2862 eDebug("display teletext subtitle page %lld", show_time);
2863 m_subtitle_widget->setPage(page);
2864 m_subtitle_pages.pop_front();
2868 eDebug("display dvb subtitle Page %lld", show_time);
2869 m_subtitle_widget->setPage(dvb_page);
2870 m_dvb_subtitle_pages.pop_front();
2874 eDebug("start subtitle delay %d", diff / 90);
2875 m_subtitle_sync_timer.start(diff / 90, 1);
2881 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2883 if (m_subtitle_widget)
2887 m_decoder->getPTS(0, pos);
2888 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2889 m_dvb_subtitle_pages.push_back(p);
2890 checkSubtitleTiming();
2894 int eDVBServicePlay::getAC3Delay()
2897 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2899 return m_decoder->getAC3Delay();
2904 int eDVBServicePlay::getPCMDelay()
2907 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2909 return m_decoder->getPCMDelay();
2914 void eDVBServicePlay::setAC3Delay(int delay)
2917 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2919 m_decoder->setAC3Delay(delay);
2922 void eDVBServicePlay::setPCMDelay(int delay)
2925 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2927 m_decoder->setPCMDelay(delay);
2930 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2932 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2933 m_event((iPlayableService*)this, evVideoSizeChanged);
2936 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2942 PyObject *eDVBServicePlay::getStreamingData()
2944 eDVBServicePMTHandler::program program;
2945 if (m_service_handler.getProgramInfo(program))
2951 PyObject *r = program.createPythonObject();
2952 ePtr<iDVBDemux> demux;
2953 if (!m_service_handler.getDataDemux(demux))
2956 demux->getCADemuxID(demux_id);
2958 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
2965 DEFINE_REF(eDVBServicePlay)
2967 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2971 case iServiceInformation::sTransponderData:
2972 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2976 return iStaticServiceInformation::getInfoObject(ref, w);
2979 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");