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!");
432 eDVBChannelID chid, chid_ignore;
433 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
434 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
436 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
437 int tmp=res->canAllocateChannel(chid, chid_ignore);
440 m_playable_service = *it;
447 m_playable_service = eServiceReference();
451 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
456 #include <lib/dvb/epgcache.h>
458 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
460 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
463 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
465 DECLARE_REF(eStaticServiceDVBPVRInformation);
466 eServiceReference m_ref;
467 eDVBMetaParser m_parser;
469 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
470 RESULT getName(const eServiceReference &ref, std::string &name);
471 int getLength(const eServiceReference &ref);
472 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
473 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
474 int getInfo(const eServiceReference &ref, int w);
475 std::string getInfoString(const eServiceReference &ref,int w);
478 DEFINE_REF(eStaticServiceDVBPVRInformation);
480 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
483 m_parser.parseFile(ref.path);
486 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
488 ASSERT(ref == m_ref);
489 if (m_parser.m_name.size())
490 name = m_parser.m_name;
494 size_t n = name.rfind('/');
495 if (n != std::string::npos)
496 name = name.substr(n + 1);
501 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
503 ASSERT(ref == m_ref);
507 if (tstools.openFile(ref.path.c_str()))
511 if (tstools.calcLen(len))
517 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
521 case iServiceInformation::sDescription:
522 return iServiceInformation::resIsString;
523 case iServiceInformation::sServiceref:
524 return iServiceInformation::resIsString;
525 case iServiceInformation::sTimeCreate:
526 if (m_parser.m_time_create)
527 return m_parser.m_time_create;
529 return iServiceInformation::resNA;
531 return iServiceInformation::resNA;
535 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
539 case iServiceInformation::sDescription:
540 return m_parser.m_description;
541 case iServiceInformation::sServiceref:
542 return m_parser.m_ref.toString();
543 case iServiceInformation::sTags:
544 return m_parser.m_tags;
550 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
552 if (!ref.path.empty())
554 ePtr<eServiceEvent> event = new eServiceEvent;
555 std::string filename = ref.path;
556 filename.erase(filename.length()-2, 2);
558 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
568 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
570 DECLARE_REF(eDVBPVRServiceOfflineOperations);
571 eServiceReferenceDVB m_ref;
573 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
575 RESULT deleteFromDisk(int simulate);
576 RESULT getListOfFilenames(std::list<std::string> &);
579 DEFINE_REF(eDVBPVRServiceOfflineOperations);
581 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
585 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
591 std::list<std::string> res;
592 if (getListOfFilenames(res))
595 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
597 eDebug("FATAL !! can't get background file eraser");
599 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
601 eDebug("Removing %s...", i->c_str());
603 eraser->erase(i->c_str());
605 ::unlink(i->c_str());
612 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
615 res.push_back(m_ref.path);
617 // handling for old splitted recordings (enigma 1)
622 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
624 if (stat(buf, &s) < 0)
629 res.push_back(m_ref.path + ".meta");
630 res.push_back(m_ref.path + ".ap");
631 res.push_back(m_ref.path + ".cuts");
632 std::string tmp = m_ref.path;
633 tmp.erase(m_ref.path.length()-3);
634 res.push_back(tmp + ".eit");
638 DEFINE_REF(eServiceFactoryDVB)
640 eServiceFactoryDVB::eServiceFactoryDVB()
642 ePtr<eServiceCenter> sc;
644 eServiceCenter::getPrivInstance(sc);
646 sc->addServiceFactory(eServiceFactoryDVB::id, this);
648 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
649 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
652 eServiceFactoryDVB::~eServiceFactoryDVB()
654 ePtr<eServiceCenter> sc;
656 eServiceCenter::getPrivInstance(sc);
658 sc->removeServiceFactory(eServiceFactoryDVB::id);
661 DEFINE_REF(eDVBServiceList);
663 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
667 eDVBServiceList::~eDVBServiceList()
671 RESULT eDVBServiceList::startQuery()
673 ePtr<iDVBChannelList> db;
674 ePtr<eDVBResourceManager> res;
677 if ((err = eDVBResourceManager::getInstance(res)) != 0)
679 eDebug("no resource manager");
682 if ((err = res->getChannelList(db)) != 0)
684 eDebug("no channel list");
688 ePtr<eDVBChannelQuery> q;
690 if (!m_parent.path.empty())
692 eDVBChannelQuery::compile(q, m_parent.path);
695 eDebug("compile query failed");
700 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
702 eDebug("startQuery failed");
709 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
711 eServiceReferenceDVB ref;
716 while (!m_query->getNextResult(ref))
720 list.sort(iListableServiceCompare(this));
725 // The first argument of this function is a format string to specify the order and
726 // the content of the returned list
727 // useable format options are
728 // R = Service Reference (as swig object .. this is very slow)
729 // S = Service Reference (as python string object .. same as ref.toString())
730 // C = Service Reference (as python string object .. same as ref.toCompareString())
731 // N = Service Name (as python string object)
732 // n = Short Service Name (short name brakets used) (as python string object)
733 // when exactly one return value per service is selected in the format string,
734 // then each value is directly a list entry
735 // when more than one value is returned per service, then the list is a list of
737 // unknown format string chars are returned as python None values !
738 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
741 std::list<eServiceReference> tmplist;
744 if (!format || !(retcount=strlen(format)))
745 format = "R"; // just return service reference swig object ...
747 if (!getContent(tmplist, sorted))
749 int services=tmplist.size();
750 ePtr<iStaticServiceInformation> sptr;
751 eServiceCenterPtr service_center;
753 if (strchr(format, 'N') || strchr(format, 'n'))
754 eServiceCenter::getPrivInstance(service_center);
756 ret = PyList_New(services);
757 std::list<eServiceReference>::iterator it(tmplist.begin());
759 for (int cnt=0; cnt < services; ++cnt)
761 eServiceReference &ref=*it++;
762 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
763 for (int i=0; i < retcount; ++i)
768 case 'R': // service reference (swig)object
769 tmp = NEW_eServiceReference(ref);
771 case 'C': // service reference compare string
772 tmp = PyString_FromString(ref.toCompareString().c_str());
774 case 'S': // service reference string
775 tmp = PyString_FromString(ref.toString().c_str());
777 case 'N': // service name
780 service_center->info(ref, sptr);
784 sptr->getName(ref, name);
786 // filter short name brakets
788 while((pos = name.find("\xc2\x86")) != std::string::npos)
790 while((pos = name.find("\xc2\x87")) != std::string::npos)
794 tmp = PyString_FromString(name.c_str());
798 tmp = PyString_FromString("<n/a>");
800 case 'n': // short service name
803 service_center->info(ref, sptr);
807 sptr->getName(ref, name);
808 name = buildShortName(name);
810 tmp = PyString_FromString(name.c_str());
814 tmp = PyString_FromString("<n/a>");
827 PyTuple_SET_ITEM(tuple, i, tmp);
829 PyList_SET_ITEM(ret, cnt, tmp);
833 PyList_SET_ITEM(ret, cnt, tuple);
836 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
839 RESULT eDVBServiceList::getNext(eServiceReference &ref)
844 return m_query->getNextResult((eServiceReferenceDVB&)ref);
847 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
849 if (m_parent.flags & eServiceReference::canDescent) // bouquet
851 ePtr<iDVBChannelList> db;
852 ePtr<eDVBResourceManager> resm;
854 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
857 if (db->getBouquet(m_parent, m_bouquet) != 0)
868 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
872 return m_bouquet->addService(ref, before);
875 RESULT eDVBServiceList::removeService(eServiceReference &ref)
879 return m_bouquet->removeService(ref);
882 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
886 return m_bouquet->moveService(ref, pos);
889 RESULT eDVBServiceList::flushChanges()
893 return m_bouquet->flushChanges();
896 RESULT eDVBServiceList::setListName(const std::string &name)
900 return m_bouquet->setListName(name);
903 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
905 ePtr<eDVBService> service;
906 int r = lookupService(service, ref);
909 // check resources...
910 ptr = new eDVBServicePlay(ref, service);
914 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
916 if (ref.path.empty())
918 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
927 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
929 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
930 if (list->startQuery())
940 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
942 /* is a listable service? */
943 if (ref.flags & eServiceReference::canDescent) // bouquet
945 if ( !ref.name.empty() ) // satellites or providers list
946 ptr = m_StaticServiceDVBInfo;
947 else // a dvb bouquet
948 ptr = m_StaticServiceDVBBouquetInfo;
950 else if (!ref.path.empty()) /* do we have a PVR service? */
951 ptr = new eStaticServiceDVBPVRInformation(ref);
952 else // normal dvb service
954 ePtr<eDVBService> service;
955 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
956 ptr = m_StaticServiceDVBInfo;
958 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
964 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
966 if (ref.path.empty())
972 ptr = new eDVBPVRServiceOfflineOperations(ref);
977 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
979 // TODO: handle the listing itself
980 // if (ref.... == -1) .. return "... bouquets ...";
981 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
983 ePtr<iDVBChannelList> db;
984 ePtr<eDVBResourceManager> res;
987 if ((err = eDVBResourceManager::getInstance(res)) != 0)
989 eDebug("no resource manager");
992 if ((err = res->getChannelList(db)) != 0)
994 eDebug("no channel list");
998 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
999 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
1001 eDebug("getService failed!");
1008 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
1009 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
1011 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
1013 m_is_pvr = !m_reference.path.empty();
1015 m_timeshift_enabled = m_timeshift_active = 0;
1018 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
1019 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
1020 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
1022 m_cuesheet_changed = 0;
1023 m_cutlist_enabled = 1;
1025 m_subtitle_widget = 0;
1029 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
1032 eDVBServicePlay::~eDVBServicePlay()
1034 delete m_subtitle_widget;
1037 void eDVBServicePlay::gotNewEvent()
1041 ePtr<eServiceEvent> m_event_now, m_event_next;
1042 getEvent(m_event_now, 0);
1043 getEvent(m_event_next, 1);
1046 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1048 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1050 m_event((iPlayableService*)this, evUpdatedEventInfo);
1053 void eDVBServicePlay::serviceEvent(int event)
1055 m_tune_state = event;
1059 case eDVBServicePMTHandler::eventTuned:
1061 ePtr<iDVBDemux> m_demux;
1062 if (!m_service_handler.getDataDemux(m_demux))
1064 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1065 int sid = ref.getParentServiceID().get();
1067 sid = ref.getServiceID().get();
1068 if ( ref.getParentTransportStreamID().get() &&
1069 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1070 m_event_handler.startOther(m_demux, sid);
1072 m_event_handler.start(m_demux, sid);
1076 case eDVBServicePMTHandler::eventNoResources:
1077 case eDVBServicePMTHandler::eventNoPAT:
1078 case eDVBServicePMTHandler::eventNoPATEntry:
1079 case eDVBServicePMTHandler::eventNoPMT:
1080 case eDVBServicePMTHandler::eventTuneFailed:
1082 eDebug("DVB service failed to tune - error %d", event);
1083 m_event((iPlayableService*)this, evTuneFailed);
1086 case eDVBServicePMTHandler::eventNewProgramInfo:
1088 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1089 if (m_timeshift_enabled)
1090 updateTimeshiftPids();
1091 if (!m_timeshift_active)
1093 if (m_first_program_info && m_is_pvr)
1095 m_first_program_info = 0;
1098 m_event((iPlayableService*)this, evUpdatedInfo);
1101 case eDVBServicePMTHandler::eventEOF:
1102 m_event((iPlayableService*)this, evEOF);
1104 case eDVBServicePMTHandler::eventSOF:
1105 m_event((iPlayableService*)this, evSOF);
1110 void eDVBServicePlay::serviceEventTimeshift(int event)
1114 case eDVBServicePMTHandler::eventNewProgramInfo:
1115 if (m_timeshift_active)
1118 case eDVBServicePMTHandler::eventSOF:
1119 m_event((iPlayableService*)this, evSOF);
1121 case eDVBServicePMTHandler::eventEOF:
1122 if ((!m_is_paused) && (m_skipmode >= 0))
1128 RESULT eDVBServicePlay::start()
1131 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1132 two (one for decoding, one for data source), as we must be prepared
1133 to start recording from the data demux. */
1135 m_cue = new eCueSheet();
1137 m_event(this, evStart);
1139 m_first_program_info = 1;
1140 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1141 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1143 /* inject EIT if there is a stored one */
1146 std::string filename = service.path;
1147 filename.erase(filename.length()-2, 2);
1149 ePtr<eServiceEvent> event = new eServiceEvent;
1150 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1152 ePtr<eServiceEvent> empty;
1153 m_event_handler.inject(event, 0);
1154 m_event_handler.inject(empty, 1);
1161 m_event(this, evStart);
1166 RESULT eDVBServicePlay::stop()
1168 /* add bookmark for last play position */
1171 pts_t play_position, length;
1172 if (!getPlayPosition(play_position))
1174 /* remove last position */
1175 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1177 if (i->what == 3) /* current play position */
1179 m_cue_entries.erase(i);
1180 i = m_cue_entries.begin();
1186 if (getLength(length))
1191 int perc = play_position * 100LL / length;
1193 /* only store last play position when between 5% and 95% */
1194 if ((5 < perc) && (perc < 95))
1195 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1197 m_cuesheet_changed = 1;
1201 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1203 m_service_handler_timeshift.free();
1204 m_service_handler.free();
1206 if (m_is_pvr && m_cuesheet_changed)
1209 /* save cuesheet only when main file is accessible. */
1210 if (!::stat(m_reference.path.c_str(), &s))
1213 m_event((iPlayableService*)this, evStopped);
1217 RESULT eDVBServicePlay::setTarget(int target)
1219 m_is_primary = !target;
1223 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1225 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1229 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1231 /* note: we check for timeshift to be enabled,
1232 not neccessary active. if you pause when timeshift
1233 is not active, you should activate it when unpausing */
1234 if ((!m_is_pvr) && (!m_timeshift_enabled))
1244 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1247 return m_decoder->setSlowMotion(ratio);
1252 RESULT eDVBServicePlay::setFastForward(int ratio)
1254 int skipmode, ffratio;
1260 } else if (ratio > 0)
1268 } else // if (ratio < 0)
1274 if (m_skipmode != skipmode)
1276 eDebug("setting cue skipmode to %d", skipmode);
1278 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1281 m_skipmode = skipmode;
1286 return m_decoder->setFastForward(ffratio);
1289 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1291 if (m_is_pvr || m_timeshift_enabled)
1301 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1302 RESULT eDVBServicePlay::getLength(pts_t &len)
1304 ePtr<iDVBPVRChannel> pvr_channel;
1306 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1309 return pvr_channel->getLength(len);
1312 RESULT eDVBServicePlay::pause()
1314 if (!m_is_paused && m_decoder)
1317 return m_decoder->freeze(0);
1322 RESULT eDVBServicePlay::unpause()
1324 if (m_is_paused && m_decoder)
1327 return m_decoder->unfreeze();
1332 RESULT eDVBServicePlay::seekTo(pts_t to)
1334 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1336 if (!m_decode_demux)
1339 ePtr<iDVBPVRChannel> pvr_channel;
1341 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1347 m_cue->seekTo(0, to);
1348 m_dvb_subtitle_pages.clear();
1349 m_subtitle_pages.clear();
1354 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1356 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1358 if (!m_decode_demux)
1361 ePtr<iDVBPVRChannel> pvr_channel;
1363 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1368 /* HACK until we have skip-AP api */
1369 if ((to > 0) && (to < 100))
1377 m_cue->seekTo(mode, to);
1378 m_dvb_subtitle_pages.clear();
1379 m_subtitle_pages.clear();
1383 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1385 ePtr<iDVBPVRChannel> pvr_channel;
1387 if (!m_decode_demux)
1390 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1395 /* if there is a decoder, use audio or video PTS */
1398 r = m_decoder->getPTS(0, pos);
1404 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1407 RESULT eDVBServicePlay::setTrickmode(int trick)
1410 m_decoder->setTrickmode(trick);
1414 RESULT eDVBServicePlay::isCurrentlySeekable()
1416 return m_is_pvr || m_timeshift_active;
1419 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1425 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1431 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1437 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1443 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1449 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1452 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1453 (m_timeshift_enabled || !m_is_pvr))
1455 if (!m_timeshift_enabled)
1457 /* we need enough diskspace */
1459 if (statfs(TSPATH "/.", &fs) < 0)
1461 eDebug("statfs failed!");
1465 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1467 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1477 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1488 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1494 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1500 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1506 RESULT eDVBServicePlay::getName(std::string &name)
1510 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1511 return i->getName(m_reference, name);
1515 m_dvb_service->getName(m_reference, name);
1519 else if (!m_reference.name.empty())
1520 eStaticServiceDVBInformation().getName(m_reference, name);
1522 name = "DVB service";
1526 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1528 return m_event_handler.getEvent(evt, nownext);
1531 int eDVBServicePlay::getInfo(int w)
1533 eDVBServicePMTHandler::program program;
1536 return resIsPyObject;
1538 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1540 int no_program_info = 0;
1542 if (h.getProgramInfo(program))
1543 no_program_info = 1;
1547 #if HAVE_DVB_API_VERSION >= 3
1549 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1550 return m_videoEventData.height;
1553 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1554 return m_videoEventData.width;
1557 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1560 #if HAVE_DVB_API_VERSION >= 3
1561 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1562 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1565 #warning "FIXMEE implement sAspect for old DVB API"
1567 if (no_program_info)
1569 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1571 ePtr<eServiceEvent> evt;
1572 if (!m_event_handler.getEvent(evt, 0))
1574 ePtr<eComponentData> data;
1575 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1577 if ( data->getStreamContent() == 1 )
1579 switch(data->getComponentType())
1582 case 1: // 4:3 SD PAL
1584 case 3: // 16:9 SD PAL
1585 case 4: // > 16:9 PAL
1586 case 5: // 4:3 SD NTSC
1588 case 7: // 16:9 SD NTSC
1589 case 8: // > 16:9 NTSC
1592 case 9: // 4:3 HD PAL
1594 case 0xB: // 16:9 HD PAL
1595 case 0xC: // > 16:9 HD PAL
1596 case 0xD: // 4:3 HD NTSC
1598 case 0xF: // 16:9 HD NTSC
1599 case 0x10: // > 16:9 HD PAL
1600 return data->getComponentType();
1607 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1608 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1609 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1610 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1611 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1612 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1613 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1614 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1615 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1616 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1617 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1618 case sProvider: if (!m_dvb_service) return -1; return -2;
1619 case sServiceref: return resIsString;
1620 case sDVBState: return m_tune_state;
1626 std::string eDVBServicePlay::getInfoString(int w)
1631 if (!m_dvb_service) return "";
1632 return m_dvb_service->m_provider_name;
1634 return m_reference.toString();
1638 return iServiceInformation::getInfoString(w);
1641 PyObject *eDVBServicePlay::getInfoObject(int w)
1646 return m_service_handler.getCaIds();
1647 case sTransponderData:
1648 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1652 return iServiceInformation::getInfoObject(w);
1655 int eDVBServicePlay::getNumberOfTracks()
1657 eDVBServicePMTHandler::program program;
1658 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1659 if (h.getProgramInfo(program))
1661 return program.audioStreams.size();
1664 int eDVBServicePlay::getCurrentTrack()
1666 eDVBServicePMTHandler::program program;
1667 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1668 if (h.getProgramInfo(program))
1671 int max = program.audioStreams.size();
1674 for (i = 0; i < max; ++i)
1675 if (program.audioStreams[i].pid == m_current_audio_pid)
1681 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1683 int ret = selectAudioStream(i);
1685 if (m_decoder->start())
1691 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1693 eDVBServicePMTHandler::program program;
1694 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1696 if (h.getProgramInfo(program))
1699 if (i >= program.audioStreams.size())
1702 info.m_pid = program.audioStreams[i].pid;
1704 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1705 info.m_description = "MPEG";
1706 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1707 info.m_description = "AC3";
1708 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1709 info.m_description = "AAC";
1710 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1711 info.m_description = "DTS";
1713 info.m_description = "???";
1715 if (program.audioStreams[i].component_tag != -1)
1717 ePtr<eServiceEvent> evt;
1718 if (!m_event_handler.getEvent(evt, 0))
1720 ePtr<eComponentData> data;
1721 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1722 info.m_language = data->getText();
1726 if (info.m_language.empty())
1727 info.m_language = program.audioStreams[i].language_code;
1732 int eDVBServicePlay::selectAudioStream(int i)
1734 eDVBServicePMTHandler::program program;
1735 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1737 if (h.getProgramInfo(program))
1740 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1748 stream = program.defaultAudioStream;
1750 int apid = -1, apidtype = -1;
1752 if (((unsigned int)stream) < program.audioStreams.size())
1754 apid = program.audioStreams[stream].pid;
1755 apidtype = program.audioStreams[stream].type;
1758 m_current_audio_pid = apid;
1760 if (m_decoder->setAudioPID(apid, apidtype))
1762 eDebug("set audio pid failed");
1766 /* 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 */
1767 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1770 ePtr<iDVBDemux> data_demux;
1771 if (!h.getDataDemux(data_demux))
1773 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1774 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1778 /* if we decided that we need one, update the pid */
1780 m_rds_decoder->start(apid);
1782 /* store new pid as default only when:
1783 a.) we have an entry in the service db for the current service,
1784 b.) we are not playing back something,
1785 c.) we are not selecting the default entry. (we wouldn't change
1786 anything in the best case, or destroy the default setting in
1787 case the real default is not yet available.)
1789 if (m_dvb_service && !m_is_pvr && ((i != -1)
1790 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1792 if (apidtype == eDVBAudio::aMPEG)
1794 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1795 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1799 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1800 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1804 h.resetCachedProgram();
1809 int eDVBServicePlay::getCurrentChannel()
1811 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1814 RESULT eDVBServicePlay::selectChannel(int i)
1816 if (i < LEFT || i > RIGHT || i == STEREO)
1819 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1821 m_decoder->setAudioChannel(i);
1825 std::string eDVBServicePlay::getText(int x)
1831 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1833 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1838 void eDVBServicePlay::rdsDecoderEvent(int what)
1842 case eDVBRdsDecoder::RadioTextChanged:
1843 m_event((iPlayableService*)this, evUpdatedRadioText);
1845 case eDVBRdsDecoder::RtpTextChanged:
1846 m_event((iPlayableService*)this, evUpdatedRtpText);
1848 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1849 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1851 case eDVBRdsDecoder::RecvRassSlidePic:
1852 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1857 void eDVBServicePlay::showRassSlidePicture()
1863 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1864 if (rass_slide_pic.length())
1865 m_decoder->showSinglePic(rass_slide_pic.c_str());
1867 eDebug("empty filename for rass slide picture received!!");
1870 eDebug("no MPEG Decoder to show iframes avail");
1873 eDebug("showRassSlidePicture called.. but not decoder");
1876 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1882 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1883 if (rass_interactive_pic.length())
1884 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1886 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1889 eDebug("no MPEG Decoder to show iframes avail");
1892 eDebug("showRassInteractivePic called.. but not decoder");
1895 ePyObject eDVBServicePlay::getRassInteractiveMask()
1898 return m_rds_decoder->getRassPictureMask();
1902 int eDVBServiceBase::getFrontendInfo(int w)
1904 eUsePtr<iDVBChannel> channel;
1905 if(m_service_handler.getChannel(channel))
1907 ePtr<iDVBFrontend> fe;
1908 if(channel->getFrontend(fe))
1910 return fe->readFrontendData(w);
1913 PyObject *eDVBServiceBase::getFrontendData()
1915 ePyObject ret = PyDict_New();
1918 eUsePtr<iDVBChannel> channel;
1919 if(!m_service_handler.getChannel(channel))
1921 ePtr<iDVBFrontend> fe;
1922 if(!channel->getFrontend(fe))
1923 fe->getFrontendData(ret);
1931 PyObject *eDVBServiceBase::getFrontendStatus()
1933 ePyObject ret = PyDict_New();
1936 eUsePtr<iDVBChannel> channel;
1937 if(!m_service_handler.getChannel(channel))
1939 ePtr<iDVBFrontend> fe;
1940 if(!channel->getFrontend(fe))
1941 fe->getFrontendStatus(ret);
1949 PyObject *eDVBServiceBase::getTransponderData(bool original)
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))
1960 fe->getTransponderData(ret, original);
1961 ePtr<iDVBFrontendParameters> feparm;
1962 channel->getCurrentFrontendParameters(feparm);
1965 eDVBFrontendParametersSatellite osat;
1966 if (!feparm->getDVBS(osat))
1968 void PutToDict(ePyObject &, const char*, long);
1969 void PutToDict(ePyObject &, const char*, const char*);
1970 PutToDict(ret, "orbital_position", osat.orbital_position);
1971 const char *tmp = "UNKNOWN";
1972 switch(osat.polarisation)
1974 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1975 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1976 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1977 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1980 PutToDict(ret, "polarization", tmp);
1991 PyObject *eDVBServiceBase::getAll(bool original)
1993 ePyObject ret = getTransponderData(original);
1996 eUsePtr<iDVBChannel> channel;
1997 if(!m_service_handler.getChannel(channel))
1999 ePtr<iDVBFrontend> fe;
2000 if(!channel->getFrontend(fe))
2002 fe->getFrontendData(ret);
2003 fe->getFrontendStatus(ret);
2010 int eDVBServicePlay::getNumberOfSubservices()
2012 ePtr<eServiceEvent> evt;
2013 if (!m_event_handler.getEvent(evt, 0))
2014 return evt->getNumOfLinkageServices();
2018 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2020 ePtr<eServiceEvent> evt;
2021 if (!m_event_handler.getEvent(evt, 0))
2023 if (!evt->getLinkageService(sub, m_reference, n))
2026 sub.type=eServiceReference::idInvalid;
2030 RESULT eDVBServicePlay::startTimeshift()
2032 ePtr<iDVBDemux> demux;
2034 eDebug("Start timeshift!");
2036 if (m_timeshift_enabled)
2039 /* start recording with the data demux. */
2040 if (m_service_handler.getDataDemux(demux))
2043 demux->createTSRecorder(m_record);
2047 char templ[]=TSPATH "/timeshift.XXXXXX";
2048 m_timeshift_fd = mkstemp(templ);
2049 m_timeshift_file = templ;
2051 eDebug("recording to %s", templ);
2053 if (m_timeshift_fd < 0)
2059 m_record->setTargetFD(m_timeshift_fd);
2061 m_timeshift_enabled = 1;
2063 updateTimeshiftPids();
2069 RESULT eDVBServicePlay::stopTimeshift()
2071 if (!m_timeshift_enabled)
2076 m_timeshift_enabled = 0;
2081 close(m_timeshift_fd);
2082 eDebug("remove timeshift file");
2083 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2088 int eDVBServicePlay::isTimeshiftActive()
2090 return m_timeshift_enabled && m_timeshift_active;
2093 RESULT eDVBServicePlay::activateTimeshift()
2095 if (!m_timeshift_enabled)
2098 if (!m_timeshift_active)
2100 switchToTimeshift();
2107 PyObject *eDVBServicePlay::getCutList()
2109 ePyObject list = PyList_New(0);
2111 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2113 ePyObject tuple = PyTuple_New(2);
2114 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2115 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2116 PyList_Append(list, tuple);
2123 void eDVBServicePlay::setCutList(ePyObject list)
2125 if (!PyList_Check(list))
2127 int size = PyList_Size(list);
2130 m_cue_entries.clear();
2132 for (i=0; i<size; ++i)
2134 ePyObject tuple = PyList_GET_ITEM(list, i);
2135 if (!PyTuple_Check(tuple))
2137 eDebug("non-tuple in cutlist");
2140 if (PyTuple_Size(tuple) != 2)
2142 eDebug("cutlist entries need to be a 2-tuple");
2145 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2146 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2148 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2151 pts_t pts = PyLong_AsLongLong(ppts);
2152 int type = PyInt_AsLong(ptype);
2153 m_cue_entries.insert(cueEntry(pts, type));
2154 eDebug("adding %08llx, %d", pts, type);
2156 m_cuesheet_changed = 1;
2158 cutlistToCuesheet();
2159 m_event((iPlayableService*)this, evCuesheetChanged);
2162 void eDVBServicePlay::setCutListEnable(int enable)
2164 m_cutlist_enabled = enable;
2165 cutlistToCuesheet();
2168 void eDVBServicePlay::updateTimeshiftPids()
2173 eDVBServicePMTHandler::program program;
2174 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2176 if (h.getProgramInfo(program))
2180 std::set<int> pids_to_record;
2181 pids_to_record.insert(0); // PAT
2182 if (program.pmtPid != -1)
2183 pids_to_record.insert(program.pmtPid); // PMT
2185 if (program.textPid != -1)
2186 pids_to_record.insert(program.textPid); // Videotext
2188 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2189 i(program.videoStreams.begin());
2190 i != program.videoStreams.end(); ++i)
2191 pids_to_record.insert(i->pid);
2193 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2194 i(program.audioStreams.begin());
2195 i != program.audioStreams.end(); ++i)
2196 pids_to_record.insert(i->pid);
2198 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2199 i(program.subtitleStreams.begin());
2200 i != program.subtitleStreams.end(); ++i)
2201 pids_to_record.insert(i->pid);
2203 std::set<int> new_pids, obsolete_pids;
2205 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2206 m_pids_active.begin(), m_pids_active.end(),
2207 std::inserter(new_pids, new_pids.begin()));
2209 std::set_difference(
2210 m_pids_active.begin(), m_pids_active.end(),
2211 pids_to_record.begin(), pids_to_record.end(),
2212 std::inserter(new_pids, new_pids.begin())
2215 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2216 m_record->addPID(*i);
2218 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2219 m_record->removePID(*i);
2223 void eDVBServicePlay::switchToLive()
2225 if (!m_timeshift_active)
2231 m_teletext_parser = 0;
2233 m_subtitle_parser = 0;
2234 m_new_dvb_subtitle_page_connection = 0;
2235 m_new_subtitle_page_connection = 0;
2236 m_rds_decoder_event_connection = 0;
2237 m_video_event_connection = 0;
2239 /* free the timeshift service handler, we need the resources */
2240 m_service_handler_timeshift.free();
2241 m_timeshift_active = 0;
2243 m_event((iPlayableService*)this, evSeekableStatusChanged);
2248 void eDVBServicePlay::switchToTimeshift()
2250 if (m_timeshift_active)
2255 m_teletext_parser = 0;
2257 m_subtitle_parser = 0;
2258 m_new_subtitle_page_connection = 0;
2259 m_new_dvb_subtitle_page_connection = 0;
2260 m_rds_decoder_event_connection = 0;
2261 m_video_event_connection = 0;
2263 m_timeshift_active = 1;
2265 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2266 r.path = m_timeshift_file;
2268 m_cue = new eCueSheet();
2269 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2271 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2273 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2275 m_event((iPlayableService*)this, evSeekableStatusChanged);
2278 void eDVBServicePlay::updateDecoder()
2280 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2282 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2284 eDVBServicePMTHandler::program program;
2285 if (h.getProgramInfo(program))
2286 eDebug("getting program info failed.");
2289 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2290 if (!program.videoStreams.empty())
2292 eDebugNoNewLine(" (");
2293 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2294 i(program.videoStreams.begin());
2295 i != program.videoStreams.end(); ++i)
2302 if (i != program.videoStreams.begin())
2303 eDebugNoNewLine(", ");
2304 eDebugNoNewLine("%04x", i->pid);
2306 eDebugNoNewLine(")");
2308 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2309 if (!program.audioStreams.empty())
2311 eDebugNoNewLine(" (");
2312 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2313 i(program.audioStreams.begin());
2314 i != program.audioStreams.end(); ++i)
2316 if (i != program.audioStreams.begin())
2317 eDebugNoNewLine(", ");
2318 eDebugNoNewLine("%04x", i->pid);
2320 eDebugNoNewLine(")");
2322 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2323 pcrpid = program.pcrPid;
2324 eDebug(", and the text pid is %04x", program.textPid);
2325 tpid = program.textPid;
2330 h.getDecodeDemux(m_decode_demux);
2333 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2335 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2336 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2337 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2338 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2339 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2342 m_teletext_parser = 0;
2343 m_subtitle_parser = 0;
2347 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2354 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2355 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2356 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2358 else // subservice or recording
2360 eServiceReferenceDVB ref;
2361 m_service_handler.getServiceReference(ref);
2362 eServiceReferenceDVB parent = ref.getParentServiceReference();
2367 ePtr<eDVBResourceManager> res_mgr;
2368 if (!eDVBResourceManager::getInstance(res_mgr))
2370 ePtr<iDVBChannelList> db;
2371 if (!res_mgr->getChannelList(db))
2373 ePtr<eDVBService> origService;
2374 if (!db->getService(parent, origService))
2376 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2377 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2383 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2384 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2386 m_decoder->setVideoPID(vpid, vpidtype);
2387 selectAudioStream();
2389 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2390 m_decoder->setSyncPCR(pcrpid);
2392 m_decoder->setSyncPCR(-1);
2394 m_decoder->setTextPID(tpid);
2396 m_teletext_parser->start(program.textPid);
2399 m_decoder->setTrickmode(1);
2402 m_decoder->preroll();
2406 if (vpid > 0 && vpid < 0x2000)
2410 std::string radio_pic;
2411 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2412 m_decoder->setRadioPic(radio_pic);
2415 m_decoder->setAudioChannel(achannel);
2417 /* don't worry about non-existing services, nor pvr services */
2418 if (m_dvb_service && !m_is_pvr)
2420 /* (audio pid will be set in selectAudioTrack */
2421 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2422 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2423 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2424 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2427 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2430 void eDVBServicePlay::loadCuesheet()
2432 std::string filename = m_reference.path + ".cuts";
2434 m_cue_entries.clear();
2436 FILE *f = fopen(filename.c_str(), "rb");
2440 eDebug("loading cuts..");
2443 unsigned long long where;
2446 if (!fread(&where, sizeof(where), 1, f))
2448 if (!fread(&what, sizeof(what), 1, f))
2451 #if BYTE_ORDER == LITTLE_ENDIAN
2452 where = bswap_64(where);
2459 m_cue_entries.insert(cueEntry(where, what));
2462 eDebug("%d entries", m_cue_entries.size());
2464 eDebug("cutfile not found!");
2466 m_cuesheet_changed = 0;
2467 cutlistToCuesheet();
2468 m_event((iPlayableService*)this, evCuesheetChanged);
2471 void eDVBServicePlay::saveCuesheet()
2473 std::string filename = m_reference.path + ".cuts";
2475 FILE *f = fopen(filename.c_str(), "wb");
2479 unsigned long long where;
2482 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2484 #if BYTE_ORDER == BIG_ENDIAN
2487 where = bswap_64(i->where);
2489 what = htonl(i->what);
2490 fwrite(&where, sizeof(where), 1, f);
2491 fwrite(&what, sizeof(what), 1, f);
2497 m_cuesheet_changed = 0;
2500 void eDVBServicePlay::cutlistToCuesheet()
2504 eDebug("no cue sheet");
2509 if (!m_cutlist_enabled)
2511 m_cue->commitSpans();
2512 eDebug("cutlists were disabled");
2516 pts_t in = 0, out = 0, length = 0;
2520 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2524 if (i == m_cue_entries.end())
2527 if (i->what == 0) /* in */
2531 } else if (i->what == 1) /* out */
2533 else /* mark (2) or last play position (3) */
2541 m_cue->addSourceSpan(in, out);
2545 if (i == m_cue_entries.end())
2548 m_cue->commitSpans();
2551 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2553 if (m_subtitle_widget)
2554 disableSubtitles(parent);
2557 int tuplesize = PyTuple_Size(tuple);
2560 if (!PyTuple_Check(tuple))
2566 entry = PyTuple_GET_ITEM(tuple, 0);
2568 if (!PyInt_Check(entry))
2571 type = PyInt_AsLong(entry);
2573 if (type == 1) // teletext subtitles
2575 int page, magazine, pid;
2579 if (!m_teletext_parser)
2581 eDebug("enable teletext subtitles.. no parser !!!");
2585 entry = PyTuple_GET_ITEM(tuple, 1);
2586 if (!PyInt_Check(entry))
2588 pid = PyInt_AsLong(entry);
2590 entry = PyTuple_GET_ITEM(tuple, 2);
2591 if (!PyInt_Check(entry))
2593 page = PyInt_AsLong(entry);
2595 entry = PyTuple_GET_ITEM(tuple, 3);
2596 if (!PyInt_Check(entry))
2598 magazine = PyInt_AsLong(entry);
2600 m_subtitle_widget = new eSubtitleWidget(parent);
2601 m_subtitle_widget->resize(parent->size()); /* full size */
2602 m_teletext_parser->setPageAndMagazine(page, magazine);
2604 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2608 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2609 if (!m_subtitle_parser)
2611 eDebug("enable dvb subtitles.. no parser !!!");
2617 entry = PyTuple_GET_ITEM(tuple, 1);
2618 if (!PyInt_Check(entry))
2620 pid = PyInt_AsLong(entry);
2622 entry = PyTuple_GET_ITEM(tuple, 2);
2623 if (!PyInt_Check(entry))
2625 composition_page_id = PyInt_AsLong(entry);
2627 entry = PyTuple_GET_ITEM(tuple, 3);
2628 if (!PyInt_Check(entry))
2630 ancillary_page_id = PyInt_AsLong(entry);
2632 m_subtitle_widget = new eSubtitleWidget(parent);
2633 m_subtitle_widget->resize(parent->size()); /* full size */
2634 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2636 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2642 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2643 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2644 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2648 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2650 delete m_subtitle_widget;
2651 m_subtitle_widget = 0;
2652 if (m_subtitle_parser)
2654 m_subtitle_parser->stop();
2655 m_dvb_subtitle_pages.clear();
2657 if (m_teletext_parser)
2659 m_teletext_parser->setPageAndMagazine(-1, -1);
2660 m_subtitle_pages.clear();
2663 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2667 PyObject *eDVBServicePlay::getCachedSubtitle()
2671 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2674 unsigned int data = (unsigned int)tmp;
2675 int pid = (data&0xFFFF0000)>>16;
2676 ePyObject tuple = PyTuple_New(4);
2677 eDVBServicePMTHandler::program program;
2678 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2679 if (!h.getProgramInfo(program))
2681 if (program.textPid==pid) // teletext
2682 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2684 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2685 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2686 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2687 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2695 PyObject *eDVBServicePlay::getSubtitleList()
2697 if (!m_teletext_parser)
2700 ePyObject l = PyList_New(0);
2701 std::set<int> added_ttx_pages;
2703 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2704 m_teletext_parser->m_found_subtitle_pages;
2706 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2707 eDVBServicePMTHandler::program program;
2708 if (h.getProgramInfo(program))
2709 eDebug("getting program info failed.");
2712 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2713 it != program.subtitleStreams.end(); ++it)
2715 switch(it->subtitling_type)
2717 case 0x01: // ebu teletext subtitles
2719 int page_number = it->teletext_page_number & 0xFF;
2720 int magazine_number = it->teletext_magazine_number & 7;
2721 int hash = magazine_number << 8 | page_number;
2722 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2724 ePyObject tuple = PyTuple_New(5);
2725 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2726 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2727 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2728 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2729 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2730 PyList_Append(l, tuple);
2732 added_ttx_pages.insert(hash);
2737 case 0x20 ... 0x23: // dvb subtitles
2739 ePyObject tuple = PyTuple_New(5);
2740 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2741 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2742 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2743 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2744 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2745 PyList_Insert(l, 0, tuple);
2753 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2754 it != subs.end(); ++it)
2756 int page_number = it->teletext_page_number & 0xFF;
2757 int magazine_number = it->teletext_magazine_number & 7;
2758 int hash = magazine_number << 8 | page_number;
2759 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2761 ePyObject tuple = PyTuple_New(5);
2762 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2763 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2764 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2765 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2766 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2767 PyList_Append(l, tuple);
2775 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2777 if (m_subtitle_widget)
2781 m_decoder->getPTS(0, pos);
2782 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2783 m_subtitle_pages.push_back(page);
2784 checkSubtitleTiming();
2788 void eDVBServicePlay::checkSubtitleTiming()
2790 eDebug("checkSubtitleTiming");
2791 if (!m_subtitle_widget)
2795 enum { TELETEXT, DVB } type;
2796 eDVBTeletextSubtitlePage page;
2797 eDVBSubtitlePage dvb_page;
2799 if (!m_subtitle_pages.empty())
2801 page = m_subtitle_pages.front();
2803 show_time = page.m_pts;
2805 else if (!m_dvb_subtitle_pages.empty())
2807 dvb_page = m_dvb_subtitle_pages.front();
2809 show_time = dvb_page.m_show_time;
2817 m_decoder->getPTS(0, pos);
2819 eDebug("%lld %lld", pos, show_time);
2820 int diff = show_time - pos;
2823 eDebug("[late (%d ms)]", -diff / 90);
2826 // if (diff > 900000)
2828 // eDebug("[invalid]");
2834 if (type == TELETEXT)
2836 eDebug("display teletext subtitle page %lld", show_time);
2837 m_subtitle_widget->setPage(page);
2838 m_subtitle_pages.pop_front();
2842 eDebug("display dvb subtitle Page %lld", show_time);
2843 m_subtitle_widget->setPage(dvb_page);
2844 m_dvb_subtitle_pages.pop_front();
2848 eDebug("start subtitle delay %d", diff / 90);
2849 m_subtitle_sync_timer.start(diff / 90, 1);
2855 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2857 if (m_subtitle_widget)
2861 m_decoder->getPTS(0, pos);
2862 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2863 m_dvb_subtitle_pages.push_back(p);
2864 checkSubtitleTiming();
2868 int eDVBServicePlay::getAC3Delay()
2871 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2873 return m_decoder->getAC3Delay();
2878 int eDVBServicePlay::getPCMDelay()
2881 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2883 return m_decoder->getPCMDelay();
2888 void eDVBServicePlay::setAC3Delay(int delay)
2891 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2893 m_decoder->setAC3Delay(delay);
2896 void eDVBServicePlay::setPCMDelay(int delay)
2899 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2901 m_decoder->setPCMDelay(delay);
2904 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2906 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2907 m_event((iPlayableService*)this, evVideoSizeChanged);
2910 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2916 PyObject *eDVBServicePlay::getStreamingData()
2918 eDVBServicePMTHandler::program program;
2919 if (m_service_handler.getProgramInfo(program))
2925 PyObject *r = program.createPythonObject();
2926 ePtr<iDVBDemux> demux;
2927 if (!m_service_handler.getDataDemux(demux))
2930 demux->getCADemuxID(demux_id);
2932 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
2939 DEFINE_REF(eDVBServicePlay)
2941 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2945 case iServiceInformation::sTransponderData:
2946 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2950 return iStaticServiceInformation::getInfoObject(ref, w);
2953 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");