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:
1107 eDebug("DVB service failed to tune - error %d", event);
1108 m_event((iPlayableService*)this, evTuneFailed);
1111 case eDVBServicePMTHandler::eventNewProgramInfo:
1113 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1114 if (m_timeshift_enabled)
1115 updateTimeshiftPids();
1116 if (!m_timeshift_active)
1118 if (m_first_program_info && m_is_pvr)
1120 m_first_program_info = 0;
1123 m_event((iPlayableService*)this, evUpdatedInfo);
1126 case eDVBServicePMTHandler::eventEOF:
1127 m_event((iPlayableService*)this, evEOF);
1129 case eDVBServicePMTHandler::eventSOF:
1130 m_event((iPlayableService*)this, evSOF);
1135 void eDVBServicePlay::serviceEventTimeshift(int event)
1139 case eDVBServicePMTHandler::eventNewProgramInfo:
1140 if (m_timeshift_active)
1143 case eDVBServicePMTHandler::eventSOF:
1144 m_event((iPlayableService*)this, evSOF);
1146 case eDVBServicePMTHandler::eventEOF:
1147 if ((!m_is_paused) && (m_skipmode >= 0))
1153 RESULT eDVBServicePlay::start()
1156 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1157 two (one for decoding, one for data source), as we must be prepared
1158 to start recording from the data demux. */
1160 m_cue = new eCueSheet();
1162 m_event(this, evStart);
1164 m_first_program_info = 1;
1165 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1166 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1168 /* inject EIT if there is a stored one */
1171 std::string filename = service.path;
1172 filename.erase(filename.length()-2, 2);
1174 ePtr<eServiceEvent> event = new eServiceEvent;
1175 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1177 ePtr<eServiceEvent> empty;
1178 m_event_handler.inject(event, 0);
1179 m_event_handler.inject(empty, 1);
1186 m_event(this, evStart);
1191 RESULT eDVBServicePlay::stop()
1193 /* add bookmark for last play position */
1196 pts_t play_position, length;
1197 if (!getPlayPosition(play_position))
1199 /* remove last position */
1200 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1202 if (i->what == 3) /* current play position */
1204 m_cue_entries.erase(i);
1205 i = m_cue_entries.begin();
1211 if (getLength(length))
1216 int perc = play_position * 100LL / length;
1218 /* only store last play position when between 5% and 95% */
1219 if ((5 < perc) && (perc < 95))
1220 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1222 m_cuesheet_changed = 1;
1226 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1228 m_service_handler_timeshift.free();
1229 m_service_handler.free();
1231 if (m_is_pvr && m_cuesheet_changed)
1234 /* save cuesheet only when main file is accessible. */
1235 if (!::stat(m_reference.path.c_str(), &s))
1238 m_event((iPlayableService*)this, evStopped);
1242 RESULT eDVBServicePlay::setTarget(int target)
1244 m_is_primary = !target;
1248 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1250 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1254 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1256 /* note: we check for timeshift to be enabled,
1257 not neccessary active. if you pause when timeshift
1258 is not active, you should activate it when unpausing */
1259 if ((!m_is_pvr) && (!m_timeshift_enabled))
1269 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1272 return m_decoder->setSlowMotion(ratio);
1277 RESULT eDVBServicePlay::setFastForward(int ratio)
1279 int skipmode, ffratio;
1285 } else if (ratio > 0)
1293 } else // if (ratio < 0)
1299 if (m_skipmode != skipmode)
1301 eDebug("setting cue skipmode to %d", skipmode);
1303 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1306 m_skipmode = skipmode;
1311 return m_decoder->setFastForward(ffratio);
1314 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1316 if (m_is_pvr || m_timeshift_enabled)
1326 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1327 RESULT eDVBServicePlay::getLength(pts_t &len)
1329 ePtr<iDVBPVRChannel> pvr_channel;
1331 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1334 return pvr_channel->getLength(len);
1337 RESULT eDVBServicePlay::pause()
1339 if (!m_is_paused && m_decoder)
1342 return m_decoder->freeze(0);
1347 RESULT eDVBServicePlay::unpause()
1349 if (m_is_paused && m_decoder)
1352 return m_decoder->unfreeze();
1357 RESULT eDVBServicePlay::seekTo(pts_t to)
1359 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1361 if (!m_decode_demux)
1364 ePtr<iDVBPVRChannel> pvr_channel;
1366 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1372 m_cue->seekTo(0, to);
1373 m_dvb_subtitle_pages.clear();
1374 m_subtitle_pages.clear();
1379 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1381 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1383 if (!m_decode_demux)
1386 ePtr<iDVBPVRChannel> pvr_channel;
1388 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1393 /* HACK until we have skip-AP api */
1394 if ((to > 0) && (to < 100))
1402 m_cue->seekTo(mode, to);
1403 m_dvb_subtitle_pages.clear();
1404 m_subtitle_pages.clear();
1408 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1410 ePtr<iDVBPVRChannel> pvr_channel;
1412 if (!m_decode_demux)
1415 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1420 /* if there is a decoder, use audio or video PTS */
1423 r = m_decoder->getPTS(0, pos);
1429 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1432 RESULT eDVBServicePlay::setTrickmode(int trick)
1435 m_decoder->setTrickmode(trick);
1439 RESULT eDVBServicePlay::isCurrentlySeekable()
1441 return m_is_pvr || m_timeshift_active;
1444 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1450 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1456 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1462 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1468 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1474 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1477 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1478 (m_timeshift_enabled || !m_is_pvr))
1480 if (!m_timeshift_enabled)
1482 /* we need enough diskspace */
1484 if (statfs(TSPATH "/.", &fs) < 0)
1486 eDebug("statfs failed!");
1490 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1492 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1502 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1513 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1519 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1525 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1531 RESULT eDVBServicePlay::getName(std::string &name)
1535 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1536 return i->getName(m_reference, name);
1540 m_dvb_service->getName(m_reference, name);
1544 else if (!m_reference.name.empty())
1545 eStaticServiceDVBInformation().getName(m_reference, name);
1547 name = "DVB service";
1551 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1553 return m_event_handler.getEvent(evt, nownext);
1556 int eDVBServicePlay::getInfo(int w)
1558 eDVBServicePMTHandler::program program;
1561 return resIsPyObject;
1563 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1565 int no_program_info = 0;
1567 if (h.getProgramInfo(program))
1568 no_program_info = 1;
1572 #if HAVE_DVB_API_VERSION >= 3
1574 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1575 return m_videoEventData.height;
1578 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1579 return m_videoEventData.width;
1582 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1585 #if HAVE_DVB_API_VERSION >= 3
1586 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1587 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1590 #warning "FIXMEE implement sAspect for old DVB API"
1592 if (no_program_info)
1594 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1596 ePtr<eServiceEvent> evt;
1597 if (!m_event_handler.getEvent(evt, 0))
1599 ePtr<eComponentData> data;
1600 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1602 if ( data->getStreamContent() == 1 )
1604 switch(data->getComponentType())
1607 case 1: // 4:3 SD PAL
1609 case 3: // 16:9 SD PAL
1610 case 4: // > 16:9 PAL
1611 case 5: // 4:3 SD NTSC
1613 case 7: // 16:9 SD NTSC
1614 case 8: // > 16:9 NTSC
1617 case 9: // 4:3 HD PAL
1619 case 0xB: // 16:9 HD PAL
1620 case 0xC: // > 16:9 HD PAL
1621 case 0xD: // 4:3 HD NTSC
1623 case 0xF: // 16:9 HD NTSC
1624 case 0x10: // > 16:9 HD PAL
1625 return data->getComponentType();
1632 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1633 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1634 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1635 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1636 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1637 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1638 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1639 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1640 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1641 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1642 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1643 case sProvider: if (!m_dvb_service) return -1; return -2;
1644 case sServiceref: return resIsString;
1645 case sDVBState: return m_tune_state;
1651 std::string eDVBServicePlay::getInfoString(int w)
1656 if (!m_dvb_service) return "";
1657 return m_dvb_service->m_provider_name;
1659 return m_reference.toString();
1663 return iServiceInformation::getInfoString(w);
1666 PyObject *eDVBServicePlay::getInfoObject(int w)
1671 return m_service_handler.getCaIds();
1672 case sTransponderData:
1673 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1677 return iServiceInformation::getInfoObject(w);
1680 int eDVBServicePlay::getNumberOfTracks()
1682 eDVBServicePMTHandler::program program;
1683 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1684 if (h.getProgramInfo(program))
1686 return program.audioStreams.size();
1689 int eDVBServicePlay::getCurrentTrack()
1691 eDVBServicePMTHandler::program program;
1692 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1693 if (h.getProgramInfo(program))
1696 int max = program.audioStreams.size();
1699 for (i = 0; i < max; ++i)
1700 if (program.audioStreams[i].pid == m_current_audio_pid)
1706 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1708 int ret = selectAudioStream(i);
1710 if (m_decoder->start())
1716 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1718 eDVBServicePMTHandler::program program;
1719 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1721 if (h.getProgramInfo(program))
1724 if (i >= program.audioStreams.size())
1727 info.m_pid = program.audioStreams[i].pid;
1729 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1730 info.m_description = "MPEG";
1731 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1732 info.m_description = "AC3";
1733 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1734 info.m_description = "AAC";
1735 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1736 info.m_description = "DTS";
1738 info.m_description = "???";
1740 if (program.audioStreams[i].component_tag != -1)
1742 ePtr<eServiceEvent> evt;
1743 if (!m_event_handler.getEvent(evt, 0))
1745 ePtr<eComponentData> data;
1746 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1747 info.m_language = data->getText();
1751 if (info.m_language.empty())
1752 info.m_language = program.audioStreams[i].language_code;
1757 int eDVBServicePlay::selectAudioStream(int i)
1759 eDVBServicePMTHandler::program program;
1760 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1762 if (h.getProgramInfo(program))
1765 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1773 stream = program.defaultAudioStream;
1775 int apid = -1, apidtype = -1;
1777 if (((unsigned int)stream) < program.audioStreams.size())
1779 apid = program.audioStreams[stream].pid;
1780 apidtype = program.audioStreams[stream].type;
1783 m_current_audio_pid = apid;
1785 if (m_decoder->setAudioPID(apid, apidtype))
1787 eDebug("set audio pid failed");
1791 /* 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 */
1792 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1795 ePtr<iDVBDemux> data_demux;
1796 if (!h.getDataDemux(data_demux))
1798 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1799 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1803 /* if we decided that we need one, update the pid */
1805 m_rds_decoder->start(apid);
1807 /* store new pid as default only when:
1808 a.) we have an entry in the service db for the current service,
1809 b.) we are not playing back something,
1810 c.) we are not selecting the default entry. (we wouldn't change
1811 anything in the best case, or destroy the default setting in
1812 case the real default is not yet available.)
1814 if (m_dvb_service && !m_is_pvr && ((i != -1)
1815 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1817 if (apidtype == eDVBAudio::aMPEG)
1819 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1820 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1824 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1825 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1829 h.resetCachedProgram();
1834 int eDVBServicePlay::getCurrentChannel()
1836 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1839 RESULT eDVBServicePlay::selectChannel(int i)
1841 if (i < LEFT || i > RIGHT || i == STEREO)
1844 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1846 m_decoder->setAudioChannel(i);
1850 std::string eDVBServicePlay::getText(int x)
1856 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1858 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1863 void eDVBServicePlay::rdsDecoderEvent(int what)
1867 case eDVBRdsDecoder::RadioTextChanged:
1868 m_event((iPlayableService*)this, evUpdatedRadioText);
1870 case eDVBRdsDecoder::RtpTextChanged:
1871 m_event((iPlayableService*)this, evUpdatedRtpText);
1873 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1874 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1876 case eDVBRdsDecoder::RecvRassSlidePic:
1877 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1882 void eDVBServicePlay::showRassSlidePicture()
1888 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1889 if (rass_slide_pic.length())
1890 m_decoder->showSinglePic(rass_slide_pic.c_str());
1892 eDebug("empty filename for rass slide picture received!!");
1895 eDebug("no MPEG Decoder to show iframes avail");
1898 eDebug("showRassSlidePicture called.. but not decoder");
1901 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1907 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1908 if (rass_interactive_pic.length())
1909 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1911 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1914 eDebug("no MPEG Decoder to show iframes avail");
1917 eDebug("showRassInteractivePic called.. but not decoder");
1920 ePyObject eDVBServicePlay::getRassInteractiveMask()
1923 return m_rds_decoder->getRassPictureMask();
1927 int eDVBServiceBase::getFrontendInfo(int w)
1929 eUsePtr<iDVBChannel> channel;
1930 if(m_service_handler.getChannel(channel))
1932 ePtr<iDVBFrontend> fe;
1933 if(channel->getFrontend(fe))
1935 return fe->readFrontendData(w);
1938 PyObject *eDVBServiceBase::getFrontendData()
1940 ePyObject ret = PyDict_New();
1943 eUsePtr<iDVBChannel> channel;
1944 if(!m_service_handler.getChannel(channel))
1946 ePtr<iDVBFrontend> fe;
1947 if(!channel->getFrontend(fe))
1948 fe->getFrontendData(ret);
1956 PyObject *eDVBServiceBase::getFrontendStatus()
1958 ePyObject ret = PyDict_New();
1961 eUsePtr<iDVBChannel> channel;
1962 if(!m_service_handler.getChannel(channel))
1964 ePtr<iDVBFrontend> fe;
1965 if(!channel->getFrontend(fe))
1966 fe->getFrontendStatus(ret);
1974 PyObject *eDVBServiceBase::getTransponderData(bool original)
1976 ePyObject ret = PyDict_New();
1979 eUsePtr<iDVBChannel> channel;
1980 if(!m_service_handler.getChannel(channel))
1982 ePtr<iDVBFrontend> fe;
1983 if(!channel->getFrontend(fe))
1985 fe->getTransponderData(ret, original);
1986 ePtr<iDVBFrontendParameters> feparm;
1987 channel->getCurrentFrontendParameters(feparm);
1990 eDVBFrontendParametersSatellite osat;
1991 if (!feparm->getDVBS(osat))
1993 void PutToDict(ePyObject &, const char*, long);
1994 void PutToDict(ePyObject &, const char*, const char*);
1995 PutToDict(ret, "orbital_position", osat.orbital_position);
1996 const char *tmp = "UNKNOWN";
1997 switch(osat.polarisation)
1999 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2000 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2001 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2002 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2005 PutToDict(ret, "polarization", tmp);
2016 PyObject *eDVBServiceBase::getAll(bool original)
2018 ePyObject ret = getTransponderData(original);
2021 eUsePtr<iDVBChannel> channel;
2022 if(!m_service_handler.getChannel(channel))
2024 ePtr<iDVBFrontend> fe;
2025 if(!channel->getFrontend(fe))
2027 fe->getFrontendData(ret);
2028 fe->getFrontendStatus(ret);
2035 int eDVBServicePlay::getNumberOfSubservices()
2037 ePtr<eServiceEvent> evt;
2038 if (!m_event_handler.getEvent(evt, 0))
2039 return evt->getNumOfLinkageServices();
2043 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2045 ePtr<eServiceEvent> evt;
2046 if (!m_event_handler.getEvent(evt, 0))
2048 if (!evt->getLinkageService(sub, m_reference, n))
2051 sub.type=eServiceReference::idInvalid;
2055 RESULT eDVBServicePlay::startTimeshift()
2057 ePtr<iDVBDemux> demux;
2059 eDebug("Start timeshift!");
2061 if (m_timeshift_enabled)
2064 /* start recording with the data demux. */
2065 if (m_service_handler.getDataDemux(demux))
2068 demux->createTSRecorder(m_record);
2072 char templ[]=TSPATH "/timeshift.XXXXXX";
2073 m_timeshift_fd = mkstemp(templ);
2074 m_timeshift_file = templ;
2076 eDebug("recording to %s", templ);
2078 if (m_timeshift_fd < 0)
2084 m_record->setTargetFD(m_timeshift_fd);
2086 m_timeshift_enabled = 1;
2088 updateTimeshiftPids();
2094 RESULT eDVBServicePlay::stopTimeshift()
2096 if (!m_timeshift_enabled)
2101 m_timeshift_enabled = 0;
2106 close(m_timeshift_fd);
2107 eDebug("remove timeshift file");
2108 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2113 int eDVBServicePlay::isTimeshiftActive()
2115 return m_timeshift_enabled && m_timeshift_active;
2118 RESULT eDVBServicePlay::activateTimeshift()
2120 if (!m_timeshift_enabled)
2123 if (!m_timeshift_active)
2125 switchToTimeshift();
2132 PyObject *eDVBServicePlay::getCutList()
2134 ePyObject list = PyList_New(0);
2136 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2138 ePyObject tuple = PyTuple_New(2);
2139 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2140 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2141 PyList_Append(list, tuple);
2148 void eDVBServicePlay::setCutList(ePyObject list)
2150 if (!PyList_Check(list))
2152 int size = PyList_Size(list);
2155 m_cue_entries.clear();
2157 for (i=0; i<size; ++i)
2159 ePyObject tuple = PyList_GET_ITEM(list, i);
2160 if (!PyTuple_Check(tuple))
2162 eDebug("non-tuple in cutlist");
2165 if (PyTuple_Size(tuple) != 2)
2167 eDebug("cutlist entries need to be a 2-tuple");
2170 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2171 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2173 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2176 pts_t pts = PyLong_AsLongLong(ppts);
2177 int type = PyInt_AsLong(ptype);
2178 m_cue_entries.insert(cueEntry(pts, type));
2179 eDebug("adding %08llx, %d", pts, type);
2181 m_cuesheet_changed = 1;
2183 cutlistToCuesheet();
2184 m_event((iPlayableService*)this, evCuesheetChanged);
2187 void eDVBServicePlay::setCutListEnable(int enable)
2189 m_cutlist_enabled = enable;
2190 cutlistToCuesheet();
2193 void eDVBServicePlay::updateTimeshiftPids()
2198 eDVBServicePMTHandler::program program;
2199 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2201 if (h.getProgramInfo(program))
2205 std::set<int> pids_to_record;
2206 pids_to_record.insert(0); // PAT
2207 if (program.pmtPid != -1)
2208 pids_to_record.insert(program.pmtPid); // PMT
2210 if (program.textPid != -1)
2211 pids_to_record.insert(program.textPid); // Videotext
2213 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2214 i(program.videoStreams.begin());
2215 i != program.videoStreams.end(); ++i)
2216 pids_to_record.insert(i->pid);
2218 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2219 i(program.audioStreams.begin());
2220 i != program.audioStreams.end(); ++i)
2221 pids_to_record.insert(i->pid);
2223 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2224 i(program.subtitleStreams.begin());
2225 i != program.subtitleStreams.end(); ++i)
2226 pids_to_record.insert(i->pid);
2228 std::set<int> new_pids, obsolete_pids;
2230 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2231 m_pids_active.begin(), m_pids_active.end(),
2232 std::inserter(new_pids, new_pids.begin()));
2234 std::set_difference(
2235 m_pids_active.begin(), m_pids_active.end(),
2236 pids_to_record.begin(), pids_to_record.end(),
2237 std::inserter(new_pids, new_pids.begin())
2240 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2241 m_record->addPID(*i);
2243 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2244 m_record->removePID(*i);
2248 void eDVBServicePlay::switchToLive()
2250 if (!m_timeshift_active)
2256 m_teletext_parser = 0;
2258 m_subtitle_parser = 0;
2259 m_new_dvb_subtitle_page_connection = 0;
2260 m_new_subtitle_page_connection = 0;
2261 m_rds_decoder_event_connection = 0;
2262 m_video_event_connection = 0;
2264 /* free the timeshift service handler, we need the resources */
2265 m_service_handler_timeshift.free();
2266 m_timeshift_active = 0;
2268 m_event((iPlayableService*)this, evSeekableStatusChanged);
2273 void eDVBServicePlay::switchToTimeshift()
2275 if (m_timeshift_active)
2280 m_teletext_parser = 0;
2282 m_subtitle_parser = 0;
2283 m_new_subtitle_page_connection = 0;
2284 m_new_dvb_subtitle_page_connection = 0;
2285 m_rds_decoder_event_connection = 0;
2286 m_video_event_connection = 0;
2288 m_timeshift_active = 1;
2290 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2291 r.path = m_timeshift_file;
2293 m_cue = new eCueSheet();
2294 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2296 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2298 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2300 m_event((iPlayableService*)this, evSeekableStatusChanged);
2303 void eDVBServicePlay::updateDecoder()
2305 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2307 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2309 eDVBServicePMTHandler::program program;
2310 if (h.getProgramInfo(program))
2311 eDebug("getting program info failed.");
2314 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2315 if (!program.videoStreams.empty())
2317 eDebugNoNewLine(" (");
2318 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2319 i(program.videoStreams.begin());
2320 i != program.videoStreams.end(); ++i)
2327 if (i != program.videoStreams.begin())
2328 eDebugNoNewLine(", ");
2329 eDebugNoNewLine("%04x", i->pid);
2331 eDebugNoNewLine(")");
2333 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2334 if (!program.audioStreams.empty())
2336 eDebugNoNewLine(" (");
2337 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2338 i(program.audioStreams.begin());
2339 i != program.audioStreams.end(); ++i)
2341 if (i != program.audioStreams.begin())
2342 eDebugNoNewLine(", ");
2343 eDebugNoNewLine("%04x", i->pid);
2345 eDebugNoNewLine(")");
2347 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2348 pcrpid = program.pcrPid;
2349 eDebug(", and the text pid is %04x", program.textPid);
2350 tpid = program.textPid;
2355 h.getDecodeDemux(m_decode_demux);
2358 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2360 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2361 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2362 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2363 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2364 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2367 m_teletext_parser = 0;
2368 m_subtitle_parser = 0;
2372 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2379 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2380 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2381 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2383 else // subservice or recording
2385 eServiceReferenceDVB ref;
2386 m_service_handler.getServiceReference(ref);
2387 eServiceReferenceDVB parent = ref.getParentServiceReference();
2392 ePtr<eDVBResourceManager> res_mgr;
2393 if (!eDVBResourceManager::getInstance(res_mgr))
2395 ePtr<iDVBChannelList> db;
2396 if (!res_mgr->getChannelList(db))
2398 ePtr<eDVBService> origService;
2399 if (!db->getService(parent, origService))
2401 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2402 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2408 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2409 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2411 m_decoder->setVideoPID(vpid, vpidtype);
2412 selectAudioStream();
2414 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2415 m_decoder->setSyncPCR(pcrpid);
2417 m_decoder->setSyncPCR(-1);
2419 m_decoder->setTextPID(tpid);
2421 m_teletext_parser->start(program.textPid);
2424 m_decoder->setTrickmode(1);
2427 m_decoder->preroll();
2431 if (vpid > 0 && vpid < 0x2000)
2435 std::string radio_pic;
2436 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2437 m_decoder->setRadioPic(radio_pic);
2440 m_decoder->setAudioChannel(achannel);
2442 /* don't worry about non-existing services, nor pvr services */
2443 if (m_dvb_service && !m_is_pvr)
2445 /* (audio pid will be set in selectAudioTrack */
2446 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2447 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2448 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2449 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2452 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2455 void eDVBServicePlay::loadCuesheet()
2457 std::string filename = m_reference.path + ".cuts";
2459 m_cue_entries.clear();
2461 FILE *f = fopen(filename.c_str(), "rb");
2465 eDebug("loading cuts..");
2468 unsigned long long where;
2471 if (!fread(&where, sizeof(where), 1, f))
2473 if (!fread(&what, sizeof(what), 1, f))
2476 #if BYTE_ORDER == LITTLE_ENDIAN
2477 where = bswap_64(where);
2484 m_cue_entries.insert(cueEntry(where, what));
2487 eDebug("%d entries", m_cue_entries.size());
2489 eDebug("cutfile not found!");
2491 m_cuesheet_changed = 0;
2492 cutlistToCuesheet();
2493 m_event((iPlayableService*)this, evCuesheetChanged);
2496 void eDVBServicePlay::saveCuesheet()
2498 std::string filename = m_reference.path + ".cuts";
2500 FILE *f = fopen(filename.c_str(), "wb");
2504 unsigned long long where;
2507 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2509 #if BYTE_ORDER == BIG_ENDIAN
2512 where = bswap_64(i->where);
2514 what = htonl(i->what);
2515 fwrite(&where, sizeof(where), 1, f);
2516 fwrite(&what, sizeof(what), 1, f);
2522 m_cuesheet_changed = 0;
2525 void eDVBServicePlay::cutlistToCuesheet()
2529 eDebug("no cue sheet");
2534 if (!m_cutlist_enabled)
2536 m_cue->commitSpans();
2537 eDebug("cutlists were disabled");
2541 pts_t in = 0, out = 0, length = 0;
2545 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2549 if (i == m_cue_entries.end())
2552 if (i->what == 0) /* in */
2556 } else if (i->what == 1) /* out */
2558 else /* mark (2) or last play position (3) */
2566 m_cue->addSourceSpan(in, out);
2570 if (i == m_cue_entries.end())
2573 m_cue->commitSpans();
2576 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2578 if (m_subtitle_widget)
2579 disableSubtitles(parent);
2582 int tuplesize = PyTuple_Size(tuple);
2585 if (!PyTuple_Check(tuple))
2591 entry = PyTuple_GET_ITEM(tuple, 0);
2593 if (!PyInt_Check(entry))
2596 type = PyInt_AsLong(entry);
2598 if (type == 1) // teletext subtitles
2600 int page, magazine, pid;
2604 if (!m_teletext_parser)
2606 eDebug("enable teletext subtitles.. no parser !!!");
2610 entry = PyTuple_GET_ITEM(tuple, 1);
2611 if (!PyInt_Check(entry))
2613 pid = PyInt_AsLong(entry);
2615 entry = PyTuple_GET_ITEM(tuple, 2);
2616 if (!PyInt_Check(entry))
2618 page = PyInt_AsLong(entry);
2620 entry = PyTuple_GET_ITEM(tuple, 3);
2621 if (!PyInt_Check(entry))
2623 magazine = PyInt_AsLong(entry);
2625 m_subtitle_widget = new eSubtitleWidget(parent);
2626 m_subtitle_widget->resize(parent->size()); /* full size */
2627 m_teletext_parser->setPageAndMagazine(page, magazine);
2629 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2633 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2634 if (!m_subtitle_parser)
2636 eDebug("enable dvb subtitles.. no parser !!!");
2642 entry = PyTuple_GET_ITEM(tuple, 1);
2643 if (!PyInt_Check(entry))
2645 pid = PyInt_AsLong(entry);
2647 entry = PyTuple_GET_ITEM(tuple, 2);
2648 if (!PyInt_Check(entry))
2650 composition_page_id = PyInt_AsLong(entry);
2652 entry = PyTuple_GET_ITEM(tuple, 3);
2653 if (!PyInt_Check(entry))
2655 ancillary_page_id = PyInt_AsLong(entry);
2657 m_subtitle_widget = new eSubtitleWidget(parent);
2658 m_subtitle_widget->resize(parent->size()); /* full size */
2659 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2661 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2667 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2668 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2669 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2673 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2675 delete m_subtitle_widget;
2676 m_subtitle_widget = 0;
2677 if (m_subtitle_parser)
2679 m_subtitle_parser->stop();
2680 m_dvb_subtitle_pages.clear();
2682 if (m_teletext_parser)
2684 m_teletext_parser->setPageAndMagazine(-1, -1);
2685 m_subtitle_pages.clear();
2688 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2692 PyObject *eDVBServicePlay::getCachedSubtitle()
2696 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2699 unsigned int data = (unsigned int)tmp;
2700 int pid = (data&0xFFFF0000)>>16;
2701 ePyObject tuple = PyTuple_New(4);
2702 eDVBServicePMTHandler::program program;
2703 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2704 if (!h.getProgramInfo(program))
2706 if (program.textPid==pid) // teletext
2707 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2709 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2710 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2711 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2712 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2720 PyObject *eDVBServicePlay::getSubtitleList()
2722 if (!m_teletext_parser)
2725 ePyObject l = PyList_New(0);
2726 std::set<int> added_ttx_pages;
2728 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2729 m_teletext_parser->m_found_subtitle_pages;
2731 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2732 eDVBServicePMTHandler::program program;
2733 if (h.getProgramInfo(program))
2734 eDebug("getting program info failed.");
2737 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2738 it != program.subtitleStreams.end(); ++it)
2740 switch(it->subtitling_type)
2742 case 0x01: // ebu teletext subtitles
2744 int page_number = it->teletext_page_number & 0xFF;
2745 int magazine_number = it->teletext_magazine_number & 7;
2746 int hash = magazine_number << 8 | page_number;
2747 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2749 ePyObject tuple = PyTuple_New(5);
2750 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2751 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2752 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2753 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2754 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2755 PyList_Append(l, tuple);
2757 added_ttx_pages.insert(hash);
2762 case 0x20 ... 0x23: // dvb subtitles
2764 ePyObject tuple = PyTuple_New(5);
2765 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2766 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2767 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2768 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2769 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2770 PyList_Insert(l, 0, tuple);
2778 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2779 it != subs.end(); ++it)
2781 int page_number = it->teletext_page_number & 0xFF;
2782 int magazine_number = it->teletext_magazine_number & 7;
2783 int hash = magazine_number << 8 | page_number;
2784 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2786 ePyObject tuple = PyTuple_New(5);
2787 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2788 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2789 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2790 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2791 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2792 PyList_Append(l, tuple);
2800 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2802 if (m_subtitle_widget)
2806 m_decoder->getPTS(0, pos);
2807 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2808 m_subtitle_pages.push_back(page);
2809 checkSubtitleTiming();
2813 void eDVBServicePlay::checkSubtitleTiming()
2815 eDebug("checkSubtitleTiming");
2816 if (!m_subtitle_widget)
2820 enum { TELETEXT, DVB } type;
2821 eDVBTeletextSubtitlePage page;
2822 eDVBSubtitlePage dvb_page;
2824 if (!m_subtitle_pages.empty())
2826 page = m_subtitle_pages.front();
2828 show_time = page.m_pts;
2830 else if (!m_dvb_subtitle_pages.empty())
2832 dvb_page = m_dvb_subtitle_pages.front();
2834 show_time = dvb_page.m_show_time;
2842 m_decoder->getPTS(0, pos);
2844 eDebug("%lld %lld", pos, show_time);
2845 int diff = show_time - pos;
2848 eDebug("[late (%d ms)]", -diff / 90);
2851 // if (diff > 900000)
2853 // eDebug("[invalid]");
2859 if (type == TELETEXT)
2861 eDebug("display teletext subtitle page %lld", show_time);
2862 m_subtitle_widget->setPage(page);
2863 m_subtitle_pages.pop_front();
2867 eDebug("display dvb subtitle Page %lld", show_time);
2868 m_subtitle_widget->setPage(dvb_page);
2869 m_dvb_subtitle_pages.pop_front();
2873 eDebug("start subtitle delay %d", diff / 90);
2874 m_subtitle_sync_timer.start(diff / 90, 1);
2880 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2882 if (m_subtitle_widget)
2886 m_decoder->getPTS(0, pos);
2887 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2888 m_dvb_subtitle_pages.push_back(p);
2889 checkSubtitleTiming();
2893 int eDVBServicePlay::getAC3Delay()
2896 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2898 return m_decoder->getAC3Delay();
2903 int eDVBServicePlay::getPCMDelay()
2906 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2908 return m_decoder->getPCMDelay();
2913 void eDVBServicePlay::setAC3Delay(int delay)
2916 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2918 m_decoder->setAC3Delay(delay);
2921 void eDVBServicePlay::setPCMDelay(int delay)
2924 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2926 m_decoder->setPCMDelay(delay);
2929 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2931 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2932 m_event((iPlayableService*)this, evVideoSizeChanged);
2935 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2941 PyObject *eDVBServicePlay::getStreamingData()
2943 eDVBServicePMTHandler::program program;
2944 if (m_service_handler.getProgramInfo(program))
2950 PyObject *r = program.createPythonObject();
2951 ePtr<iDVBDemux> demux;
2952 if (!m_service_handler.getDataDemux(demux))
2955 demux->getCADemuxID(demux_id);
2957 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
2964 DEFINE_REF(eDVBServicePlay)
2966 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2970 case iServiceInformation::sTransponderData:
2971 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2975 return iStaticServiceInformation::getInfoObject(ref, w);
2978 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");