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::seekChapter(int chapter)
1451 /* seekChapter N/I. */
1455 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1461 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1467 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1473 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1479 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1485 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1488 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1489 (m_timeshift_enabled || !m_is_pvr))
1491 if (!m_timeshift_enabled)
1493 /* we need enough diskspace */
1495 if (statfs(TSPATH "/.", &fs) < 0)
1497 eDebug("statfs failed!");
1501 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1503 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1513 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1524 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1530 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1536 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1542 RESULT eDVBServicePlay::getName(std::string &name)
1546 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1547 return i->getName(m_reference, name);
1551 m_dvb_service->getName(m_reference, name);
1555 else if (!m_reference.name.empty())
1556 eStaticServiceDVBInformation().getName(m_reference, name);
1558 name = "DVB service";
1562 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1564 return m_event_handler.getEvent(evt, nownext);
1567 int eDVBServicePlay::getInfo(int w)
1569 eDVBServicePMTHandler::program program;
1572 return resIsPyObject;
1574 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1576 int no_program_info = 0;
1578 if (h.getProgramInfo(program))
1579 no_program_info = 1;
1583 #if HAVE_DVB_API_VERSION >= 3
1585 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1586 return m_videoEventData.height;
1589 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1590 return m_videoEventData.width;
1593 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1596 #if HAVE_DVB_API_VERSION >= 3
1597 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1598 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1601 #warning "FIXMEE implement sAspect for old DVB API"
1603 if (no_program_info)
1605 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1607 ePtr<eServiceEvent> evt;
1608 if (!m_event_handler.getEvent(evt, 0))
1610 ePtr<eComponentData> data;
1611 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1613 if ( data->getStreamContent() == 1 )
1615 switch(data->getComponentType())
1618 case 1: // 4:3 SD PAL
1620 case 3: // 16:9 SD PAL
1621 case 4: // > 16:9 PAL
1622 case 5: // 4:3 SD NTSC
1624 case 7: // 16:9 SD NTSC
1625 case 8: // > 16:9 NTSC
1628 case 9: // 4:3 HD PAL
1630 case 0xB: // 16:9 HD PAL
1631 case 0xC: // > 16:9 HD PAL
1632 case 0xD: // 4:3 HD NTSC
1634 case 0xF: // 16:9 HD NTSC
1635 case 0x10: // > 16:9 HD PAL
1636 return data->getComponentType();
1643 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1644 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1645 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1646 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1647 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1648 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1649 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1650 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1651 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1652 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1653 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1654 case sProvider: if (!m_dvb_service) return -1; return -2;
1655 case sServiceref: return resIsString;
1656 case sDVBState: return m_tune_state;
1662 std::string eDVBServicePlay::getInfoString(int w)
1667 if (!m_dvb_service) return "";
1668 return m_dvb_service->m_provider_name;
1670 return m_reference.toString();
1674 return iServiceInformation::getInfoString(w);
1677 PyObject *eDVBServicePlay::getInfoObject(int w)
1682 return m_service_handler.getCaIds();
1683 case sTransponderData:
1684 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1688 return iServiceInformation::getInfoObject(w);
1691 int eDVBServicePlay::getNumberOfTracks()
1693 eDVBServicePMTHandler::program program;
1694 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1695 if (h.getProgramInfo(program))
1697 return program.audioStreams.size();
1700 int eDVBServicePlay::getCurrentTrack()
1702 eDVBServicePMTHandler::program program;
1703 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1704 if (h.getProgramInfo(program))
1707 int max = program.audioStreams.size();
1710 for (i = 0; i < max; ++i)
1711 if (program.audioStreams[i].pid == m_current_audio_pid)
1717 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1719 int ret = selectAudioStream(i);
1721 if (m_decoder->start())
1727 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1729 eDVBServicePMTHandler::program program;
1730 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1732 if (h.getProgramInfo(program))
1735 if (i >= program.audioStreams.size())
1738 info.m_pid = program.audioStreams[i].pid;
1740 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1741 info.m_description = "MPEG";
1742 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1743 info.m_description = "AC3";
1744 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1745 info.m_description = "AAC";
1746 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1747 info.m_description = "DTS";
1749 info.m_description = "???";
1751 if (program.audioStreams[i].component_tag != -1)
1753 ePtr<eServiceEvent> evt;
1754 if (!m_event_handler.getEvent(evt, 0))
1756 ePtr<eComponentData> data;
1757 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1758 info.m_language = data->getText();
1762 if (info.m_language.empty())
1763 info.m_language = program.audioStreams[i].language_code;
1768 int eDVBServicePlay::selectAudioStream(int i)
1770 eDVBServicePMTHandler::program program;
1771 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1773 if (h.getProgramInfo(program))
1776 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1784 stream = program.defaultAudioStream;
1786 int apid = -1, apidtype = -1;
1788 if (((unsigned int)stream) < program.audioStreams.size())
1790 apid = program.audioStreams[stream].pid;
1791 apidtype = program.audioStreams[stream].type;
1794 m_current_audio_pid = apid;
1796 if (m_decoder->setAudioPID(apid, apidtype))
1798 eDebug("set audio pid failed");
1802 /* 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 */
1803 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1806 ePtr<iDVBDemux> data_demux;
1807 if (!h.getDataDemux(data_demux))
1809 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1810 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1814 /* if we decided that we need one, update the pid */
1816 m_rds_decoder->start(apid);
1818 /* store new pid as default only when:
1819 a.) we have an entry in the service db for the current service,
1820 b.) we are not playing back something,
1821 c.) we are not selecting the default entry. (we wouldn't change
1822 anything in the best case, or destroy the default setting in
1823 case the real default is not yet available.)
1825 if (m_dvb_service && !m_is_pvr && ((i != -1)
1826 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1828 if (apidtype == eDVBAudio::aMPEG)
1830 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1831 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1835 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1836 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1840 h.resetCachedProgram();
1845 int eDVBServicePlay::getCurrentChannel()
1847 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1850 RESULT eDVBServicePlay::selectChannel(int i)
1852 if (i < LEFT || i > RIGHT || i == STEREO)
1855 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1857 m_decoder->setAudioChannel(i);
1861 std::string eDVBServicePlay::getText(int x)
1867 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1869 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1874 void eDVBServicePlay::rdsDecoderEvent(int what)
1878 case eDVBRdsDecoder::RadioTextChanged:
1879 m_event((iPlayableService*)this, evUpdatedRadioText);
1881 case eDVBRdsDecoder::RtpTextChanged:
1882 m_event((iPlayableService*)this, evUpdatedRtpText);
1884 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1885 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1887 case eDVBRdsDecoder::RecvRassSlidePic:
1888 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1893 void eDVBServicePlay::showRassSlidePicture()
1899 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1900 if (rass_slide_pic.length())
1901 m_decoder->showSinglePic(rass_slide_pic.c_str());
1903 eDebug("empty filename for rass slide picture received!!");
1906 eDebug("no MPEG Decoder to show iframes avail");
1909 eDebug("showRassSlidePicture called.. but not decoder");
1912 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1918 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1919 if (rass_interactive_pic.length())
1920 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1922 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1925 eDebug("no MPEG Decoder to show iframes avail");
1928 eDebug("showRassInteractivePic called.. but not decoder");
1931 ePyObject eDVBServicePlay::getRassInteractiveMask()
1934 return m_rds_decoder->getRassPictureMask();
1938 int eDVBServiceBase::getFrontendInfo(int w)
1940 eUsePtr<iDVBChannel> channel;
1941 if(m_service_handler.getChannel(channel))
1943 ePtr<iDVBFrontend> fe;
1944 if(channel->getFrontend(fe))
1946 return fe->readFrontendData(w);
1949 PyObject *eDVBServiceBase::getFrontendData()
1951 ePyObject ret = PyDict_New();
1954 eUsePtr<iDVBChannel> channel;
1955 if(!m_service_handler.getChannel(channel))
1957 ePtr<iDVBFrontend> fe;
1958 if(!channel->getFrontend(fe))
1959 fe->getFrontendData(ret);
1967 PyObject *eDVBServiceBase::getFrontendStatus()
1969 ePyObject ret = PyDict_New();
1972 eUsePtr<iDVBChannel> channel;
1973 if(!m_service_handler.getChannel(channel))
1975 ePtr<iDVBFrontend> fe;
1976 if(!channel->getFrontend(fe))
1977 fe->getFrontendStatus(ret);
1985 PyObject *eDVBServiceBase::getTransponderData(bool original)
1987 ePyObject ret = PyDict_New();
1990 eUsePtr<iDVBChannel> channel;
1991 if(!m_service_handler.getChannel(channel))
1993 ePtr<iDVBFrontend> fe;
1994 if(!channel->getFrontend(fe))
1996 fe->getTransponderData(ret, original);
1997 ePtr<iDVBFrontendParameters> feparm;
1998 channel->getCurrentFrontendParameters(feparm);
2001 eDVBFrontendParametersSatellite osat;
2002 if (!feparm->getDVBS(osat))
2004 void PutToDict(ePyObject &, const char*, long);
2005 void PutToDict(ePyObject &, const char*, const char*);
2006 PutToDict(ret, "orbital_position", osat.orbital_position);
2007 const char *tmp = "UNKNOWN";
2008 switch(osat.polarisation)
2010 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2011 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2012 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2013 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2016 PutToDict(ret, "polarization", tmp);
2027 PyObject *eDVBServiceBase::getAll(bool original)
2029 ePyObject ret = getTransponderData(original);
2032 eUsePtr<iDVBChannel> channel;
2033 if(!m_service_handler.getChannel(channel))
2035 ePtr<iDVBFrontend> fe;
2036 if(!channel->getFrontend(fe))
2038 fe->getFrontendData(ret);
2039 fe->getFrontendStatus(ret);
2046 int eDVBServicePlay::getNumberOfSubservices()
2048 ePtr<eServiceEvent> evt;
2049 if (!m_event_handler.getEvent(evt, 0))
2050 return evt->getNumOfLinkageServices();
2054 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2056 ePtr<eServiceEvent> evt;
2057 if (!m_event_handler.getEvent(evt, 0))
2059 if (!evt->getLinkageService(sub, m_reference, n))
2062 sub.type=eServiceReference::idInvalid;
2066 RESULT eDVBServicePlay::startTimeshift()
2068 ePtr<iDVBDemux> demux;
2070 eDebug("Start timeshift!");
2072 if (m_timeshift_enabled)
2075 /* start recording with the data demux. */
2076 if (m_service_handler.getDataDemux(demux))
2079 demux->createTSRecorder(m_record);
2083 char templ[]=TSPATH "/timeshift.XXXXXX";
2084 m_timeshift_fd = mkstemp(templ);
2085 m_timeshift_file = templ;
2087 eDebug("recording to %s", templ);
2089 if (m_timeshift_fd < 0)
2095 m_record->setTargetFD(m_timeshift_fd);
2097 m_timeshift_enabled = 1;
2099 updateTimeshiftPids();
2105 RESULT eDVBServicePlay::stopTimeshift()
2107 if (!m_timeshift_enabled)
2112 m_timeshift_enabled = 0;
2117 close(m_timeshift_fd);
2118 eDebug("remove timeshift file");
2119 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2124 int eDVBServicePlay::isTimeshiftActive()
2126 return m_timeshift_enabled && m_timeshift_active;
2129 RESULT eDVBServicePlay::activateTimeshift()
2131 if (!m_timeshift_enabled)
2134 if (!m_timeshift_active)
2136 switchToTimeshift();
2143 PyObject *eDVBServicePlay::getCutList()
2145 ePyObject list = PyList_New(0);
2147 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2149 ePyObject tuple = PyTuple_New(2);
2150 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2151 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2152 PyList_Append(list, tuple);
2159 void eDVBServicePlay::setCutList(ePyObject list)
2161 if (!PyList_Check(list))
2163 int size = PyList_Size(list);
2166 m_cue_entries.clear();
2168 for (i=0; i<size; ++i)
2170 ePyObject tuple = PyList_GET_ITEM(list, i);
2171 if (!PyTuple_Check(tuple))
2173 eDebug("non-tuple in cutlist");
2176 if (PyTuple_Size(tuple) != 2)
2178 eDebug("cutlist entries need to be a 2-tuple");
2181 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2182 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2184 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2187 pts_t pts = PyLong_AsLongLong(ppts);
2188 int type = PyInt_AsLong(ptype);
2189 m_cue_entries.insert(cueEntry(pts, type));
2190 eDebug("adding %08llx, %d", pts, type);
2192 m_cuesheet_changed = 1;
2194 cutlistToCuesheet();
2195 m_event((iPlayableService*)this, evCuesheetChanged);
2198 void eDVBServicePlay::setCutListEnable(int enable)
2200 m_cutlist_enabled = enable;
2201 cutlistToCuesheet();
2204 void eDVBServicePlay::updateTimeshiftPids()
2209 eDVBServicePMTHandler::program program;
2210 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2212 if (h.getProgramInfo(program))
2216 std::set<int> pids_to_record;
2217 pids_to_record.insert(0); // PAT
2218 if (program.pmtPid != -1)
2219 pids_to_record.insert(program.pmtPid); // PMT
2221 if (program.textPid != -1)
2222 pids_to_record.insert(program.textPid); // Videotext
2224 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2225 i(program.videoStreams.begin());
2226 i != program.videoStreams.end(); ++i)
2227 pids_to_record.insert(i->pid);
2229 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2230 i(program.audioStreams.begin());
2231 i != program.audioStreams.end(); ++i)
2232 pids_to_record.insert(i->pid);
2234 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2235 i(program.subtitleStreams.begin());
2236 i != program.subtitleStreams.end(); ++i)
2237 pids_to_record.insert(i->pid);
2239 std::set<int> new_pids, obsolete_pids;
2241 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2242 m_pids_active.begin(), m_pids_active.end(),
2243 std::inserter(new_pids, new_pids.begin()));
2245 std::set_difference(
2246 m_pids_active.begin(), m_pids_active.end(),
2247 pids_to_record.begin(), pids_to_record.end(),
2248 std::inserter(new_pids, new_pids.begin())
2251 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2252 m_record->addPID(*i);
2254 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2255 m_record->removePID(*i);
2259 void eDVBServicePlay::switchToLive()
2261 if (!m_timeshift_active)
2267 m_teletext_parser = 0;
2269 m_subtitle_parser = 0;
2270 m_new_dvb_subtitle_page_connection = 0;
2271 m_new_subtitle_page_connection = 0;
2272 m_rds_decoder_event_connection = 0;
2273 m_video_event_connection = 0;
2275 /* free the timeshift service handler, we need the resources */
2276 m_service_handler_timeshift.free();
2277 m_timeshift_active = 0;
2279 m_event((iPlayableService*)this, evSeekableStatusChanged);
2284 void eDVBServicePlay::switchToTimeshift()
2286 if (m_timeshift_active)
2291 m_teletext_parser = 0;
2293 m_subtitle_parser = 0;
2294 m_new_subtitle_page_connection = 0;
2295 m_new_dvb_subtitle_page_connection = 0;
2296 m_rds_decoder_event_connection = 0;
2297 m_video_event_connection = 0;
2299 m_timeshift_active = 1;
2301 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2302 r.path = m_timeshift_file;
2304 m_cue = new eCueSheet();
2305 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2307 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2309 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2311 m_event((iPlayableService*)this, evSeekableStatusChanged);
2314 void eDVBServicePlay::updateDecoder()
2316 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2318 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2320 eDVBServicePMTHandler::program program;
2321 if (h.getProgramInfo(program))
2322 eDebug("getting program info failed.");
2325 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2326 if (!program.videoStreams.empty())
2328 eDebugNoNewLine(" (");
2329 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2330 i(program.videoStreams.begin());
2331 i != program.videoStreams.end(); ++i)
2338 if (i != program.videoStreams.begin())
2339 eDebugNoNewLine(", ");
2340 eDebugNoNewLine("%04x", i->pid);
2342 eDebugNoNewLine(")");
2344 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2345 if (!program.audioStreams.empty())
2347 eDebugNoNewLine(" (");
2348 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2349 i(program.audioStreams.begin());
2350 i != program.audioStreams.end(); ++i)
2352 if (i != program.audioStreams.begin())
2353 eDebugNoNewLine(", ");
2354 eDebugNoNewLine("%04x", i->pid);
2356 eDebugNoNewLine(")");
2358 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2359 pcrpid = program.pcrPid;
2360 eDebug(", and the text pid is %04x", program.textPid);
2361 tpid = program.textPid;
2366 h.getDecodeDemux(m_decode_demux);
2369 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2371 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2372 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2373 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2374 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2375 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2378 m_teletext_parser = 0;
2379 m_subtitle_parser = 0;
2383 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2390 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2391 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2392 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2394 else // subservice or recording
2396 eServiceReferenceDVB ref;
2397 m_service_handler.getServiceReference(ref);
2398 eServiceReferenceDVB parent = ref.getParentServiceReference();
2403 ePtr<eDVBResourceManager> res_mgr;
2404 if (!eDVBResourceManager::getInstance(res_mgr))
2406 ePtr<iDVBChannelList> db;
2407 if (!res_mgr->getChannelList(db))
2409 ePtr<eDVBService> origService;
2410 if (!db->getService(parent, origService))
2412 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2413 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2419 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2420 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2422 m_decoder->setVideoPID(vpid, vpidtype);
2423 selectAudioStream();
2425 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2426 m_decoder->setSyncPCR(pcrpid);
2428 m_decoder->setSyncPCR(-1);
2430 m_decoder->setTextPID(tpid);
2432 m_teletext_parser->start(program.textPid);
2435 m_decoder->setTrickmode(1);
2438 m_decoder->preroll();
2442 if (vpid > 0 && vpid < 0x2000)
2446 std::string radio_pic;
2447 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2448 m_decoder->setRadioPic(radio_pic);
2451 m_decoder->setAudioChannel(achannel);
2453 /* don't worry about non-existing services, nor pvr services */
2454 if (m_dvb_service && !m_is_pvr)
2456 /* (audio pid will be set in selectAudioTrack */
2457 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2458 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2459 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2460 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2463 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2466 void eDVBServicePlay::loadCuesheet()
2468 std::string filename = m_reference.path + ".cuts";
2470 m_cue_entries.clear();
2472 FILE *f = fopen(filename.c_str(), "rb");
2476 eDebug("loading cuts..");
2479 unsigned long long where;
2482 if (!fread(&where, sizeof(where), 1, f))
2484 if (!fread(&what, sizeof(what), 1, f))
2487 #if BYTE_ORDER == LITTLE_ENDIAN
2488 where = bswap_64(where);
2495 m_cue_entries.insert(cueEntry(where, what));
2498 eDebug("%d entries", m_cue_entries.size());
2500 eDebug("cutfile not found!");
2502 m_cuesheet_changed = 0;
2503 cutlistToCuesheet();
2504 m_event((iPlayableService*)this, evCuesheetChanged);
2507 void eDVBServicePlay::saveCuesheet()
2509 std::string filename = m_reference.path + ".cuts";
2511 FILE *f = fopen(filename.c_str(), "wb");
2515 unsigned long long where;
2518 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2520 #if BYTE_ORDER == BIG_ENDIAN
2523 where = bswap_64(i->where);
2525 what = htonl(i->what);
2526 fwrite(&where, sizeof(where), 1, f);
2527 fwrite(&what, sizeof(what), 1, f);
2533 m_cuesheet_changed = 0;
2536 void eDVBServicePlay::cutlistToCuesheet()
2540 eDebug("no cue sheet");
2545 if (!m_cutlist_enabled)
2547 m_cue->commitSpans();
2548 eDebug("cutlists were disabled");
2552 pts_t in = 0, out = 0, length = 0;
2556 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2560 if (i == m_cue_entries.end())
2563 if (i->what == 0) /* in */
2567 } else if (i->what == 1) /* out */
2569 else /* mark (2) or last play position (3) */
2586 m_cue->addSourceSpan(in, out);
2590 if (i == m_cue_entries.end())
2593 m_cue->commitSpans();
2596 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2598 if (m_subtitle_widget)
2599 disableSubtitles(parent);
2602 int tuplesize = PyTuple_Size(tuple);
2605 if (!PyTuple_Check(tuple))
2611 entry = PyTuple_GET_ITEM(tuple, 0);
2613 if (!PyInt_Check(entry))
2616 type = PyInt_AsLong(entry);
2618 if (type == 1) // teletext subtitles
2620 int page, magazine, pid;
2624 if (!m_teletext_parser)
2626 eDebug("enable teletext subtitles.. no parser !!!");
2630 entry = PyTuple_GET_ITEM(tuple, 1);
2631 if (!PyInt_Check(entry))
2633 pid = PyInt_AsLong(entry);
2635 entry = PyTuple_GET_ITEM(tuple, 2);
2636 if (!PyInt_Check(entry))
2638 page = PyInt_AsLong(entry);
2640 entry = PyTuple_GET_ITEM(tuple, 3);
2641 if (!PyInt_Check(entry))
2643 magazine = PyInt_AsLong(entry);
2645 m_subtitle_widget = new eSubtitleWidget(parent);
2646 m_subtitle_widget->resize(parent->size()); /* full size */
2647 m_teletext_parser->setPageAndMagazine(page, magazine);
2649 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2653 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2654 if (!m_subtitle_parser)
2656 eDebug("enable dvb subtitles.. no parser !!!");
2662 entry = PyTuple_GET_ITEM(tuple, 1);
2663 if (!PyInt_Check(entry))
2665 pid = PyInt_AsLong(entry);
2667 entry = PyTuple_GET_ITEM(tuple, 2);
2668 if (!PyInt_Check(entry))
2670 composition_page_id = PyInt_AsLong(entry);
2672 entry = PyTuple_GET_ITEM(tuple, 3);
2673 if (!PyInt_Check(entry))
2675 ancillary_page_id = PyInt_AsLong(entry);
2677 m_subtitle_widget = new eSubtitleWidget(parent);
2678 m_subtitle_widget->resize(parent->size()); /* full size */
2679 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2681 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2687 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2688 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2689 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2693 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2695 delete m_subtitle_widget;
2696 m_subtitle_widget = 0;
2697 if (m_subtitle_parser)
2699 m_subtitle_parser->stop();
2700 m_dvb_subtitle_pages.clear();
2702 if (m_teletext_parser)
2704 m_teletext_parser->setPageAndMagazine(-1, -1);
2705 m_subtitle_pages.clear();
2708 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2712 PyObject *eDVBServicePlay::getCachedSubtitle()
2716 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2719 unsigned int data = (unsigned int)tmp;
2720 int pid = (data&0xFFFF0000)>>16;
2721 ePyObject tuple = PyTuple_New(4);
2722 eDVBServicePMTHandler::program program;
2723 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2724 if (!h.getProgramInfo(program))
2726 if (program.textPid==pid) // teletext
2727 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2729 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2730 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2731 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2732 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2740 PyObject *eDVBServicePlay::getSubtitleList()
2742 if (!m_teletext_parser)
2745 ePyObject l = PyList_New(0);
2746 std::set<int> added_ttx_pages;
2748 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2749 m_teletext_parser->m_found_subtitle_pages;
2751 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2752 eDVBServicePMTHandler::program program;
2753 if (h.getProgramInfo(program))
2754 eDebug("getting program info failed.");
2757 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2758 it != program.subtitleStreams.end(); ++it)
2760 switch(it->subtitling_type)
2762 case 0x01: // ebu teletext subtitles
2764 int page_number = it->teletext_page_number & 0xFF;
2765 int magazine_number = it->teletext_magazine_number & 7;
2766 int hash = magazine_number << 8 | page_number;
2767 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2769 ePyObject tuple = PyTuple_New(5);
2770 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2771 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2772 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2773 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2774 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2775 PyList_Append(l, tuple);
2777 added_ttx_pages.insert(hash);
2782 case 0x20 ... 0x23: // dvb subtitles
2784 ePyObject tuple = PyTuple_New(5);
2785 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2786 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2787 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2788 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2789 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2790 PyList_Insert(l, 0, tuple);
2798 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2799 it != subs.end(); ++it)
2801 int page_number = it->teletext_page_number & 0xFF;
2802 int magazine_number = it->teletext_magazine_number & 7;
2803 int hash = magazine_number << 8 | page_number;
2804 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2806 ePyObject tuple = PyTuple_New(5);
2807 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2808 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2809 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2810 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2811 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2812 PyList_Append(l, tuple);
2820 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2822 if (m_subtitle_widget)
2826 m_decoder->getPTS(0, pos);
2827 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2828 m_subtitle_pages.push_back(page);
2829 checkSubtitleTiming();
2833 void eDVBServicePlay::checkSubtitleTiming()
2835 eDebug("checkSubtitleTiming");
2836 if (!m_subtitle_widget)
2840 enum { TELETEXT, DVB } type;
2841 eDVBTeletextSubtitlePage page;
2842 eDVBSubtitlePage dvb_page;
2844 if (!m_subtitle_pages.empty())
2846 page = m_subtitle_pages.front();
2848 show_time = page.m_pts;
2850 else if (!m_dvb_subtitle_pages.empty())
2852 dvb_page = m_dvb_subtitle_pages.front();
2854 show_time = dvb_page.m_show_time;
2862 m_decoder->getPTS(0, pos);
2864 eDebug("%lld %lld", pos, show_time);
2865 int diff = show_time - pos;
2868 eDebug("[late (%d ms)]", -diff / 90);
2871 // if (diff > 900000)
2873 // eDebug("[invalid]");
2879 if (type == TELETEXT)
2881 eDebug("display teletext subtitle page %lld", show_time);
2882 m_subtitle_widget->setPage(page);
2883 m_subtitle_pages.pop_front();
2887 eDebug("display dvb subtitle Page %lld", show_time);
2888 m_subtitle_widget->setPage(dvb_page);
2889 m_dvb_subtitle_pages.pop_front();
2893 eDebug("start subtitle delay %d", diff / 90);
2894 m_subtitle_sync_timer.start(diff / 90, 1);
2900 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2902 if (m_subtitle_widget)
2906 m_decoder->getPTS(0, pos);
2907 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2908 m_dvb_subtitle_pages.push_back(p);
2909 checkSubtitleTiming();
2913 int eDVBServicePlay::getAC3Delay()
2916 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2918 return m_decoder->getAC3Delay();
2923 int eDVBServicePlay::getPCMDelay()
2926 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2928 return m_decoder->getPCMDelay();
2933 void eDVBServicePlay::setAC3Delay(int delay)
2936 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2938 m_decoder->setAC3Delay(delay);
2941 void eDVBServicePlay::setPCMDelay(int delay)
2944 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2946 m_decoder->setPCMDelay(delay);
2949 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2951 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2952 m_event((iPlayableService*)this, evVideoSizeChanged);
2955 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2961 PyObject *eDVBServicePlay::getStreamingData()
2963 eDVBServicePMTHandler::program program;
2964 if (m_service_handler.getProgramInfo(program))
2970 PyObject *r = program.createPythonObject();
2971 ePtr<iDVBDemux> demux;
2972 if (!m_service_handler.getDataDemux(demux))
2975 demux->getCADemuxID(demux_id);
2977 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
2984 DEFINE_REF(eDVBServicePlay)
2986 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2990 case iServiceInformation::sTransponderData:
2991 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2995 return iStaticServiceInformation::getInfoObject(ref, w);
2998 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");