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);
672 std::list<std::string> extensions;
673 extensions.push_back("ts");
674 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
677 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
678 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
681 eServiceFactoryDVB::~eServiceFactoryDVB()
683 ePtr<eServiceCenter> sc;
685 eServiceCenter::getPrivInstance(sc);
687 sc->removeServiceFactory(eServiceFactoryDVB::id);
690 DEFINE_REF(eDVBServiceList);
692 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
696 eDVBServiceList::~eDVBServiceList()
700 RESULT eDVBServiceList::startQuery()
702 ePtr<iDVBChannelList> db;
703 ePtr<eDVBResourceManager> res;
706 if ((err = eDVBResourceManager::getInstance(res)) != 0)
708 eDebug("no resource manager");
711 if ((err = res->getChannelList(db)) != 0)
713 eDebug("no channel list");
717 ePtr<eDVBChannelQuery> q;
719 if (!m_parent.path.empty())
721 eDVBChannelQuery::compile(q, m_parent.path);
724 eDebug("compile query failed");
729 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
731 eDebug("startQuery failed");
738 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
740 eServiceReferenceDVB ref;
745 while (!m_query->getNextResult(ref))
749 list.sort(iListableServiceCompare(this));
754 // The first argument of this function is a format string to specify the order and
755 // the content of the returned list
756 // useable format options are
757 // R = Service Reference (as swig object .. this is very slow)
758 // S = Service Reference (as python string object .. same as ref.toString())
759 // C = Service Reference (as python string object .. same as ref.toCompareString())
760 // N = Service Name (as python string object)
761 // n = Short Service Name (short name brakets used) (as python string object)
762 // when exactly one return value per service is selected in the format string,
763 // then each value is directly a list entry
764 // when more than one value is returned per service, then the list is a list of
766 // unknown format string chars are returned as python None values !
767 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
770 std::list<eServiceReference> tmplist;
773 if (!format || !(retcount=strlen(format)))
774 format = "R"; // just return service reference swig object ...
776 if (!getContent(tmplist, sorted))
778 int services=tmplist.size();
779 ePtr<iStaticServiceInformation> sptr;
780 eServiceCenterPtr service_center;
782 if (strchr(format, 'N') || strchr(format, 'n'))
783 eServiceCenter::getPrivInstance(service_center);
785 ret = PyList_New(services);
786 std::list<eServiceReference>::iterator it(tmplist.begin());
788 for (int cnt=0; cnt < services; ++cnt)
790 eServiceReference &ref=*it++;
791 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
792 for (int i=0; i < retcount; ++i)
797 case 'R': // service reference (swig)object
798 tmp = NEW_eServiceReference(ref);
800 case 'C': // service reference compare string
801 tmp = PyString_FromString(ref.toCompareString().c_str());
803 case 'S': // service reference string
804 tmp = PyString_FromString(ref.toString().c_str());
806 case 'N': // service name
809 service_center->info(ref, sptr);
813 sptr->getName(ref, name);
815 // filter short name brakets
817 while((pos = name.find("\xc2\x86")) != std::string::npos)
819 while((pos = name.find("\xc2\x87")) != std::string::npos)
823 tmp = PyString_FromString(name.c_str());
827 tmp = PyString_FromString("<n/a>");
829 case 'n': // short service name
832 service_center->info(ref, sptr);
836 sptr->getName(ref, name);
837 name = buildShortName(name);
839 tmp = PyString_FromString(name.c_str());
843 tmp = PyString_FromString("<n/a>");
856 PyTuple_SET_ITEM(tuple, i, tmp);
858 PyList_SET_ITEM(ret, cnt, tmp);
862 PyList_SET_ITEM(ret, cnt, tuple);
865 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
868 RESULT eDVBServiceList::getNext(eServiceReference &ref)
873 return m_query->getNextResult((eServiceReferenceDVB&)ref);
876 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
878 if (m_parent.flags & eServiceReference::canDescent) // bouquet
880 ePtr<iDVBChannelList> db;
881 ePtr<eDVBResourceManager> resm;
883 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
886 if (db->getBouquet(m_parent, m_bouquet) != 0)
897 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
901 return m_bouquet->addService(ref, before);
904 RESULT eDVBServiceList::removeService(eServiceReference &ref)
908 return m_bouquet->removeService(ref);
911 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
915 return m_bouquet->moveService(ref, pos);
918 RESULT eDVBServiceList::flushChanges()
922 return m_bouquet->flushChanges();
925 RESULT eDVBServiceList::setListName(const std::string &name)
929 return m_bouquet->setListName(name);
932 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
934 ePtr<eDVBService> service;
935 int r = lookupService(service, ref);
938 // check resources...
939 ptr = new eDVBServicePlay(ref, service);
943 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
945 if (ref.path.empty())
947 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
956 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
958 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
959 if (list->startQuery())
969 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
971 /* is a listable service? */
972 if (ref.flags & eServiceReference::canDescent) // bouquet
974 if ( !ref.name.empty() ) // satellites or providers list
975 ptr = m_StaticServiceDVBInfo;
976 else // a dvb bouquet
977 ptr = m_StaticServiceDVBBouquetInfo;
979 else if (!ref.path.empty()) /* do we have a PVR service? */
980 ptr = new eStaticServiceDVBPVRInformation(ref);
981 else // normal dvb service
983 ePtr<eDVBService> service;
984 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
985 ptr = m_StaticServiceDVBInfo;
987 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
993 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
995 if (ref.path.empty())
1001 ptr = new eDVBPVRServiceOfflineOperations(ref);
1006 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
1008 // TODO: handle the listing itself
1009 // if (ref.... == -1) .. return "... bouquets ...";
1010 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
1012 ePtr<iDVBChannelList> db;
1013 ePtr<eDVBResourceManager> res;
1016 if ((err = eDVBResourceManager::getInstance(res)) != 0)
1018 eDebug("no resource manager");
1021 if ((err = res->getChannelList(db)) != 0)
1023 eDebug("no channel list");
1027 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
1028 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
1030 eDebug("getService failed!");
1037 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
1038 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
1040 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
1042 m_is_pvr = !m_reference.path.empty();
1044 m_timeshift_enabled = m_timeshift_active = 0;
1047 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
1048 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
1049 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
1051 m_cuesheet_changed = 0;
1052 m_cutlist_enabled = 1;
1054 m_subtitle_widget = 0;
1058 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
1061 eDVBServicePlay::~eDVBServicePlay()
1063 delete m_subtitle_widget;
1066 void eDVBServicePlay::gotNewEvent()
1070 ePtr<eServiceEvent> m_event_now, m_event_next;
1071 getEvent(m_event_now, 0);
1072 getEvent(m_event_next, 1);
1075 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1077 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1079 m_event((iPlayableService*)this, evUpdatedEventInfo);
1082 void eDVBServicePlay::serviceEvent(int event)
1084 m_tune_state = event;
1088 case eDVBServicePMTHandler::eventTuned:
1090 ePtr<iDVBDemux> m_demux;
1091 if (!m_service_handler.getDataDemux(m_demux))
1093 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1094 int sid = ref.getParentServiceID().get();
1096 sid = ref.getServiceID().get();
1097 if ( ref.getParentTransportStreamID().get() &&
1098 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1099 m_event_handler.startOther(m_demux, sid);
1101 m_event_handler.start(m_demux, sid);
1105 case eDVBServicePMTHandler::eventNoResources:
1106 case eDVBServicePMTHandler::eventNoPAT:
1107 case eDVBServicePMTHandler::eventNoPATEntry:
1108 case eDVBServicePMTHandler::eventNoPMT:
1109 case eDVBServicePMTHandler::eventTuneFailed:
1110 case eDVBServicePMTHandler::eventMisconfiguration:
1112 eDebug("DVB service failed to tune - error %d", event);
1113 m_event((iPlayableService*)this, evTuneFailed);
1116 case eDVBServicePMTHandler::eventNewProgramInfo:
1118 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1119 if (m_timeshift_enabled)
1120 updateTimeshiftPids();
1121 if (!m_timeshift_active)
1123 if (m_first_program_info && m_is_pvr)
1125 m_first_program_info = 0;
1128 m_event((iPlayableService*)this, evUpdatedInfo);
1131 case eDVBServicePMTHandler::eventEOF:
1132 m_event((iPlayableService*)this, evEOF);
1134 case eDVBServicePMTHandler::eventSOF:
1135 m_event((iPlayableService*)this, evSOF);
1140 void eDVBServicePlay::serviceEventTimeshift(int event)
1144 case eDVBServicePMTHandler::eventNewProgramInfo:
1145 if (m_timeshift_active)
1148 case eDVBServicePMTHandler::eventSOF:
1149 m_event((iPlayableService*)this, evSOF);
1151 case eDVBServicePMTHandler::eventEOF:
1152 if ((!m_is_paused) && (m_skipmode >= 0))
1158 RESULT eDVBServicePlay::start()
1161 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1162 two (one for decoding, one for data source), as we must be prepared
1163 to start recording from the data demux. */
1165 m_cue = new eCueSheet();
1167 m_event(this, evStart);
1169 m_first_program_info = 1;
1170 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1171 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1173 /* inject EIT if there is a stored one */
1176 std::string filename = service.path;
1177 filename.erase(filename.length()-2, 2);
1179 ePtr<eServiceEvent> event = new eServiceEvent;
1180 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1182 ePtr<eServiceEvent> empty;
1183 m_event_handler.inject(event, 0);
1184 m_event_handler.inject(empty, 1);
1191 m_event(this, evStart);
1196 RESULT eDVBServicePlay::stop()
1198 /* add bookmark for last play position */
1201 pts_t play_position, length;
1202 if (!getPlayPosition(play_position))
1204 /* remove last position */
1205 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1207 if (i->what == 3) /* current play position */
1209 m_cue_entries.erase(i);
1210 i = m_cue_entries.begin();
1216 if (getLength(length))
1221 int perc = play_position * 100LL / length;
1223 /* only store last play position when between 5% and 95% */
1224 if ((5 < perc) && (perc < 95))
1225 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1227 m_cuesheet_changed = 1;
1231 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1233 m_service_handler_timeshift.free();
1234 m_service_handler.free();
1236 if (m_is_pvr && m_cuesheet_changed)
1239 /* save cuesheet only when main file is accessible. */
1240 if (!::stat(m_reference.path.c_str(), &s))
1243 m_event((iPlayableService*)this, evStopped);
1247 RESULT eDVBServicePlay::setTarget(int target)
1249 m_is_primary = !target;
1253 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1255 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1259 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1261 /* note: we check for timeshift to be enabled,
1262 not neccessary active. if you pause when timeshift
1263 is not active, you should activate it when unpausing */
1264 if ((!m_is_pvr) && (!m_timeshift_enabled))
1274 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1277 return m_decoder->setSlowMotion(ratio);
1282 RESULT eDVBServicePlay::setFastForward(int ratio)
1284 int skipmode, ffratio;
1290 } else if (ratio > 0)
1298 } else // if (ratio < 0)
1304 if (m_skipmode != skipmode)
1306 eDebug("setting cue skipmode to %d", skipmode);
1308 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1311 m_skipmode = skipmode;
1316 return m_decoder->setFastForward(ffratio);
1319 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1321 if (m_is_pvr || m_timeshift_enabled)
1331 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1332 RESULT eDVBServicePlay::getLength(pts_t &len)
1334 ePtr<iDVBPVRChannel> pvr_channel;
1336 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1339 return pvr_channel->getLength(len);
1342 RESULT eDVBServicePlay::pause()
1344 if (!m_is_paused && m_decoder)
1347 return m_decoder->freeze(0);
1352 RESULT eDVBServicePlay::unpause()
1354 if (m_is_paused && m_decoder)
1357 return m_decoder->unfreeze();
1362 RESULT eDVBServicePlay::seekTo(pts_t to)
1364 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1366 if (!m_decode_demux)
1369 ePtr<iDVBPVRChannel> pvr_channel;
1371 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1377 m_cue->seekTo(0, to);
1378 m_dvb_subtitle_pages.clear();
1379 m_subtitle_pages.clear();
1384 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1386 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1388 if (!m_decode_demux)
1391 ePtr<iDVBPVRChannel> pvr_channel;
1393 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1398 /* HACK until we have skip-AP api */
1399 if ((to > 0) && (to < 100))
1407 m_cue->seekTo(mode, to);
1408 m_dvb_subtitle_pages.clear();
1409 m_subtitle_pages.clear();
1413 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1415 ePtr<iDVBPVRChannel> pvr_channel;
1417 if (!m_decode_demux)
1420 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1425 /* if there is a decoder, use audio or video PTS */
1428 r = m_decoder->getPTS(0, pos);
1434 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1437 RESULT eDVBServicePlay::setTrickmode(int trick)
1440 m_decoder->setTrickmode(trick);
1444 RESULT eDVBServicePlay::isCurrentlySeekable()
1446 return m_is_pvr || m_timeshift_active;
1449 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1455 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1461 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1467 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1473 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1479 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1482 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1483 (m_timeshift_enabled || !m_is_pvr))
1485 if (!m_timeshift_enabled)
1487 /* we need enough diskspace */
1489 if (statfs(TSPATH "/.", &fs) < 0)
1491 eDebug("statfs failed!");
1495 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1497 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1507 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1518 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1524 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1530 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1536 RESULT eDVBServicePlay::getName(std::string &name)
1540 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1541 return i->getName(m_reference, name);
1545 m_dvb_service->getName(m_reference, name);
1549 else if (!m_reference.name.empty())
1550 eStaticServiceDVBInformation().getName(m_reference, name);
1552 name = "DVB service";
1556 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1558 return m_event_handler.getEvent(evt, nownext);
1561 int eDVBServicePlay::getInfo(int w)
1563 eDVBServicePMTHandler::program program;
1566 return resIsPyObject;
1568 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1570 int no_program_info = 0;
1572 if (h.getProgramInfo(program))
1573 no_program_info = 1;
1577 #if HAVE_DVB_API_VERSION >= 3
1579 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1580 return m_videoEventData.height;
1583 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1584 return m_videoEventData.width;
1587 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1590 #if HAVE_DVB_API_VERSION >= 3
1591 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1592 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1595 #warning "FIXMEE implement sAspect for old DVB API"
1597 if (no_program_info)
1599 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1601 ePtr<eServiceEvent> evt;
1602 if (!m_event_handler.getEvent(evt, 0))
1604 ePtr<eComponentData> data;
1605 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1607 if ( data->getStreamContent() == 1 )
1609 switch(data->getComponentType())
1612 case 1: // 4:3 SD PAL
1614 case 3: // 16:9 SD PAL
1615 case 4: // > 16:9 PAL
1616 case 5: // 4:3 SD NTSC
1618 case 7: // 16:9 SD NTSC
1619 case 8: // > 16:9 NTSC
1622 case 9: // 4:3 HD PAL
1624 case 0xB: // 16:9 HD PAL
1625 case 0xC: // > 16:9 HD PAL
1626 case 0xD: // 4:3 HD NTSC
1628 case 0xF: // 16:9 HD NTSC
1629 case 0x10: // > 16:9 HD PAL
1630 return data->getComponentType();
1637 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1638 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1639 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1640 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1641 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1642 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1643 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1644 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1645 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1646 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1647 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1648 case sProvider: if (!m_dvb_service) return -1; return -2;
1649 case sServiceref: return resIsString;
1650 case sDVBState: return m_tune_state;
1656 std::string eDVBServicePlay::getInfoString(int w)
1661 if (!m_dvb_service) return "";
1662 return m_dvb_service->m_provider_name;
1664 return m_reference.toString();
1668 return iServiceInformation::getInfoString(w);
1671 PyObject *eDVBServicePlay::getInfoObject(int w)
1676 return m_service_handler.getCaIds();
1677 case sTransponderData:
1678 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1682 return iServiceInformation::getInfoObject(w);
1685 int eDVBServicePlay::getNumberOfTracks()
1687 eDVBServicePMTHandler::program program;
1688 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1689 if (h.getProgramInfo(program))
1691 return program.audioStreams.size();
1694 int eDVBServicePlay::getCurrentTrack()
1696 eDVBServicePMTHandler::program program;
1697 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1698 if (h.getProgramInfo(program))
1701 int max = program.audioStreams.size();
1704 for (i = 0; i < max; ++i)
1705 if (program.audioStreams[i].pid == m_current_audio_pid)
1711 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1713 int ret = selectAudioStream(i);
1715 if (m_decoder->start())
1721 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1723 eDVBServicePMTHandler::program program;
1724 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1726 if (h.getProgramInfo(program))
1729 if (i >= program.audioStreams.size())
1732 info.m_pid = program.audioStreams[i].pid;
1734 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1735 info.m_description = "MPEG";
1736 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1737 info.m_description = "AC3";
1738 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1739 info.m_description = "AAC";
1740 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1741 info.m_description = "DTS";
1743 info.m_description = "???";
1745 if (program.audioStreams[i].component_tag != -1)
1747 ePtr<eServiceEvent> evt;
1748 if (!m_event_handler.getEvent(evt, 0))
1750 ePtr<eComponentData> data;
1751 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1752 info.m_language = data->getText();
1756 if (info.m_language.empty())
1757 info.m_language = program.audioStreams[i].language_code;
1762 int eDVBServicePlay::selectAudioStream(int i)
1764 eDVBServicePMTHandler::program program;
1765 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1767 if (h.getProgramInfo(program))
1770 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1778 stream = program.defaultAudioStream;
1780 int apid = -1, apidtype = -1;
1782 if (((unsigned int)stream) < program.audioStreams.size())
1784 apid = program.audioStreams[stream].pid;
1785 apidtype = program.audioStreams[stream].type;
1788 m_current_audio_pid = apid;
1790 if (m_decoder->setAudioPID(apid, apidtype))
1792 eDebug("set audio pid failed");
1796 /* 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 */
1797 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1800 ePtr<iDVBDemux> data_demux;
1801 if (!h.getDataDemux(data_demux))
1803 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1804 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1808 /* if we decided that we need one, update the pid */
1810 m_rds_decoder->start(apid);
1812 /* store new pid as default only when:
1813 a.) we have an entry in the service db for the current service,
1814 b.) we are not playing back something,
1815 c.) we are not selecting the default entry. (we wouldn't change
1816 anything in the best case, or destroy the default setting in
1817 case the real default is not yet available.)
1819 if (m_dvb_service && !m_is_pvr && ((i != -1)
1820 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1822 if (apidtype == eDVBAudio::aMPEG)
1824 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1825 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1829 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1830 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1834 h.resetCachedProgram();
1839 int eDVBServicePlay::getCurrentChannel()
1841 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1844 RESULT eDVBServicePlay::selectChannel(int i)
1846 if (i < LEFT || i > RIGHT || i == STEREO)
1849 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1851 m_decoder->setAudioChannel(i);
1855 std::string eDVBServicePlay::getText(int x)
1861 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1863 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1868 void eDVBServicePlay::rdsDecoderEvent(int what)
1872 case eDVBRdsDecoder::RadioTextChanged:
1873 m_event((iPlayableService*)this, evUpdatedRadioText);
1875 case eDVBRdsDecoder::RtpTextChanged:
1876 m_event((iPlayableService*)this, evUpdatedRtpText);
1878 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1879 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1881 case eDVBRdsDecoder::RecvRassSlidePic:
1882 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1887 void eDVBServicePlay::showRassSlidePicture()
1893 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1894 if (rass_slide_pic.length())
1895 m_decoder->showSinglePic(rass_slide_pic.c_str());
1897 eDebug("empty filename for rass slide picture received!!");
1900 eDebug("no MPEG Decoder to show iframes avail");
1903 eDebug("showRassSlidePicture called.. but not decoder");
1906 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1912 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1913 if (rass_interactive_pic.length())
1914 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1916 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1919 eDebug("no MPEG Decoder to show iframes avail");
1922 eDebug("showRassInteractivePic called.. but not decoder");
1925 ePyObject eDVBServicePlay::getRassInteractiveMask()
1928 return m_rds_decoder->getRassPictureMask();
1932 int eDVBServiceBase::getFrontendInfo(int w)
1934 eUsePtr<iDVBChannel> channel;
1935 if(m_service_handler.getChannel(channel))
1937 ePtr<iDVBFrontend> fe;
1938 if(channel->getFrontend(fe))
1940 return fe->readFrontendData(w);
1943 PyObject *eDVBServiceBase::getFrontendData()
1945 ePyObject ret = PyDict_New();
1948 eUsePtr<iDVBChannel> channel;
1949 if(!m_service_handler.getChannel(channel))
1951 ePtr<iDVBFrontend> fe;
1952 if(!channel->getFrontend(fe))
1953 fe->getFrontendData(ret);
1961 PyObject *eDVBServiceBase::getFrontendStatus()
1963 ePyObject ret = PyDict_New();
1966 eUsePtr<iDVBChannel> channel;
1967 if(!m_service_handler.getChannel(channel))
1969 ePtr<iDVBFrontend> fe;
1970 if(!channel->getFrontend(fe))
1971 fe->getFrontendStatus(ret);
1979 PyObject *eDVBServiceBase::getTransponderData(bool original)
1981 ePyObject ret = PyDict_New();
1984 eUsePtr<iDVBChannel> channel;
1985 if(!m_service_handler.getChannel(channel))
1987 ePtr<iDVBFrontend> fe;
1988 if(!channel->getFrontend(fe))
1990 fe->getTransponderData(ret, original);
1991 ePtr<iDVBFrontendParameters> feparm;
1992 channel->getCurrentFrontendParameters(feparm);
1995 eDVBFrontendParametersSatellite osat;
1996 if (!feparm->getDVBS(osat))
1998 void PutToDict(ePyObject &, const char*, long);
1999 void PutToDict(ePyObject &, const char*, const char*);
2000 PutToDict(ret, "orbital_position", osat.orbital_position);
2001 const char *tmp = "UNKNOWN";
2002 switch(osat.polarisation)
2004 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2005 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2006 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2007 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2010 PutToDict(ret, "polarization", tmp);
2021 PyObject *eDVBServiceBase::getAll(bool original)
2023 ePyObject ret = getTransponderData(original);
2026 eUsePtr<iDVBChannel> channel;
2027 if(!m_service_handler.getChannel(channel))
2029 ePtr<iDVBFrontend> fe;
2030 if(!channel->getFrontend(fe))
2032 fe->getFrontendData(ret);
2033 fe->getFrontendStatus(ret);
2040 int eDVBServicePlay::getNumberOfSubservices()
2042 ePtr<eServiceEvent> evt;
2043 if (!m_event_handler.getEvent(evt, 0))
2044 return evt->getNumOfLinkageServices();
2048 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2050 ePtr<eServiceEvent> evt;
2051 if (!m_event_handler.getEvent(evt, 0))
2053 if (!evt->getLinkageService(sub, m_reference, n))
2056 sub.type=eServiceReference::idInvalid;
2060 RESULT eDVBServicePlay::startTimeshift()
2062 ePtr<iDVBDemux> demux;
2064 eDebug("Start timeshift!");
2066 if (m_timeshift_enabled)
2069 /* start recording with the data demux. */
2070 if (m_service_handler.getDataDemux(demux))
2073 demux->createTSRecorder(m_record);
2077 char templ[]=TSPATH "/timeshift.XXXXXX";
2078 m_timeshift_fd = mkstemp(templ);
2079 m_timeshift_file = templ;
2081 eDebug("recording to %s", templ);
2083 if (m_timeshift_fd < 0)
2089 m_record->setTargetFD(m_timeshift_fd);
2091 m_timeshift_enabled = 1;
2093 updateTimeshiftPids();
2099 RESULT eDVBServicePlay::stopTimeshift()
2101 if (!m_timeshift_enabled)
2106 m_timeshift_enabled = 0;
2111 close(m_timeshift_fd);
2112 eDebug("remove timeshift file");
2113 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2118 int eDVBServicePlay::isTimeshiftActive()
2120 return m_timeshift_enabled && m_timeshift_active;
2123 RESULT eDVBServicePlay::activateTimeshift()
2125 if (!m_timeshift_enabled)
2128 if (!m_timeshift_active)
2130 switchToTimeshift();
2137 PyObject *eDVBServicePlay::getCutList()
2139 ePyObject list = PyList_New(0);
2141 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2143 ePyObject tuple = PyTuple_New(2);
2144 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2145 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2146 PyList_Append(list, tuple);
2153 void eDVBServicePlay::setCutList(ePyObject list)
2155 if (!PyList_Check(list))
2157 int size = PyList_Size(list);
2160 m_cue_entries.clear();
2162 for (i=0; i<size; ++i)
2164 ePyObject tuple = PyList_GET_ITEM(list, i);
2165 if (!PyTuple_Check(tuple))
2167 eDebug("non-tuple in cutlist");
2170 if (PyTuple_Size(tuple) != 2)
2172 eDebug("cutlist entries need to be a 2-tuple");
2175 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2176 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2178 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2181 pts_t pts = PyLong_AsLongLong(ppts);
2182 int type = PyInt_AsLong(ptype);
2183 m_cue_entries.insert(cueEntry(pts, type));
2184 eDebug("adding %08llx, %d", pts, type);
2186 m_cuesheet_changed = 1;
2188 cutlistToCuesheet();
2189 m_event((iPlayableService*)this, evCuesheetChanged);
2192 void eDVBServicePlay::setCutListEnable(int enable)
2194 m_cutlist_enabled = enable;
2195 cutlistToCuesheet();
2198 void eDVBServicePlay::updateTimeshiftPids()
2203 eDVBServicePMTHandler::program program;
2204 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2206 if (h.getProgramInfo(program))
2210 std::set<int> pids_to_record;
2211 pids_to_record.insert(0); // PAT
2212 if (program.pmtPid != -1)
2213 pids_to_record.insert(program.pmtPid); // PMT
2215 if (program.textPid != -1)
2216 pids_to_record.insert(program.textPid); // Videotext
2218 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2219 i(program.videoStreams.begin());
2220 i != program.videoStreams.end(); ++i)
2221 pids_to_record.insert(i->pid);
2223 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2224 i(program.audioStreams.begin());
2225 i != program.audioStreams.end(); ++i)
2226 pids_to_record.insert(i->pid);
2228 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2229 i(program.subtitleStreams.begin());
2230 i != program.subtitleStreams.end(); ++i)
2231 pids_to_record.insert(i->pid);
2233 std::set<int> new_pids, obsolete_pids;
2235 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2236 m_pids_active.begin(), m_pids_active.end(),
2237 std::inserter(new_pids, new_pids.begin()));
2239 std::set_difference(
2240 m_pids_active.begin(), m_pids_active.end(),
2241 pids_to_record.begin(), pids_to_record.end(),
2242 std::inserter(new_pids, new_pids.begin())
2245 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2246 m_record->addPID(*i);
2248 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2249 m_record->removePID(*i);
2253 void eDVBServicePlay::switchToLive()
2255 if (!m_timeshift_active)
2261 m_teletext_parser = 0;
2263 m_subtitle_parser = 0;
2264 m_new_dvb_subtitle_page_connection = 0;
2265 m_new_subtitle_page_connection = 0;
2266 m_rds_decoder_event_connection = 0;
2267 m_video_event_connection = 0;
2269 /* free the timeshift service handler, we need the resources */
2270 m_service_handler_timeshift.free();
2271 m_timeshift_active = 0;
2273 m_event((iPlayableService*)this, evSeekableStatusChanged);
2278 void eDVBServicePlay::switchToTimeshift()
2280 if (m_timeshift_active)
2285 m_teletext_parser = 0;
2287 m_subtitle_parser = 0;
2288 m_new_subtitle_page_connection = 0;
2289 m_new_dvb_subtitle_page_connection = 0;
2290 m_rds_decoder_event_connection = 0;
2291 m_video_event_connection = 0;
2293 m_timeshift_active = 1;
2295 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2296 r.path = m_timeshift_file;
2298 m_cue = new eCueSheet();
2299 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2301 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2303 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2305 m_event((iPlayableService*)this, evSeekableStatusChanged);
2308 void eDVBServicePlay::updateDecoder()
2310 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2312 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2314 eDVBServicePMTHandler::program program;
2315 if (h.getProgramInfo(program))
2316 eDebug("getting program info failed.");
2319 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2320 if (!program.videoStreams.empty())
2322 eDebugNoNewLine(" (");
2323 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2324 i(program.videoStreams.begin());
2325 i != program.videoStreams.end(); ++i)
2332 if (i != program.videoStreams.begin())
2333 eDebugNoNewLine(", ");
2334 eDebugNoNewLine("%04x", i->pid);
2336 eDebugNoNewLine(")");
2338 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2339 if (!program.audioStreams.empty())
2341 eDebugNoNewLine(" (");
2342 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2343 i(program.audioStreams.begin());
2344 i != program.audioStreams.end(); ++i)
2346 if (i != program.audioStreams.begin())
2347 eDebugNoNewLine(", ");
2348 eDebugNoNewLine("%04x", i->pid);
2350 eDebugNoNewLine(")");
2352 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2353 pcrpid = program.pcrPid;
2354 eDebug(", and the text pid is %04x", program.textPid);
2355 tpid = program.textPid;
2360 h.getDecodeDemux(m_decode_demux);
2363 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2365 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2366 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2367 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2368 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2369 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2372 m_teletext_parser = 0;
2373 m_subtitle_parser = 0;
2377 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2384 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2385 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2386 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2388 else // subservice or recording
2390 eServiceReferenceDVB ref;
2391 m_service_handler.getServiceReference(ref);
2392 eServiceReferenceDVB parent = ref.getParentServiceReference();
2397 ePtr<eDVBResourceManager> res_mgr;
2398 if (!eDVBResourceManager::getInstance(res_mgr))
2400 ePtr<iDVBChannelList> db;
2401 if (!res_mgr->getChannelList(db))
2403 ePtr<eDVBService> origService;
2404 if (!db->getService(parent, origService))
2406 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2407 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2413 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2414 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2416 m_decoder->setVideoPID(vpid, vpidtype);
2417 selectAudioStream();
2419 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2420 m_decoder->setSyncPCR(pcrpid);
2422 m_decoder->setSyncPCR(-1);
2424 m_decoder->setTextPID(tpid);
2426 m_teletext_parser->start(program.textPid);
2429 m_decoder->setTrickmode(1);
2432 m_decoder->preroll();
2436 if (vpid > 0 && vpid < 0x2000)
2440 std::string radio_pic;
2441 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2442 m_decoder->setRadioPic(radio_pic);
2445 m_decoder->setAudioChannel(achannel);
2447 /* don't worry about non-existing services, nor pvr services */
2448 if (m_dvb_service && !m_is_pvr)
2450 /* (audio pid will be set in selectAudioTrack */
2451 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2452 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2453 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2454 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2457 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2460 void eDVBServicePlay::loadCuesheet()
2462 std::string filename = m_reference.path + ".cuts";
2464 m_cue_entries.clear();
2466 FILE *f = fopen(filename.c_str(), "rb");
2470 eDebug("loading cuts..");
2473 unsigned long long where;
2476 if (!fread(&where, sizeof(where), 1, f))
2478 if (!fread(&what, sizeof(what), 1, f))
2481 #if BYTE_ORDER == LITTLE_ENDIAN
2482 where = bswap_64(where);
2489 m_cue_entries.insert(cueEntry(where, what));
2492 eDebug("%d entries", m_cue_entries.size());
2494 eDebug("cutfile not found!");
2496 m_cuesheet_changed = 0;
2497 cutlistToCuesheet();
2498 m_event((iPlayableService*)this, evCuesheetChanged);
2501 void eDVBServicePlay::saveCuesheet()
2503 std::string filename = m_reference.path + ".cuts";
2505 FILE *f = fopen(filename.c_str(), "wb");
2509 unsigned long long where;
2512 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2514 #if BYTE_ORDER == BIG_ENDIAN
2517 where = bswap_64(i->where);
2519 what = htonl(i->what);
2520 fwrite(&where, sizeof(where), 1, f);
2521 fwrite(&what, sizeof(what), 1, f);
2527 m_cuesheet_changed = 0;
2530 void eDVBServicePlay::cutlistToCuesheet()
2534 eDebug("no cue sheet");
2539 if (!m_cutlist_enabled)
2541 m_cue->commitSpans();
2542 eDebug("cutlists were disabled");
2546 pts_t in = 0, out = 0, length = 0;
2550 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2554 if (i == m_cue_entries.end())
2557 if (i->what == 0) /* in */
2561 } else if (i->what == 1) /* out */
2563 else /* mark (2) or last play position (3) */
2580 m_cue->addSourceSpan(in, out);
2584 if (i == m_cue_entries.end())
2587 m_cue->commitSpans();
2590 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2592 if (m_subtitle_widget)
2593 disableSubtitles(parent);
2596 int tuplesize = PyTuple_Size(tuple);
2599 if (!PyTuple_Check(tuple))
2605 entry = PyTuple_GET_ITEM(tuple, 0);
2607 if (!PyInt_Check(entry))
2610 type = PyInt_AsLong(entry);
2612 if (type == 1) // teletext subtitles
2614 int page, magazine, pid;
2618 if (!m_teletext_parser)
2620 eDebug("enable teletext subtitles.. no parser !!!");
2624 entry = PyTuple_GET_ITEM(tuple, 1);
2625 if (!PyInt_Check(entry))
2627 pid = PyInt_AsLong(entry);
2629 entry = PyTuple_GET_ITEM(tuple, 2);
2630 if (!PyInt_Check(entry))
2632 page = PyInt_AsLong(entry);
2634 entry = PyTuple_GET_ITEM(tuple, 3);
2635 if (!PyInt_Check(entry))
2637 magazine = PyInt_AsLong(entry);
2639 m_subtitle_widget = new eSubtitleWidget(parent);
2640 m_subtitle_widget->resize(parent->size()); /* full size */
2641 m_teletext_parser->setPageAndMagazine(page, magazine);
2643 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2647 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2648 if (!m_subtitle_parser)
2650 eDebug("enable dvb subtitles.. no parser !!!");
2656 entry = PyTuple_GET_ITEM(tuple, 1);
2657 if (!PyInt_Check(entry))
2659 pid = PyInt_AsLong(entry);
2661 entry = PyTuple_GET_ITEM(tuple, 2);
2662 if (!PyInt_Check(entry))
2664 composition_page_id = PyInt_AsLong(entry);
2666 entry = PyTuple_GET_ITEM(tuple, 3);
2667 if (!PyInt_Check(entry))
2669 ancillary_page_id = PyInt_AsLong(entry);
2671 m_subtitle_widget = new eSubtitleWidget(parent);
2672 m_subtitle_widget->resize(parent->size()); /* full size */
2673 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2675 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2681 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2682 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2683 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2687 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2689 delete m_subtitle_widget;
2690 m_subtitle_widget = 0;
2691 if (m_subtitle_parser)
2693 m_subtitle_parser->stop();
2694 m_dvb_subtitle_pages.clear();
2696 if (m_teletext_parser)
2698 m_teletext_parser->setPageAndMagazine(-1, -1);
2699 m_subtitle_pages.clear();
2702 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2706 PyObject *eDVBServicePlay::getCachedSubtitle()
2710 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2713 unsigned int data = (unsigned int)tmp;
2714 int pid = (data&0xFFFF0000)>>16;
2715 ePyObject tuple = PyTuple_New(4);
2716 eDVBServicePMTHandler::program program;
2717 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2718 if (!h.getProgramInfo(program))
2720 if (program.textPid==pid) // teletext
2721 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2723 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2724 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2725 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2726 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2734 PyObject *eDVBServicePlay::getSubtitleList()
2736 if (!m_teletext_parser)
2739 ePyObject l = PyList_New(0);
2740 std::set<int> added_ttx_pages;
2742 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2743 m_teletext_parser->m_found_subtitle_pages;
2745 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2746 eDVBServicePMTHandler::program program;
2747 if (h.getProgramInfo(program))
2748 eDebug("getting program info failed.");
2751 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2752 it != program.subtitleStreams.end(); ++it)
2754 switch(it->subtitling_type)
2756 case 0x01: // ebu teletext subtitles
2758 int page_number = it->teletext_page_number & 0xFF;
2759 int magazine_number = it->teletext_magazine_number & 7;
2760 int hash = magazine_number << 8 | page_number;
2761 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2763 ePyObject tuple = PyTuple_New(5);
2764 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2765 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2766 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2767 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2768 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2769 PyList_Append(l, tuple);
2771 added_ttx_pages.insert(hash);
2776 case 0x20 ... 0x23: // dvb subtitles
2778 ePyObject tuple = PyTuple_New(5);
2779 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2780 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2781 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2782 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2783 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2784 PyList_Insert(l, 0, tuple);
2792 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2793 it != subs.end(); ++it)
2795 int page_number = it->teletext_page_number & 0xFF;
2796 int magazine_number = it->teletext_magazine_number & 7;
2797 int hash = magazine_number << 8 | page_number;
2798 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2800 ePyObject tuple = PyTuple_New(5);
2801 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2802 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2803 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2804 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2805 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2806 PyList_Append(l, tuple);
2814 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2816 if (m_subtitle_widget)
2820 m_decoder->getPTS(0, pos);
2821 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2822 m_subtitle_pages.push_back(page);
2823 checkSubtitleTiming();
2827 void eDVBServicePlay::checkSubtitleTiming()
2829 eDebug("checkSubtitleTiming");
2830 if (!m_subtitle_widget)
2834 enum { TELETEXT, DVB } type;
2835 eDVBTeletextSubtitlePage page;
2836 eDVBSubtitlePage dvb_page;
2838 if (!m_subtitle_pages.empty())
2840 page = m_subtitle_pages.front();
2842 show_time = page.m_pts;
2844 else if (!m_dvb_subtitle_pages.empty())
2846 dvb_page = m_dvb_subtitle_pages.front();
2848 show_time = dvb_page.m_show_time;
2856 m_decoder->getPTS(0, pos);
2858 eDebug("%lld %lld", pos, show_time);
2859 int diff = show_time - pos;
2862 eDebug("[late (%d ms)]", -diff / 90);
2865 // if (diff > 900000)
2867 // eDebug("[invalid]");
2873 if (type == TELETEXT)
2875 eDebug("display teletext subtitle page %lld", show_time);
2876 m_subtitle_widget->setPage(page);
2877 m_subtitle_pages.pop_front();
2881 eDebug("display dvb subtitle Page %lld", show_time);
2882 m_subtitle_widget->setPage(dvb_page);
2883 m_dvb_subtitle_pages.pop_front();
2887 eDebug("start subtitle delay %d", diff / 90);
2888 m_subtitle_sync_timer.start(diff / 90, 1);
2894 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2896 if (m_subtitle_widget)
2900 m_decoder->getPTS(0, pos);
2901 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2902 m_dvb_subtitle_pages.push_back(p);
2903 checkSubtitleTiming();
2907 int eDVBServicePlay::getAC3Delay()
2910 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2912 return m_decoder->getAC3Delay();
2917 int eDVBServicePlay::getPCMDelay()
2920 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2922 return m_decoder->getPCMDelay();
2927 void eDVBServicePlay::setAC3Delay(int delay)
2930 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2932 m_decoder->setAC3Delay(delay);
2935 void eDVBServicePlay::setPCMDelay(int delay)
2938 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2940 m_decoder->setPCMDelay(delay);
2943 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2945 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2946 m_event((iPlayableService*)this, evVideoSizeChanged);
2949 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2955 PyObject *eDVBServicePlay::getStreamingData()
2957 eDVBServicePMTHandler::program program;
2958 if (m_service_handler.getProgramInfo(program))
2964 PyObject *r = program.createPythonObject();
2965 ePtr<iDVBDemux> demux;
2966 if (!m_service_handler.getDataDemux(demux))
2969 demux->getCADemuxID(demux_id);
2971 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
2978 DEFINE_REF(eDVBServicePlay)
2980 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2984 case iServiceInformation::sTransponderData:
2985 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2989 return iStaticServiceInformation::getInfoObject(ref, w);
2992 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");