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/base/nconfig.h> // access to python config
10 #include <lib/dvb/dvb.h>
11 #include <lib/dvb/db.h>
12 #include <lib/dvb/decoder.h>
14 #include <lib/components/file_eraser.h>
15 #include <lib/service/servicedvbrecord.h>
16 #include <lib/service/event.h>
17 #include <lib/dvb/metaparser.h>
18 #include <lib/dvb/tstools.h>
19 #include <lib/python/python.h>
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);
1351 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1353 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1355 if (!m_decode_demux)
1358 ePtr<iDVBPVRChannel> pvr_channel;
1360 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1365 /* HACK until we have skip-AP api */
1366 if ((to > 0) && (to < 100))
1374 m_cue->seekTo(mode, to);
1378 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1380 ePtr<iDVBPVRChannel> pvr_channel;
1382 if (!m_decode_demux)
1385 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1390 /* if there is a decoder, use audio or video PTS */
1393 r = m_decoder->getPTS(0, pos);
1399 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1402 RESULT eDVBServicePlay::setTrickmode(int trick)
1405 m_decoder->setTrickmode(trick);
1409 RESULT eDVBServicePlay::isCurrentlySeekable()
1411 return m_is_pvr || m_timeshift_active;
1414 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1420 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1426 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1432 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1438 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1444 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1447 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1448 (m_timeshift_enabled || !m_is_pvr))
1450 if (!m_timeshift_enabled)
1452 /* we need enough diskspace */
1454 if (statfs(TSPATH "/.", &fs) < 0)
1456 eDebug("statfs failed!");
1460 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1462 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1472 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1483 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1489 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1495 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1501 RESULT eDVBServicePlay::getName(std::string &name)
1505 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1506 return i->getName(m_reference, name);
1510 m_dvb_service->getName(m_reference, name);
1514 else if (!m_reference.name.empty())
1515 eStaticServiceDVBInformation().getName(m_reference, name);
1517 name = "DVB service";
1521 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1523 return m_event_handler.getEvent(evt, nownext);
1526 int eDVBServicePlay::getInfo(int w)
1528 eDVBServicePMTHandler::program program;
1531 return resIsPyObject;
1533 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1535 int no_program_info = 0;
1537 if (h.getProgramInfo(program))
1538 no_program_info = 1;
1542 #if HAVE_DVB_API_VERSION >= 3
1544 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1545 return m_videoEventData.height;
1548 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1549 return m_videoEventData.width;
1552 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1555 #if HAVE_DVB_API_VERSION >= 3
1556 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1557 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1560 #warning "FIXMEE implement sAspect for old DVB API"
1562 if (no_program_info)
1564 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1566 ePtr<eServiceEvent> evt;
1567 if (!m_event_handler.getEvent(evt, 0))
1569 ePtr<eComponentData> data;
1570 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1572 if ( data->getStreamContent() == 1 )
1574 switch(data->getComponentType())
1577 case 1: // 4:3 SD PAL
1579 case 3: // 16:9 SD PAL
1580 case 4: // > 16:9 PAL
1581 case 5: // 4:3 SD NTSC
1583 case 7: // 16:9 SD NTSC
1584 case 8: // > 16:9 NTSC
1587 case 9: // 4:3 HD PAL
1589 case 0xB: // 16:9 HD PAL
1590 case 0xC: // > 16:9 HD PAL
1591 case 0xD: // 4:3 HD NTSC
1593 case 0xF: // 16:9 HD NTSC
1594 case 0x10: // > 16:9 HD PAL
1595 return data->getComponentType();
1602 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1603 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1604 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1605 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1606 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1607 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1608 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1609 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1610 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1611 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1612 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1613 case sProvider: if (!m_dvb_service) return -1; return -2;
1614 case sServiceref: return resIsString;
1615 case sDVBState: return m_tune_state;
1621 std::string eDVBServicePlay::getInfoString(int w)
1626 if (!m_dvb_service) return "";
1627 return m_dvb_service->m_provider_name;
1629 return m_reference.toString();
1633 return iServiceInformation::getInfoString(w);
1636 PyObject *eDVBServicePlay::getInfoObject(int w)
1641 return m_service_handler.getCaIds();
1642 case sTransponderData:
1643 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1647 return iServiceInformation::getInfoObject(w);
1650 int eDVBServicePlay::getNumberOfTracks()
1652 eDVBServicePMTHandler::program program;
1653 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1654 if (h.getProgramInfo(program))
1656 return program.audioStreams.size();
1659 int eDVBServicePlay::getCurrentTrack()
1661 eDVBServicePMTHandler::program program;
1662 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1663 if (h.getProgramInfo(program))
1666 int max = program.audioStreams.size();
1669 for (i = 0; i < max; ++i)
1670 if (program.audioStreams[i].pid == m_current_audio_pid)
1676 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1678 int ret = selectAudioStream(i);
1680 if (m_decoder->start())
1686 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1688 eDVBServicePMTHandler::program program;
1689 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1691 if (h.getProgramInfo(program))
1694 if (i >= program.audioStreams.size())
1697 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1698 info.m_description = "MPEG";
1699 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1700 info.m_description = "AC3";
1701 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1702 info.m_description = "AAC";
1703 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1704 info.m_description = "DTS";
1706 info.m_description = "???";
1708 if (program.audioStreams[i].component_tag != -1)
1710 ePtr<eServiceEvent> evt;
1711 if (!m_event_handler.getEvent(evt, 0))
1713 ePtr<eComponentData> data;
1714 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1715 info.m_language = data->getText();
1719 if (info.m_language.empty())
1720 info.m_language = program.audioStreams[i].language_code;
1725 int eDVBServicePlay::selectAudioStream(int i)
1727 eDVBServicePMTHandler::program program;
1728 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1730 if (h.getProgramInfo(program))
1733 if ((unsigned int)i >= program.audioStreams.size())
1741 stream = program.defaultAudioStream;
1743 m_current_audio_pid = program.audioStreams[stream].pid;
1745 if (m_decoder->setAudioPID(program.audioStreams[stream].pid, program.audioStreams[stream].type))
1747 eDebug("set audio pid failed");
1752 m_rds_decoder->start(program.audioStreams[stream].pid);
1754 /* store new pid as default only when:
1755 a.) we have an entry in the service db for the current service,
1756 b.) we are not playing back something,
1757 c.) we are not selecting the default entry. (we wouldn't change
1758 anything in the best case, or destroy the default setting in
1759 case the real default is not yet available.)
1761 if (m_dvb_service && !m_is_pvr && (i != -1))
1763 if (program.audioStreams[stream].type == eDVBAudio::aMPEG)
1765 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[stream].pid);
1766 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1770 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1771 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[stream].pid);
1775 h.resetCachedProgram();
1780 int eDVBServicePlay::getCurrentChannel()
1782 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1785 RESULT eDVBServicePlay::selectChannel(int i)
1787 if (i < LEFT || i > RIGHT || i == STEREO)
1790 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1792 m_decoder->setAudioChannel(i);
1796 std::string eDVBServicePlay::getText(int x)
1802 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1804 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1809 void eDVBServicePlay::rdsDecoderEvent(int what)
1813 case eDVBRdsDecoder::RadioTextChanged:
1814 m_event((iPlayableService*)this, evUpdatedRadioText);
1816 case eDVBRdsDecoder::RtpTextChanged:
1817 m_event((iPlayableService*)this, evUpdatedRtpText);
1819 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1820 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1822 case eDVBRdsDecoder::RecvRassSlidePic:
1823 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1828 void eDVBServicePlay::showRassSlidePicture()
1834 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1835 if (rass_slide_pic.length())
1836 m_decoder->showSinglePic(rass_slide_pic.c_str());
1838 eDebug("empty filename for rass slide picture received!!");
1841 eDebug("no MPEG Decoder to show iframes avail");
1844 eDebug("showRassSlidePicture called.. but not decoder");
1847 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1853 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1854 if (rass_interactive_pic.length())
1855 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1857 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1860 eDebug("no MPEG Decoder to show iframes avail");
1863 eDebug("showRassInteractivePic called.. but not decoder");
1866 ePyObject eDVBServicePlay::getRassInteractiveMask()
1869 return m_rds_decoder->getRassPictureMask();
1873 int eDVBServiceBase::getFrontendInfo(int w)
1875 eUsePtr<iDVBChannel> channel;
1876 if(m_service_handler.getChannel(channel))
1878 ePtr<iDVBFrontend> fe;
1879 if(channel->getFrontend(fe))
1881 return fe->readFrontendData(w);
1884 PyObject *eDVBServiceBase::getFrontendData()
1886 ePyObject ret = PyDict_New();
1889 eUsePtr<iDVBChannel> channel;
1890 if(!m_service_handler.getChannel(channel))
1892 ePtr<iDVBFrontend> fe;
1893 if(!channel->getFrontend(fe))
1894 fe->getFrontendData(ret);
1902 PyObject *eDVBServiceBase::getFrontendStatus()
1904 ePyObject ret = PyDict_New();
1907 eUsePtr<iDVBChannel> channel;
1908 if(!m_service_handler.getChannel(channel))
1910 ePtr<iDVBFrontend> fe;
1911 if(!channel->getFrontend(fe))
1912 fe->getFrontendStatus(ret);
1920 PyObject *eDVBServiceBase::getTransponderData(bool original)
1922 ePyObject ret = PyDict_New();
1925 eUsePtr<iDVBChannel> channel;
1926 if(!m_service_handler.getChannel(channel))
1928 ePtr<iDVBFrontend> fe;
1929 if(!channel->getFrontend(fe))
1931 fe->getTransponderData(ret, original);
1932 ePtr<iDVBFrontendParameters> feparm;
1933 channel->getCurrentFrontendParameters(feparm);
1936 eDVBFrontendParametersSatellite osat;
1937 if (!feparm->getDVBS(osat))
1939 void PutToDict(ePyObject &, const char*, long);
1940 void PutToDict(ePyObject &, const char*, const char*);
1941 PutToDict(ret, "orbital_position", osat.orbital_position);
1942 const char *tmp = "UNKNOWN";
1943 switch(osat.polarisation)
1945 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1946 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1947 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1948 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1951 PutToDict(ret, "polarization", tmp);
1962 PyObject *eDVBServiceBase::getAll(bool original)
1964 ePyObject ret = getTransponderData(original);
1967 eUsePtr<iDVBChannel> channel;
1968 if(!m_service_handler.getChannel(channel))
1970 ePtr<iDVBFrontend> fe;
1971 if(!channel->getFrontend(fe))
1973 fe->getFrontendData(ret);
1974 fe->getFrontendStatus(ret);
1981 int eDVBServicePlay::getNumberOfSubservices()
1983 ePtr<eServiceEvent> evt;
1984 if (!m_event_handler.getEvent(evt, 0))
1985 return evt->getNumOfLinkageServices();
1989 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1991 ePtr<eServiceEvent> evt;
1992 if (!m_event_handler.getEvent(evt, 0))
1994 if (!evt->getLinkageService(sub, m_reference, n))
1997 sub.type=eServiceReference::idInvalid;
2001 RESULT eDVBServicePlay::startTimeshift()
2003 ePtr<iDVBDemux> demux;
2005 eDebug("Start timeshift!");
2007 if (m_timeshift_enabled)
2010 /* start recording with the data demux. */
2011 if (m_service_handler.getDataDemux(demux))
2014 demux->createTSRecorder(m_record);
2018 char templ[]=TSPATH "/timeshift.XXXXXX";
2019 m_timeshift_fd = mkstemp(templ);
2020 m_timeshift_file = templ;
2022 eDebug("recording to %s", templ);
2024 if (m_timeshift_fd < 0)
2030 m_record->setTargetFD(m_timeshift_fd);
2032 m_timeshift_enabled = 1;
2034 updateTimeshiftPids();
2040 RESULT eDVBServicePlay::stopTimeshift()
2042 if (!m_timeshift_enabled)
2047 m_timeshift_enabled = 0;
2052 close(m_timeshift_fd);
2053 eDebug("remove timeshift file");
2054 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2059 int eDVBServicePlay::isTimeshiftActive()
2061 return m_timeshift_enabled && m_timeshift_active;
2064 RESULT eDVBServicePlay::activateTimeshift()
2066 if (!m_timeshift_enabled)
2069 if (!m_timeshift_active)
2071 switchToTimeshift();
2078 PyObject *eDVBServicePlay::getCutList()
2080 ePyObject list = PyList_New(0);
2082 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2084 ePyObject tuple = PyTuple_New(2);
2085 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2086 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2087 PyList_Append(list, tuple);
2094 void eDVBServicePlay::setCutList(ePyObject list)
2096 if (!PyList_Check(list))
2098 int size = PyList_Size(list);
2101 m_cue_entries.clear();
2103 for (i=0; i<size; ++i)
2105 ePyObject tuple = PyList_GET_ITEM(list, i);
2106 if (!PyTuple_Check(tuple))
2108 eDebug("non-tuple in cutlist");
2111 if (PyTuple_Size(tuple) != 2)
2113 eDebug("cutlist entries need to be a 2-tuple");
2116 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2117 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2119 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2122 pts_t pts = PyLong_AsLongLong(ppts);
2123 int type = PyInt_AsLong(ptype);
2124 m_cue_entries.insert(cueEntry(pts, type));
2125 eDebug("adding %08llx, %d", pts, type);
2127 m_cuesheet_changed = 1;
2129 cutlistToCuesheet();
2130 m_event((iPlayableService*)this, evCuesheetChanged);
2133 void eDVBServicePlay::setCutListEnable(int enable)
2135 m_cutlist_enabled = enable;
2136 cutlistToCuesheet();
2139 void eDVBServicePlay::updateTimeshiftPids()
2144 eDVBServicePMTHandler::program program;
2145 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2147 if (h.getProgramInfo(program))
2151 std::set<int> pids_to_record;
2152 pids_to_record.insert(0); // PAT
2153 if (program.pmtPid != -1)
2154 pids_to_record.insert(program.pmtPid); // PMT
2156 if (program.textPid != -1)
2157 pids_to_record.insert(program.textPid); // Videotext
2159 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2160 i(program.videoStreams.begin());
2161 i != program.videoStreams.end(); ++i)
2162 pids_to_record.insert(i->pid);
2164 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2165 i(program.audioStreams.begin());
2166 i != program.audioStreams.end(); ++i)
2167 pids_to_record.insert(i->pid);
2169 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2170 i(program.subtitleStreams.begin());
2171 i != program.subtitleStreams.end(); ++i)
2172 pids_to_record.insert(i->pid);
2174 std::set<int> new_pids, obsolete_pids;
2176 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2177 m_pids_active.begin(), m_pids_active.end(),
2178 std::inserter(new_pids, new_pids.begin()));
2180 std::set_difference(
2181 m_pids_active.begin(), m_pids_active.end(),
2182 pids_to_record.begin(), pids_to_record.end(),
2183 std::inserter(new_pids, new_pids.begin())
2186 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2187 m_record->addPID(*i);
2189 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2190 m_record->removePID(*i);
2194 void eDVBServicePlay::switchToLive()
2196 if (!m_timeshift_active)
2202 m_teletext_parser = 0;
2204 m_subtitle_parser = 0;
2205 m_new_dvb_subtitle_page_connection = 0;
2206 m_new_subtitle_page_connection = 0;
2207 m_rds_decoder_event_connection = 0;
2208 m_video_event_connection = 0;
2210 /* free the timeshift service handler, we need the resources */
2211 m_service_handler_timeshift.free();
2212 m_timeshift_active = 0;
2214 m_event((iPlayableService*)this, evSeekableStatusChanged);
2219 void eDVBServicePlay::switchToTimeshift()
2221 if (m_timeshift_active)
2226 m_teletext_parser = 0;
2228 m_subtitle_parser = 0;
2229 m_new_subtitle_page_connection = 0;
2230 m_new_dvb_subtitle_page_connection = 0;
2231 m_rds_decoder_event_connection = 0;
2232 m_video_event_connection = 0;
2234 m_timeshift_active = 1;
2236 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2237 r.path = m_timeshift_file;
2239 m_cue = new eCueSheet();
2240 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2242 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2244 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2246 m_event((iPlayableService*)this, evSeekableStatusChanged);
2249 void eDVBServicePlay::updateDecoder()
2251 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2253 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2255 bool defaultac3=false;
2256 std::string default_ac3;
2258 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2259 defaultac3 = default_ac3 == "True";
2261 eDVBServicePMTHandler::program program;
2262 if (h.getProgramInfo(program))
2263 eDebug("getting program info failed.");
2266 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2267 if (!program.videoStreams.empty())
2269 eDebugNoNewLine(" (");
2270 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2271 i(program.videoStreams.begin());
2272 i != program.videoStreams.end(); ++i)
2279 if (i != program.videoStreams.begin())
2280 eDebugNoNewLine(", ");
2281 eDebugNoNewLine("%04x", i->pid);
2283 eDebugNoNewLine(")");
2285 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2286 if (!program.audioStreams.empty())
2288 eDebugNoNewLine(" (");
2289 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2290 i(program.audioStreams.begin());
2291 i != program.audioStreams.end(); ++i)
2293 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2295 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2301 if (i != program.audioStreams.begin())
2302 eDebugNoNewLine(", ");
2303 eDebugNoNewLine("%04x", i->pid);
2305 eDebugNoNewLine(")");
2307 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2308 pcrpid = program.pcrPid;
2309 eDebug(", and the text pid is %04x", program.textPid);
2310 tpid = program.textPid;
2315 h.getDecodeDemux(m_decode_demux);
2318 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2320 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2321 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2322 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2323 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2324 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2327 m_teletext_parser = 0;
2328 m_subtitle_parser = 0;
2332 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2339 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2340 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2341 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2343 else // subservice or recording
2345 eServiceReferenceDVB ref;
2346 m_service_handler.getServiceReference(ref);
2347 eServiceReferenceDVB parent = ref.getParentServiceReference();
2352 ePtr<eDVBResourceManager> res_mgr;
2353 if (!eDVBResourceManager::getInstance(res_mgr))
2355 ePtr<iDVBChannelList> db;
2356 if (!res_mgr->getChannelList(db))
2358 ePtr<eDVBService> origService;
2359 if (!db->getService(parent, origService))
2361 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2362 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2368 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2369 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2371 m_decoder->setVideoPID(vpid, vpidtype);
2372 selectAudioStream();
2374 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2376 m_decoder->setSyncPCR(pcrpid);
2379 ePtr<iDVBDemux> data_demux;
2380 if (!h.getDataDemux(data_demux))
2382 m_rds_decoder = new eDVBRdsDecoder(data_demux);
2383 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
2384 m_rds_decoder->start(apid);
2389 m_decoder->setSyncPCR(-1);
2391 m_decoder->setTextPID(tpid);
2393 m_teletext_parser->start(program.textPid);
2396 m_decoder->setTrickmode(1);
2399 m_decoder->preroll();
2403 if (vpid > 0 && vpid < 0x2000)
2407 std::string radio_pic;
2408 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2409 m_decoder->setRadioPic(radio_pic);
2412 m_decoder->setAudioChannel(achannel);
2414 // how we can do this better?
2415 // update cache pid when the user changed the audio track or video track
2416 // TODO handling of difference audio types.. default audio types..
2418 /* don't worry about non-existing services, nor pvr services */
2419 if (m_dvb_service && !m_is_pvr)
2421 if (apidtype == eDVBAudio::aMPEG)
2423 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2424 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2428 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2429 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2431 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2432 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2433 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2434 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2437 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2440 void eDVBServicePlay::loadCuesheet()
2442 std::string filename = m_reference.path + ".cuts";
2444 m_cue_entries.clear();
2446 FILE *f = fopen(filename.c_str(), "rb");
2450 eDebug("loading cuts..");
2453 unsigned long long where;
2456 if (!fread(&where, sizeof(where), 1, f))
2458 if (!fread(&what, sizeof(what), 1, f))
2461 #if BYTE_ORDER == LITTLE_ENDIAN
2462 where = bswap_64(where);
2469 m_cue_entries.insert(cueEntry(where, what));
2472 eDebug("%d entries", m_cue_entries.size());
2474 eDebug("cutfile not found!");
2476 m_cuesheet_changed = 0;
2477 cutlistToCuesheet();
2478 m_event((iPlayableService*)this, evCuesheetChanged);
2481 void eDVBServicePlay::saveCuesheet()
2483 std::string filename = m_reference.path + ".cuts";
2485 FILE *f = fopen(filename.c_str(), "wb");
2489 unsigned long long where;
2492 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2494 #if BYTE_ORDER == BIG_ENDIAN
2497 where = bswap_64(i->where);
2499 what = htonl(i->what);
2500 fwrite(&where, sizeof(where), 1, f);
2501 fwrite(&what, sizeof(what), 1, f);
2507 m_cuesheet_changed = 0;
2510 void eDVBServicePlay::cutlistToCuesheet()
2514 eDebug("no cue sheet");
2519 if (!m_cutlist_enabled)
2521 m_cue->commitSpans();
2522 eDebug("cutlists were disabled");
2526 pts_t in = 0, out = 0, length = 0;
2530 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2534 if (i == m_cue_entries.end())
2537 if (i->what == 0) /* in */
2541 } else if (i->what == 1) /* out */
2543 else /* mark (2) or last play position (3) */
2551 m_cue->addSourceSpan(in, out);
2555 if (i == m_cue_entries.end())
2558 m_cue->commitSpans();
2561 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2563 if (m_subtitle_widget)
2564 disableSubtitles(parent);
2567 int tuplesize = PyTuple_Size(tuple);
2570 if (!PyTuple_Check(tuple))
2576 entry = PyTuple_GET_ITEM(tuple, 0);
2578 if (!PyInt_Check(entry))
2581 type = PyInt_AsLong(entry);
2583 if (type == 1) // teletext subtitles
2585 int page, magazine, pid;
2589 if (!m_teletext_parser)
2591 eDebug("enable teletext subtitles.. no parser !!!");
2595 entry = PyTuple_GET_ITEM(tuple, 1);
2596 if (!PyInt_Check(entry))
2598 pid = PyInt_AsLong(entry);
2600 entry = PyTuple_GET_ITEM(tuple, 2);
2601 if (!PyInt_Check(entry))
2603 page = PyInt_AsLong(entry);
2605 entry = PyTuple_GET_ITEM(tuple, 3);
2606 if (!PyInt_Check(entry))
2608 magazine = PyInt_AsLong(entry);
2610 m_subtitle_widget = new eSubtitleWidget(parent);
2611 m_subtitle_widget->resize(parent->size()); /* full size */
2612 m_teletext_parser->setPageAndMagazine(page, magazine);
2614 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2618 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2619 if (!m_subtitle_parser)
2621 eDebug("enable dvb subtitles.. no parser !!!");
2627 entry = PyTuple_GET_ITEM(tuple, 1);
2628 if (!PyInt_Check(entry))
2630 pid = PyInt_AsLong(entry);
2632 entry = PyTuple_GET_ITEM(tuple, 2);
2633 if (!PyInt_Check(entry))
2635 composition_page_id = PyInt_AsLong(entry);
2637 entry = PyTuple_GET_ITEM(tuple, 3);
2638 if (!PyInt_Check(entry))
2640 ancillary_page_id = PyInt_AsLong(entry);
2642 m_subtitle_widget = new eSubtitleWidget(parent);
2643 m_subtitle_widget->resize(parent->size()); /* full size */
2644 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2646 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2652 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2653 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2654 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2658 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2660 delete m_subtitle_widget;
2661 m_subtitle_widget = 0;
2662 if (m_subtitle_parser)
2664 m_subtitle_parser->stop();
2665 m_dvb_subtitle_pages.clear();
2667 if (m_teletext_parser)
2669 m_teletext_parser->setPageAndMagazine(-1, -1);
2670 m_subtitle_pages.clear();
2673 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2677 PyObject *eDVBServicePlay::getCachedSubtitle()
2681 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2684 unsigned int data = (unsigned int)tmp;
2685 int pid = (data&0xFFFF0000)>>16;
2686 ePyObject tuple = PyTuple_New(4);
2687 eDVBServicePMTHandler::program program;
2688 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2689 if (!h.getProgramInfo(program))
2691 if (program.textPid==pid) // teletext
2692 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2694 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2695 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2696 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2697 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2705 PyObject *eDVBServicePlay::getSubtitleList()
2707 if (!m_teletext_parser)
2710 ePyObject l = PyList_New(0);
2711 std::set<int> added_ttx_pages;
2713 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2714 m_teletext_parser->m_found_subtitle_pages;
2716 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2717 eDVBServicePMTHandler::program program;
2718 if (h.getProgramInfo(program))
2719 eDebug("getting program info failed.");
2722 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2723 it != program.subtitleStreams.end(); ++it)
2725 switch(it->subtitling_type)
2727 case 0x01: // ebu teletext subtitles
2729 int page_number = it->teletext_page_number & 0xFF;
2730 int magazine_number = it->teletext_magazine_number & 7;
2731 int hash = magazine_number << 8 | page_number;
2732 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2734 ePyObject tuple = PyTuple_New(5);
2735 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2736 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2737 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2738 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2739 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2740 PyList_Append(l, tuple);
2742 added_ttx_pages.insert(hash);
2747 case 0x20 ... 0x23: // dvb subtitles
2749 ePyObject tuple = PyTuple_New(5);
2750 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2751 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2752 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2753 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2754 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2755 PyList_Insert(l, 0, tuple);
2763 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2764 it != subs.end(); ++it)
2766 int page_number = it->teletext_page_number & 0xFF;
2767 int magazine_number = it->teletext_magazine_number & 7;
2768 int hash = magazine_number << 8 | page_number;
2769 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2771 ePyObject tuple = PyTuple_New(5);
2772 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2773 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2774 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2775 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2776 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2777 PyList_Append(l, tuple);
2785 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2787 if (m_subtitle_widget)
2789 m_subtitle_pages.push_back(page);
2790 checkSubtitleTiming();
2794 void eDVBServicePlay::checkSubtitleTiming()
2796 // eDebug("checkSubtitleTiming");
2797 if (!m_subtitle_widget)
2801 enum { TELETEXT, DVB } type;
2802 eDVBTeletextSubtitlePage page;
2803 eDVBSubtitlePage dvb_page;
2805 if (!m_subtitle_pages.empty())
2807 page = m_subtitle_pages.front();
2809 show_time = page.m_pts;
2811 else if (!m_dvb_subtitle_pages.empty())
2813 dvb_page = m_dvb_subtitle_pages.front();
2815 show_time = dvb_page.m_show_time;
2823 m_decoder->getPTS(0, pos);
2825 // eDebug("%lld %lld", pos, show_time);
2826 int diff = show_time - pos;
2829 eDebug("[late (%d ms)]", -diff / 90);
2834 eDebug("[invalid]");
2840 if (type == TELETEXT)
2842 eDebug("display teletext subtitle page");
2843 m_subtitle_widget->setPage(page);
2844 m_subtitle_pages.pop_front();
2848 eDebug("display dvb subtitle Page");
2849 m_subtitle_widget->setPage(dvb_page);
2850 m_dvb_subtitle_pages.pop_front();
2854 // eDebug("start subtitle delay %d", diff / 90);
2855 m_subtitle_sync_timer.start(diff / 90, 1);
2861 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2863 if (m_subtitle_widget)
2865 m_dvb_subtitle_pages.push_back(p);
2866 checkSubtitleTiming();
2870 int eDVBServicePlay::getAC3Delay()
2873 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2875 return m_decoder->getAC3Delay();
2880 int eDVBServicePlay::getPCMDelay()
2883 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2885 return m_decoder->getPCMDelay();
2890 void eDVBServicePlay::setAC3Delay(int delay)
2893 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2895 m_decoder->setAC3Delay(delay);
2898 void eDVBServicePlay::setPCMDelay(int delay)
2901 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2903 m_decoder->setPCMDelay(delay);
2906 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2908 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2909 m_event((iPlayableService*)this, evVideoSizeChanged);
2912 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2918 PyObject *eDVBServicePlay::getStreamingData()
2920 eDVBServicePMTHandler::program program;
2921 if (m_service_handler.getProgramInfo(program))
2927 PyObject *r = program.createPythonObject();
2928 ePtr<iDVBDemux> demux;
2929 if (!m_service_handler.getDataDemux(demux))
2932 demux->getCADemuxID(demux_id);
2934 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
2941 DEFINE_REF(eDVBServicePlay)
2943 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2947 case iServiceInformation::sTransponderData:
2948 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2952 return iStaticServiceInformation::getInfoObject(ref, w);
2955 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");