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))
69 // just show short name
70 unsigned int pos = name.find("\xc2\x86");
71 if ( pos != std::string::npos )
73 pos = name.find("\xc2\x87");
74 if ( pos != std::string::npos )
90 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
95 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
97 ePtr<eDVBResourceManager> res_mgr;
98 if ( eDVBResourceManager::getInstance( res_mgr ) )
99 eDebug("isPlayable... no res manager!!");
102 eDVBChannelID chid, chid_ignore;
103 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
104 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
105 return res_mgr->canAllocateChannel(chid, chid_ignore);
110 static void PutToDict(ePyObject &dict, const char*key, long value)
112 ePyObject item = PyString_FromFormat("%d", value);
115 if (PyDict_SetItemString(dict, key, item))
116 eDebug("put %s to dict failed", key);
120 eDebug("could not create PyObject for %s", key);
123 extern void PutToDict(ePyObject &dict, const char*key, const char *value);
125 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
128 PutToDict(dict, "type", "Satellite");
129 PutToDict(dict, "frequency", feparm.frequency);
130 PutToDict(dict, "symbolrate", feparm.symbol_rate);
131 PutToDict(dict, "orbital position", feparm.orbital_position);
132 switch (feparm.inversion)
134 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
135 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
137 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
139 PutToDict(dict, "inversion", tmp);
142 case eDVBFrontendParametersSatellite::FEC::fNone: tmp="NONE"; break;
143 case eDVBFrontendParametersSatellite::FEC::f1_2: tmp="1/2"; break;
144 case eDVBFrontendParametersSatellite::FEC::f2_3: tmp="2/3"; break;
145 case eDVBFrontendParametersSatellite::FEC::f3_4: tmp="3/4"; break;
146 case eDVBFrontendParametersSatellite::FEC::f5_6: tmp="5/6"; break;
147 case eDVBFrontendParametersSatellite::FEC::f7_8: tmp="7/8"; break;
148 case eDVBFrontendParametersSatellite::FEC::f3_5: tmp="3/5"; break;
149 case eDVBFrontendParametersSatellite::FEC::f4_5: tmp="4/5"; break;
150 case eDVBFrontendParametersSatellite::FEC::f8_9: tmp="8/9"; break;
151 case eDVBFrontendParametersSatellite::FEC::f9_10: tmp="9/10"; break;
153 case eDVBFrontendParametersSatellite::FEC::fAuto: tmp="AUTO"; break;
155 PutToDict(dict, "fec inner", tmp);
156 switch (feparm.modulation)
158 case eDVBFrontendParametersSatellite::Modulation::Auto: tmp="AUTO"; break;
159 case eDVBFrontendParametersSatellite::Modulation::QPSK: tmp="QPSK"; break;
160 case eDVBFrontendParametersSatellite::Modulation::M8PSK: tmp="8PSK"; break;
161 case eDVBFrontendParametersSatellite::Modulation::QAM_16: tmp="QAM16"; break;
163 PutToDict(dict, "modulation", tmp);
164 switch(feparm.polarisation)
166 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
167 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
168 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR LEFT"; break;
170 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR RIGHT"; break;
172 PutToDict(dict, "polarization", tmp);
173 switch(feparm.system)
176 case eDVBFrontendParametersSatellite::System::DVB_S: tmp="DVB-S"; break;
177 case eDVBFrontendParametersSatellite::System::DVB_S2:
178 switch(feparm.roll_off)
180 case eDVBFrontendParametersSatellite::RollOff::alpha_0_35: tmp="0.35"; break;
181 case eDVBFrontendParametersSatellite::RollOff::alpha_0_25: tmp="0.25"; break;
182 case eDVBFrontendParametersSatellite::RollOff::alpha_0_20: tmp="0.20"; break;
184 case eDVBFrontendParametersSatellite::RollOff::alpha_auto: tmp="AUTO"; break;
186 PutToDict(dict, "roll off", tmp);
190 PutToDict(dict, "system", tmp);
193 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
195 PutToDict(dict, "type", "Terrestrial");
196 PutToDict(dict, "frequency", feparm.frequency);
198 switch (feparm.bandwidth)
200 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz: tmp="8 MHz"; break;
201 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz: tmp="7 MHz"; break;
202 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz: tmp="6 MHz"; break;
204 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto: tmp="AUTO"; break;
206 PutToDict(dict, "bandwidth", tmp);
207 switch (feparm.code_rate_LP)
209 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
210 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
211 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
212 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
213 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
215 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
217 PutToDict(dict, "code rate lp", tmp);
218 switch (feparm.code_rate_HP)
220 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
221 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
222 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
223 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
224 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
226 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
228 PutToDict(dict, "code rate hp", tmp);
229 switch (feparm.modulation)
231 case eDVBFrontendParametersTerrestrial::Modulation::QPSK: tmp="QPSK"; break;
232 case eDVBFrontendParametersTerrestrial::Modulation::QAM16: tmp="QAM16"; break;
233 case eDVBFrontendParametersTerrestrial::Modulation::QAM64: tmp="QAM64"; break;
235 case eDVBFrontendParametersTerrestrial::Modulation::Auto: tmp="AUTO"; break;
237 PutToDict(dict, "constellation", tmp);
238 switch (feparm.transmission_mode)
240 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k: tmp="2k"; break;
241 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k: tmp="8k"; break;
243 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto: tmp="AUTO"; break;
245 PutToDict(dict, "transmission mode", tmp);
246 switch (feparm.guard_interval)
248 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32: tmp="1/32"; break;
249 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16: tmp="1/16"; break;
250 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8: tmp="1/8"; break;
251 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4: tmp="1/4"; break;
253 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto: tmp="AUTO"; break;
255 PutToDict(dict, "guard interval", tmp);
256 switch (feparm.hierarchy)
258 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone: tmp="NONE"; break;
259 case eDVBFrontendParametersTerrestrial::Hierarchy::H1: tmp="1"; break;
260 case eDVBFrontendParametersTerrestrial::Hierarchy::H2: tmp="2"; break;
261 case eDVBFrontendParametersTerrestrial::Hierarchy::H4: tmp="4"; break;
263 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto: tmp="AUTO"; break;
265 PutToDict(dict, "hierarchy", tmp);
266 switch (feparm.inversion)
268 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
269 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
271 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
273 PutToDict(dict, "inversion", tmp);
276 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
279 PutToDict(dict, "type", "Cable");
280 PutToDict(dict, "frequency", feparm.frequency);
281 PutToDict(dict, "symbolrate", feparm.symbol_rate);
282 switch (feparm.modulation)
284 case eDVBFrontendParametersCable::Modulation::QAM16: tmp="QAM16"; break;
285 case eDVBFrontendParametersCable::Modulation::QAM32: tmp="QAM32"; break;
286 case eDVBFrontendParametersCable::Modulation::QAM64: tmp="QAM64"; break;
287 case eDVBFrontendParametersCable::Modulation::QAM128: tmp="QAM128"; break;
288 case eDVBFrontendParametersCable::Modulation::QAM256: tmp="QAM256"; break;
290 case eDVBFrontendParametersCable::Modulation::Auto: tmp="AUTO"; break;
292 PutToDict(dict, "modulation", tmp);
293 switch (feparm.inversion)
295 case eDVBFrontendParametersCable::Inversion::On: tmp="ON"; break;
296 case eDVBFrontendParametersCable::Inversion::Off: tmp="OFF"; break;
298 case eDVBFrontendParametersCable::Inversion::Unknown: tmp="AUTO"; break;
300 PutToDict(dict, "inversion", tmp);
301 switch (feparm.fec_inner)
303 case eDVBFrontendParametersCable::FEC::fNone: tmp="NONE"; break;
304 case eDVBFrontendParametersCable::FEC::f1_2: tmp="1/2"; break;
305 case eDVBFrontendParametersCable::FEC::f2_3: tmp="2/3"; break;
306 case eDVBFrontendParametersCable::FEC::f3_4: tmp="3/4"; break;
307 case eDVBFrontendParametersCable::FEC::f5_6: tmp="5/6"; break;
308 case eDVBFrontendParametersCable::FEC::f7_8: tmp="7/8"; break;
309 case eDVBFrontendParametersCable::FEC::f8_9: tmp="8/9"; break;
311 case eDVBFrontendParametersCable::FEC::fAuto: tmp="AUTO"; break;
313 PutToDict(dict, "fec inner", tmp);
316 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
318 if (r.type == eServiceReference::idDVB)
320 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
323 case iServiceInformation::sTransponderData:
325 ePtr<eDVBResourceManager> res;
326 if (!eDVBResourceManager::getInstance(res))
328 ePtr<iDVBChannelList> db;
329 if (!res->getChannelList(db))
332 ref.getChannelID(chid);
333 ePtr<iDVBFrontendParameters> feparm;
334 if (!db->getChannelFrontendData(chid, feparm))
337 if (!feparm->getSystem(system))
339 ePyObject dict = PyDict_New();
342 case iDVBFrontend::feSatellite:
344 eDVBFrontendParametersSatellite s;
346 PutSatelliteDataToDict(dict, s);
349 case iDVBFrontend::feTerrestrial:
351 eDVBFrontendParametersTerrestrial t;
353 PutTerrestrialDataToDict(dict, t);
356 case iDVBFrontend::feCable:
358 eDVBFrontendParametersCable c;
360 PutCableDataToDict(dict, c);
364 eDebug("unknown frontend type %d", system);
379 DEFINE_REF(eStaticServiceDVBBouquetInformation);
381 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
383 ePtr<iDVBChannelList> db;
384 ePtr<eDVBResourceManager> res;
387 if ((err = eDVBResourceManager::getInstance(res)) != 0)
389 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
392 if ((err = res->getChannelList(db)) != 0)
394 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
399 if ((err = db->getBouquet(ref, bouquet)) != 0)
401 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
405 if ( bouquet && bouquet->m_bouquet_name.length() )
407 name = bouquet->m_bouquet_name;
414 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
416 if (ref.flags & eServiceReference::isGroup)
418 ePtr<iDVBChannelList> db;
419 ePtr<eDVBResourceManager> res;
421 if (eDVBResourceManager::getInstance(res))
423 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
427 if (res->getChannelList(db))
429 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
434 if (db->getBouquet(ref, bouquet))
436 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
441 eDVBChannelID chid, chid_ignore;
442 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
443 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
445 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
446 int tmp=res->canAllocateChannel(chid, chid_ignore);
449 m_playable_service = *it;
456 m_playable_service = eServiceReference();
460 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
465 #include <lib/dvb/epgcache.h>
467 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
469 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
472 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
474 DECLARE_REF(eStaticServiceDVBPVRInformation);
475 eServiceReference m_ref;
476 eDVBMetaParser m_parser;
478 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
479 RESULT getName(const eServiceReference &ref, std::string &name);
480 int getLength(const eServiceReference &ref);
481 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
482 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
483 int getInfo(const eServiceReference &ref, int w);
484 std::string getInfoString(const eServiceReference &ref,int w);
487 DEFINE_REF(eStaticServiceDVBPVRInformation);
489 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
492 m_parser.parseFile(ref.path);
495 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
497 ASSERT(ref == m_ref);
498 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
502 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
504 ASSERT(ref == m_ref);
508 if (tstools.openFile(ref.path.c_str()))
512 if (tstools.calcLen(len))
518 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
522 case iServiceInformation::sDescription:
523 return iServiceInformation::resIsString;
524 case iServiceInformation::sServiceref:
525 return iServiceInformation::resIsString;
526 case iServiceInformation::sTimeCreate:
527 if (m_parser.m_time_create)
528 return m_parser.m_time_create;
530 return iServiceInformation::resNA;
532 return iServiceInformation::resNA;
536 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
540 case iServiceInformation::sDescription:
541 return m_parser.m_description;
542 case iServiceInformation::sServiceref:
543 return m_parser.m_ref.toString();
544 case iServiceInformation::sTags:
545 return m_parser.m_tags;
551 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
553 if (!ref.path.empty())
555 ePtr<eServiceEvent> event = new eServiceEvent;
556 std::string filename = ref.path;
557 filename.erase(filename.length()-2, 2);
559 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
569 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
571 DECLARE_REF(eDVBPVRServiceOfflineOperations);
572 eServiceReferenceDVB m_ref;
574 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
576 RESULT deleteFromDisk(int simulate);
577 RESULT getListOfFilenames(std::list<std::string> &);
580 DEFINE_REF(eDVBPVRServiceOfflineOperations);
582 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
586 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
592 std::list<std::string> res;
593 if (getListOfFilenames(res))
596 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
598 eDebug("FATAL !! can't get background file eraser");
600 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
602 eDebug("Removing %s...", i->c_str());
604 eraser->erase(i->c_str());
606 ::unlink(i->c_str());
613 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
616 res.push_back(m_ref.path);
618 // handling for old splitted recordings (enigma 1)
623 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
625 if (stat(buf, &s) < 0)
630 res.push_back(m_ref.path + ".meta");
631 res.push_back(m_ref.path + ".ap");
632 res.push_back(m_ref.path + ".cuts");
633 std::string tmp = m_ref.path;
634 tmp.erase(m_ref.path.length()-3);
635 res.push_back(tmp + ".eit");
639 DEFINE_REF(eServiceFactoryDVB)
641 eServiceFactoryDVB::eServiceFactoryDVB()
643 ePtr<eServiceCenter> sc;
645 eServiceCenter::getPrivInstance(sc);
647 sc->addServiceFactory(eServiceFactoryDVB::id, this);
649 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
650 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
653 eServiceFactoryDVB::~eServiceFactoryDVB()
655 ePtr<eServiceCenter> sc;
657 eServiceCenter::getPrivInstance(sc);
659 sc->removeServiceFactory(eServiceFactoryDVB::id);
662 DEFINE_REF(eDVBServiceList);
664 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
668 eDVBServiceList::~eDVBServiceList()
672 RESULT eDVBServiceList::startQuery()
674 ePtr<iDVBChannelList> db;
675 ePtr<eDVBResourceManager> res;
678 if ((err = eDVBResourceManager::getInstance(res)) != 0)
680 eDebug("no resource manager");
683 if ((err = res->getChannelList(db)) != 0)
685 eDebug("no channel list");
689 ePtr<eDVBChannelQuery> q;
691 if (!m_parent.path.empty())
693 eDVBChannelQuery::compile(q, m_parent.path);
696 eDebug("compile query failed");
701 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
703 eDebug("startQuery failed");
710 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
712 eServiceReferenceDVB ref;
717 while (!m_query->getNextResult(ref))
721 list.sort(iListableServiceCompare(this));
726 // The first argument of this function is a format string to specify the order and
727 // the content of the returned list
728 // useable format options are
729 // R = Service Reference (as swig object .. this is very slow)
730 // S = Service Reference (as python string object .. same as ref.toString())
731 // C = Service Reference (as python string object .. same as ref.toCompareString())
732 // N = Service Name (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'))
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 tmp = PyString_FromString(name.c_str());
790 tmp = PyString_FromString("<n/a>");
803 PyTuple_SET_ITEM(tuple, i, tmp);
805 PyList_SET_ITEM(ret, cnt, tmp);
809 PyList_SET_ITEM(ret, cnt, tuple);
812 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
815 RESULT eDVBServiceList::getNext(eServiceReference &ref)
820 return m_query->getNextResult((eServiceReferenceDVB&)ref);
823 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
825 if (m_parent.flags & eServiceReference::canDescent) // bouquet
827 ePtr<iDVBChannelList> db;
828 ePtr<eDVBResourceManager> resm;
830 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
833 if (db->getBouquet(m_parent, m_bouquet) != 0)
844 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
848 return m_bouquet->addService(ref, before);
851 RESULT eDVBServiceList::removeService(eServiceReference &ref)
855 return m_bouquet->removeService(ref);
858 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
862 return m_bouquet->moveService(ref, pos);
865 RESULT eDVBServiceList::flushChanges()
869 return m_bouquet->flushChanges();
872 RESULT eDVBServiceList::setListName(const std::string &name)
876 return m_bouquet->setListName(name);
879 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
881 ePtr<eDVBService> service;
882 int r = lookupService(service, ref);
885 // check resources...
886 ptr = new eDVBServicePlay(ref, service);
890 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
892 if (ref.path.empty())
894 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
903 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
905 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
906 if (list->startQuery())
916 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
918 /* is a listable service? */
919 if (ref.flags & eServiceReference::canDescent) // bouquet
921 if ( !ref.name.empty() ) // satellites or providers list
922 ptr = m_StaticServiceDVBInfo;
923 else // a dvb bouquet
924 ptr = m_StaticServiceDVBBouquetInfo;
926 else if (!ref.path.empty()) /* do we have a PVR service? */
927 ptr = new eStaticServiceDVBPVRInformation(ref);
928 else // normal dvb service
930 ePtr<eDVBService> service;
931 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
932 ptr = m_StaticServiceDVBInfo;
934 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
940 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
942 if (ref.path.empty())
948 ptr = new eDVBPVRServiceOfflineOperations(ref);
953 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
955 // TODO: handle the listing itself
956 // if (ref.... == -1) .. return "... bouquets ...";
957 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
959 ePtr<iDVBChannelList> db;
960 ePtr<eDVBResourceManager> res;
963 if ((err = eDVBResourceManager::getInstance(res)) != 0)
965 eDebug("no resource manager");
968 if ((err = res->getChannelList(db)) != 0)
970 eDebug("no channel list");
974 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
975 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
977 eDebug("getService failed!");
984 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
985 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
987 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
989 m_is_pvr = !m_reference.path.empty();
991 m_timeshift_enabled = m_timeshift_active = 0;
994 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
995 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
996 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
998 m_cuesheet_changed = 0;
999 m_cutlist_enabled = 1;
1001 m_subtitle_widget = 0;
1005 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
1008 eDVBServicePlay::~eDVBServicePlay()
1010 delete m_subtitle_widget;
1013 void eDVBServicePlay::gotNewEvent()
1017 ePtr<eServiceEvent> m_event_now, m_event_next;
1018 getEvent(m_event_now, 0);
1019 getEvent(m_event_next, 1);
1022 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1024 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1026 m_event((iPlayableService*)this, evUpdatedEventInfo);
1029 void eDVBServicePlay::serviceEvent(int event)
1031 m_tune_state = event;
1035 case eDVBServicePMTHandler::eventTuned:
1037 ePtr<iDVBDemux> m_demux;
1038 if (!m_service_handler.getDataDemux(m_demux))
1040 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1041 int sid = ref.getParentServiceID().get();
1043 sid = ref.getServiceID().get();
1044 if ( ref.getParentTransportStreamID().get() &&
1045 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1046 m_event_handler.startOther(m_demux, sid);
1048 m_event_handler.start(m_demux, sid);
1052 case eDVBServicePMTHandler::eventNoResources:
1053 case eDVBServicePMTHandler::eventNoPAT:
1054 case eDVBServicePMTHandler::eventNoPATEntry:
1055 case eDVBServicePMTHandler::eventNoPMT:
1056 case eDVBServicePMTHandler::eventTuneFailed:
1058 eDebug("DVB service failed to tune - error %d", event);
1059 m_event((iPlayableService*)this, evTuneFailed);
1062 case eDVBServicePMTHandler::eventNewProgramInfo:
1064 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1065 if (m_timeshift_enabled)
1066 updateTimeshiftPids();
1067 if (!m_timeshift_active)
1069 if (m_first_program_info && m_is_pvr)
1071 m_first_program_info = 0;
1074 m_event((iPlayableService*)this, evUpdatedInfo);
1077 case eDVBServicePMTHandler::eventEOF:
1078 m_event((iPlayableService*)this, evEOF);
1080 case eDVBServicePMTHandler::eventSOF:
1081 m_event((iPlayableService*)this, evSOF);
1086 void eDVBServicePlay::serviceEventTimeshift(int event)
1090 case eDVBServicePMTHandler::eventNewProgramInfo:
1091 if (m_timeshift_active)
1094 case eDVBServicePMTHandler::eventSOF:
1095 m_event((iPlayableService*)this, evSOF);
1097 case eDVBServicePMTHandler::eventEOF:
1103 RESULT eDVBServicePlay::start()
1106 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1107 two (one for decoding, one for data source), as we must be prepared
1108 to start recording from the data demux. */
1110 m_cue = new eCueSheet();
1112 m_event(this, evStart);
1114 m_first_program_info = 1;
1115 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1116 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1118 /* inject EIT if there is a stored one */
1121 std::string filename = service.path;
1122 filename.erase(filename.length()-2, 2);
1124 ePtr<eServiceEvent> event = new eServiceEvent;
1125 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1127 ePtr<eServiceEvent> empty;
1128 m_event_handler.inject(event, 0);
1129 m_event_handler.inject(empty, 1);
1136 m_event((iPlayableService*)this, evSeekableStatusChanged);
1140 RESULT eDVBServicePlay::stop()
1142 /* add bookmark for last play position */
1145 pts_t play_position;
1146 if (!getPlayPosition(play_position))
1148 /* remove last position */
1149 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1151 if (i->what == 3) /* current play position */
1153 m_cue_entries.erase(i);
1154 i = m_cue_entries.begin();
1160 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1161 m_cuesheet_changed = 1;
1165 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1167 m_service_handler_timeshift.free();
1168 m_service_handler.free();
1170 if (m_is_pvr && m_cuesheet_changed)
1173 /* save cuesheet only when main file is accessible. */
1174 if (!::stat(m_reference.path.c_str(), &s))
1181 RESULT eDVBServicePlay::setTarget(int target)
1183 m_is_primary = !target;
1187 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1189 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1193 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1195 /* note: we check for timeshift to be enabled,
1196 not neccessary active. if you pause when timeshift
1197 is not active, you should activate it when unpausing */
1198 if ((!m_is_pvr) && (!m_timeshift_enabled))
1208 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1211 return m_decoder->setSlowMotion(ratio);
1216 RESULT eDVBServicePlay::setFastForward(int ratio)
1218 int skipmode, ffratio;
1224 } else if (ratio > 0)
1232 } else // if (ratio < 0)
1238 if (m_skipmode != skipmode)
1240 eDebug("setting cue skipmode to %d", skipmode);
1242 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1245 m_skipmode = skipmode;
1250 return m_decoder->setFastForward(ffratio);
1253 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1255 if (m_is_pvr || m_timeshift_enabled)
1265 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1266 RESULT eDVBServicePlay::getLength(pts_t &len)
1268 ePtr<iDVBPVRChannel> pvr_channel;
1270 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1273 return pvr_channel->getLength(len);
1276 RESULT eDVBServicePlay::pause()
1278 if (!m_is_paused && m_decoder)
1281 return m_decoder->freeze(0);
1286 RESULT eDVBServicePlay::unpause()
1288 if (m_is_paused && m_decoder)
1291 return m_decoder->unfreeze();
1296 RESULT eDVBServicePlay::seekTo(pts_t to)
1298 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1300 if (!m_decode_demux)
1303 ePtr<iDVBPVRChannel> pvr_channel;
1305 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1311 m_cue->seekTo(0, to);
1315 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1317 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1319 if (!m_decode_demux)
1322 ePtr<iDVBPVRChannel> pvr_channel;
1324 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1329 /* HACK until we have skip-AP api */
1330 if ((to > 0) && (to < 100))
1338 m_cue->seekTo(mode, to);
1342 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1344 ePtr<iDVBPVRChannel> pvr_channel;
1346 if (!m_decode_demux)
1349 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1354 /* if there is a decoder, use audio or video PTS */
1357 r = m_decoder->getPTS(0, pos);
1363 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1366 RESULT eDVBServicePlay::setTrickmode(int trick)
1369 m_decoder->setTrickmode(trick);
1373 RESULT eDVBServicePlay::isCurrentlySeekable()
1375 return m_is_pvr || m_timeshift_active;
1378 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1384 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1390 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1396 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1402 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1408 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1411 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1412 (m_timeshift_enabled || !m_is_pvr))
1414 if (!m_timeshift_enabled)
1416 /* we need enough diskspace */
1418 if (statfs(TSPATH "/.", &fs) < 0)
1420 eDebug("statfs failed!");
1424 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1426 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1436 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1447 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1453 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1459 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1465 RESULT eDVBServicePlay::getName(std::string &name)
1469 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1470 return i->getName(m_reference, name);
1474 m_dvb_service->getName(m_reference, name);
1478 else if (!m_reference.name.empty())
1479 eStaticServiceDVBInformation().getName(m_reference, name);
1481 name = "DVB service";
1485 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1487 return m_event_handler.getEvent(evt, nownext);
1490 int eDVBServicePlay::getInfo(int w)
1492 eDVBServicePMTHandler::program program;
1495 return resIsPyObject;
1497 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1499 int no_program_info = 0;
1501 if (h.getProgramInfo(program))
1502 no_program_info = 1;
1506 #if HAVE_DVB_API_VERSION >= 3
1508 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1509 return m_videoEventData.height;
1512 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1513 return m_videoEventData.width;
1516 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1519 #if HAVE_DVB_API_VERSION >= 3
1520 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1521 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1524 #warning "FIXMEE implement sAspect for old DVB API"
1526 if (no_program_info)
1528 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1530 ePtr<eServiceEvent> evt;
1531 if (!m_event_handler.getEvent(evt, 0))
1533 ePtr<eComponentData> data;
1534 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1536 if ( data->getStreamContent() == 1 )
1538 switch(data->getComponentType())
1541 case 1: // 4:3 SD PAL
1543 case 3: // 16:9 SD PAL
1544 case 4: // > 16:9 PAL
1545 case 5: // 4:3 SD NTSC
1547 case 7: // 16:9 SD NTSC
1548 case 8: // > 16:9 NTSC
1551 case 9: // 4:3 HD PAL
1553 case 0xB: // 16:9 HD PAL
1554 case 0xC: // > 16:9 HD PAL
1555 case 0xD: // 4:3 HD NTSC
1557 case 0xF: // 16:9 HD NTSC
1558 case 0x10: // > 16:9 HD PAL
1559 return data->getComponentType();
1566 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1567 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1568 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1569 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1570 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1571 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1572 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1573 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1574 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1575 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1576 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1577 case sProvider: if (!m_dvb_service) return -1; return -2;
1578 case sServiceref: return resIsString;
1579 case sDVBState: return m_tune_state;
1585 std::string eDVBServicePlay::getInfoString(int w)
1590 if (!m_dvb_service) return "";
1591 return m_dvb_service->m_provider_name;
1593 return m_reference.toString();
1597 return iServiceInformation::getInfoString(w);
1600 PyObject *eDVBServicePlay::getInfoObject(int w)
1605 return m_service_handler.getCaIds();
1606 case sTransponderData:
1607 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1611 return iServiceInformation::getInfoObject(w);
1614 int eDVBServicePlay::getNumberOfTracks()
1616 eDVBServicePMTHandler::program program;
1617 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1618 if (h.getProgramInfo(program))
1620 return program.audioStreams.size();
1623 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1625 int ret = selectAudioStream(i);
1627 if (m_decoder->start())
1633 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1635 eDVBServicePMTHandler::program program;
1636 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1638 if (h.getProgramInfo(program))
1641 if (i >= program.audioStreams.size())
1644 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1645 info.m_description = "MPEG";
1646 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1647 info.m_description = "AC3";
1648 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1649 info.m_description = "AAC";
1650 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1651 info.m_description = "DTS";
1653 info.m_description = "???";
1655 if (program.audioStreams[i].component_tag != -1)
1657 ePtr<eServiceEvent> evt;
1658 if (!m_event_handler.getEvent(evt, 0))
1660 ePtr<eComponentData> data;
1661 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1662 info.m_language = data->getText();
1666 if (info.m_language.empty())
1667 info.m_language = program.audioStreams[i].language_code;
1672 int eDVBServicePlay::selectAudioStream(int i)
1674 eDVBServicePMTHandler::program program;
1675 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1677 if (h.getProgramInfo(program))
1680 if ((unsigned int)i >= program.audioStreams.size())
1686 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1689 if (m_radiotext_parser)
1690 m_radiotext_parser->start(program.audioStreams[i].pid);
1692 if (m_dvb_service && !m_is_pvr)
1694 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1696 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1697 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1701 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1702 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1706 h.resetCachedProgram();
1711 int eDVBServicePlay::getCurrentChannel()
1713 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1716 RESULT eDVBServicePlay::selectChannel(int i)
1718 if (i < LEFT || i > RIGHT || i == STEREO)
1721 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1723 m_decoder->setAudioChannel(i);
1727 std::string eDVBServicePlay::getRadioText(int x)
1729 if (m_radiotext_parser)
1733 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1738 void eDVBServicePlay::radioTextUpdated()
1740 m_event((iPlayableService*)this, evUpdatedRadioText);
1743 int eDVBServiceBase::getFrontendInfo(int w)
1745 eUsePtr<iDVBChannel> channel;
1746 if(m_service_handler.getChannel(channel))
1748 ePtr<iDVBFrontend> fe;
1749 if(channel->getFrontend(fe))
1751 return fe->readFrontendData(w);
1754 PyObject *eDVBServiceBase::getFrontendData(bool original)
1758 eUsePtr<iDVBChannel> channel;
1759 if(!m_service_handler.getChannel(channel))
1761 ePtr<iDVBFrontend> fe;
1762 if(!channel->getFrontend(fe))
1764 ret = fe->readTransponderData(original);
1767 ePtr<iDVBFrontendParameters> feparm;
1768 channel->getCurrentFrontendParameters(feparm);
1771 eDVBFrontendParametersSatellite osat;
1772 if (!feparm->getDVBS(osat))
1774 void PutToDict(ePyObject &, const char*, long);
1775 void PutToDict(ePyObject &, const char*, const char*);
1776 PutToDict(ret, "orbital_position", osat.orbital_position);
1777 const char *tmp = "UNKNOWN";
1778 switch(osat.polarisation)
1780 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1781 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1782 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1783 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1786 PutToDict(ret, "polarization", tmp);
1797 int eDVBServicePlay::getNumberOfSubservices()
1799 ePtr<eServiceEvent> evt;
1800 if (!m_event_handler.getEvent(evt, 0))
1801 return evt->getNumOfLinkageServices();
1805 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1807 ePtr<eServiceEvent> evt;
1808 if (!m_event_handler.getEvent(evt, 0))
1810 if (!evt->getLinkageService(sub, m_reference, n))
1813 sub.type=eServiceReference::idInvalid;
1817 RESULT eDVBServicePlay::startTimeshift()
1819 ePtr<iDVBDemux> demux;
1821 eDebug("Start timeshift!");
1823 if (m_timeshift_enabled)
1826 /* start recording with the data demux. */
1827 if (m_service_handler.getDataDemux(demux))
1830 demux->createTSRecorder(m_record);
1834 char templ[]=TSPATH "/timeshift.XXXXXX";
1835 m_timeshift_fd = mkstemp(templ);
1836 m_timeshift_file = templ;
1838 eDebug("recording to %s", templ);
1840 if (m_timeshift_fd < 0)
1846 m_record->setTargetFD(m_timeshift_fd);
1848 m_timeshift_enabled = 1;
1850 updateTimeshiftPids();
1856 RESULT eDVBServicePlay::stopTimeshift()
1858 if (!m_timeshift_enabled)
1863 m_timeshift_enabled = 0;
1868 close(m_timeshift_fd);
1869 eDebug("remove timeshift file");
1870 remove(m_timeshift_file.c_str());
1875 int eDVBServicePlay::isTimeshiftActive()
1877 return m_timeshift_enabled && m_timeshift_active;
1880 RESULT eDVBServicePlay::activateTimeshift()
1882 if (!m_timeshift_enabled)
1885 if (!m_timeshift_active)
1887 switchToTimeshift();
1894 PyObject *eDVBServicePlay::getCutList()
1896 ePyObject list = PyList_New(0);
1898 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1900 ePyObject tuple = PyTuple_New(2);
1901 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1902 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1903 PyList_Append(list, tuple);
1910 void eDVBServicePlay::setCutList(ePyObject list)
1912 if (!PyList_Check(list))
1914 int size = PyList_Size(list);
1917 m_cue_entries.clear();
1919 for (i=0; i<size; ++i)
1921 ePyObject tuple = PyList_GET_ITEM(list, i);
1922 if (!PyTuple_Check(tuple))
1924 eDebug("non-tuple in cutlist");
1927 if (PyTuple_Size(tuple) != 2)
1929 eDebug("cutlist entries need to be a 2-tuple");
1932 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1933 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1935 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1938 pts_t pts = PyLong_AsLongLong(ppts);
1939 int type = PyInt_AsLong(ptype);
1940 m_cue_entries.insert(cueEntry(pts, type));
1941 eDebug("adding %08llx, %d", pts, type);
1943 m_cuesheet_changed = 1;
1945 cutlistToCuesheet();
1946 m_event((iPlayableService*)this, evCuesheetChanged);
1949 void eDVBServicePlay::setCutListEnable(int enable)
1951 m_cutlist_enabled = enable;
1952 cutlistToCuesheet();
1955 void eDVBServicePlay::updateTimeshiftPids()
1960 eDVBServicePMTHandler::program program;
1961 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1963 if (h.getProgramInfo(program))
1967 std::set<int> pids_to_record;
1968 pids_to_record.insert(0); // PAT
1969 if (program.pmtPid != -1)
1970 pids_to_record.insert(program.pmtPid); // PMT
1972 if (program.textPid != -1)
1973 pids_to_record.insert(program.textPid); // Videotext
1975 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1976 i(program.videoStreams.begin());
1977 i != program.videoStreams.end(); ++i)
1978 pids_to_record.insert(i->pid);
1980 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1981 i(program.audioStreams.begin());
1982 i != program.audioStreams.end(); ++i)
1983 pids_to_record.insert(i->pid);
1985 std::set<int> new_pids, obsolete_pids;
1987 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1988 m_pids_active.begin(), m_pids_active.end(),
1989 std::inserter(new_pids, new_pids.begin()));
1991 std::set_difference(
1992 m_pids_active.begin(), m_pids_active.end(),
1993 pids_to_record.begin(), pids_to_record.end(),
1994 std::inserter(new_pids, new_pids.begin())
1997 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1998 m_record->addPID(*i);
2000 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2001 m_record->removePID(*i);
2005 void eDVBServicePlay::switchToLive()
2007 if (!m_timeshift_active)
2013 m_teletext_parser = 0;
2014 m_radiotext_parser = 0;
2015 m_subtitle_parser = 0;
2016 m_new_dvb_subtitle_page_connection = 0;
2017 m_new_subtitle_page_connection = 0;
2018 m_radiotext_updated_connection = 0;
2020 /* free the timeshift service handler, we need the resources */
2021 m_service_handler_timeshift.free();
2022 m_timeshift_active = 0;
2024 m_event((iPlayableService*)this, evSeekableStatusChanged);
2029 void eDVBServicePlay::switchToTimeshift()
2031 if (m_timeshift_active)
2036 m_teletext_parser = 0;
2037 m_radiotext_parser = 0;
2038 m_subtitle_parser = 0;
2039 m_new_subtitle_page_connection = 0;
2040 m_new_dvb_subtitle_page_connection = 0;
2041 m_radiotext_updated_connection = 0;
2043 m_timeshift_active = 1;
2045 m_event((iPlayableService*)this, evSeekableStatusChanged);
2047 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2048 r.path = m_timeshift_file;
2050 m_cue = new eCueSheet();
2051 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2052 updateDecoder(); /* mainly to switch off PCR */
2055 void eDVBServicePlay::updateDecoder()
2057 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2059 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2061 bool defaultac3=false;
2062 std::string default_ac3;
2064 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2065 defaultac3 = default_ac3 == "True";
2067 eDVBServicePMTHandler::program program;
2068 if (h.getProgramInfo(program))
2069 eDebug("getting program info failed.");
2072 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2073 if (!program.videoStreams.empty())
2075 eDebugNoNewLine(" (");
2076 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2077 i(program.videoStreams.begin());
2078 i != program.videoStreams.end(); ++i)
2085 if (i != program.videoStreams.begin())
2086 eDebugNoNewLine(", ");
2087 eDebugNoNewLine("%04x", i->pid);
2089 eDebugNoNewLine(")");
2091 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2092 if (!program.audioStreams.empty())
2094 eDebugNoNewLine(" (");
2095 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2096 i(program.audioStreams.begin());
2097 i != program.audioStreams.end(); ++i)
2099 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2101 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2107 if (i != program.audioStreams.begin())
2108 eDebugNoNewLine(", ");
2109 eDebugNoNewLine("%04x", i->pid);
2111 eDebugNoNewLine(")");
2113 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2114 pcrpid = program.pcrPid;
2115 eDebug(", and the text pid is %04x", program.textPid);
2116 tpid = program.textPid;
2121 h.getDecodeDemux(m_decode_demux);
2124 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2126 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2129 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2130 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2131 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2132 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2133 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2140 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2141 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2142 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2144 else // subservice or recording
2146 eServiceReferenceDVB ref;
2147 m_service_handler.getServiceReference(ref);
2148 eServiceReferenceDVB parent = ref.getParentServiceReference();
2153 ePtr<eDVBResourceManager> res_mgr;
2154 if (!eDVBResourceManager::getInstance(res_mgr))
2156 ePtr<iDVBChannelList> db;
2157 if (!res_mgr->getChannelList(db))
2159 ePtr<eDVBService> origService;
2160 if (!db->getService(parent, origService))
2162 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2163 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2169 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2170 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2172 m_decoder->setVideoPID(vpid, vpidtype);
2173 m_decoder->setAudioPID(apid, apidtype);
2174 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2176 m_decoder->setSyncPCR(pcrpid);
2179 ePtr<iDVBDemux> data_demux;
2180 if (!h.getDataDemux(data_demux))
2182 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
2183 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
2184 m_radiotext_parser->start(apid);
2189 m_decoder->setSyncPCR(-1);
2191 m_decoder->setTextPID(tpid);
2193 m_teletext_parser->start(program.textPid);
2196 m_decoder->setTrickmode(1);
2200 if (vpid > 0 && vpid < 0x2000)
2204 std::string radio_pic;
2205 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2206 m_decoder->setRadioPic(radio_pic);
2209 m_decoder->setAudioChannel(achannel);
2211 // how we can do this better?
2212 // update cache pid when the user changed the audio track or video track
2213 // TODO handling of difference audio types.. default audio types..
2215 /* don't worry about non-existing services, nor pvr services */
2216 if (m_dvb_service && !m_is_pvr)
2218 if (apidtype == eDVBAudio::aMPEG)
2220 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2221 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2225 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2226 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2228 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2229 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2230 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2231 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2234 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2237 void eDVBServicePlay::loadCuesheet()
2239 std::string filename = m_reference.path + ".cuts";
2241 m_cue_entries.clear();
2243 FILE *f = fopen(filename.c_str(), "rb");
2247 eDebug("loading cuts..");
2250 unsigned long long where;
2253 if (!fread(&where, sizeof(where), 1, f))
2255 if (!fread(&what, sizeof(what), 1, f))
2258 #if BYTE_ORDER == LITTLE_ENDIAN
2259 where = bswap_64(where);
2266 m_cue_entries.insert(cueEntry(where, what));
2269 eDebug("%d entries", m_cue_entries.size());
2271 eDebug("cutfile not found!");
2273 m_cuesheet_changed = 0;
2274 cutlistToCuesheet();
2275 m_event((iPlayableService*)this, evCuesheetChanged);
2278 void eDVBServicePlay::saveCuesheet()
2280 std::string filename = m_reference.path + ".cuts";
2282 FILE *f = fopen(filename.c_str(), "wb");
2286 unsigned long long where;
2289 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2291 #if BYTE_ORDER == BIG_ENDIAN
2294 where = bswap_64(i->where);
2296 what = htonl(i->what);
2297 fwrite(&where, sizeof(where), 1, f);
2298 fwrite(&what, sizeof(what), 1, f);
2304 m_cuesheet_changed = 0;
2307 void eDVBServicePlay::cutlistToCuesheet()
2311 eDebug("no cue sheet");
2316 if (!m_cutlist_enabled)
2318 m_cue->commitSpans();
2319 eDebug("cutlists were disabled");
2323 pts_t in = 0, out = 0, length = 0;
2327 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2331 if (i == m_cue_entries.end())
2334 if (i->what == 0) /* in */
2338 } else if (i->what == 1) /* out */
2340 else /* mark (2) or last play position (3) */
2348 m_cue->addSourceSpan(in, out);
2352 if (i == m_cue_entries.end())
2355 m_cue->commitSpans();
2358 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2360 if (m_subtitle_widget)
2361 disableSubtitles(parent);
2364 int tuplesize = PyTuple_Size(tuple);
2367 if (!PyTuple_Check(tuple))
2373 entry = PyTuple_GET_ITEM(tuple, 0);
2375 if (!PyInt_Check(entry))
2378 type = PyInt_AsLong(entry);
2380 if (type == 1) // teletext subtitles
2382 int page, magazine, pid;
2386 if (!m_teletext_parser)
2388 eDebug("enable teletext subtitles.. no parser !!!");
2392 entry = PyTuple_GET_ITEM(tuple, 1);
2393 if (!PyInt_Check(entry))
2395 pid = PyInt_AsLong(entry);
2397 entry = PyTuple_GET_ITEM(tuple, 2);
2398 if (!PyInt_Check(entry))
2400 page = PyInt_AsLong(entry);
2402 entry = PyTuple_GET_ITEM(tuple, 3);
2403 if (!PyInt_Check(entry))
2405 magazine = PyInt_AsLong(entry);
2407 m_subtitle_widget = new eSubtitleWidget(parent);
2408 m_subtitle_widget->resize(parent->size()); /* full size */
2409 m_teletext_parser->setPageAndMagazine(page, magazine);
2411 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2415 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2416 if (!m_subtitle_parser)
2418 eDebug("enable dvb subtitles.. no parser !!!");
2424 entry = PyTuple_GET_ITEM(tuple, 1);
2425 if (!PyInt_Check(entry))
2427 pid = PyInt_AsLong(entry);
2429 entry = PyTuple_GET_ITEM(tuple, 2);
2430 if (!PyInt_Check(entry))
2432 composition_page_id = PyInt_AsLong(entry);
2434 entry = PyTuple_GET_ITEM(tuple, 3);
2435 if (!PyInt_Check(entry))
2437 ancillary_page_id = PyInt_AsLong(entry);
2439 m_subtitle_widget = new eSubtitleWidget(parent);
2440 m_subtitle_widget->resize(parent->size()); /* full size */
2441 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2443 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2449 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2450 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2451 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2455 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2457 delete m_subtitle_widget;
2458 m_subtitle_widget = 0;
2459 if (m_subtitle_parser)
2461 m_subtitle_parser->stop();
2462 m_dvb_subtitle_pages.clear();
2464 if (m_teletext_parser)
2466 m_teletext_parser->setPageAndMagazine(-1, -1);
2467 m_subtitle_pages.clear();
2470 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2474 PyObject *eDVBServicePlay::getCachedSubtitle()
2478 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2481 unsigned int data = (unsigned int)tmp;
2482 int pid = (data&0xFFFF0000)>>16;
2483 ePyObject tuple = PyTuple_New(4);
2484 eDVBServicePMTHandler::program program;
2485 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2486 if (!h.getProgramInfo(program))
2488 if (program.textPid==pid) // teletext
2489 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2491 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2492 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2493 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2494 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2502 PyObject *eDVBServicePlay::getSubtitleList()
2504 if (!m_teletext_parser)
2507 ePyObject l = PyList_New(0);
2508 std::set<int> added_ttx_pages;
2510 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2511 m_teletext_parser->m_found_subtitle_pages;
2513 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2514 eDVBServicePMTHandler::program program;
2515 if (h.getProgramInfo(program))
2516 eDebug("getting program info failed.");
2519 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2520 it != program.subtitleStreams.end(); ++it)
2522 switch(it->subtitling_type)
2524 case 0x01: // ebu teletext subtitles
2526 int page_number = it->teletext_page_number & 0xFF;
2527 int magazine_number = it->teletext_magazine_number & 7;
2528 int hash = magazine_number << 8 | page_number;
2529 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2531 ePyObject tuple = PyTuple_New(5);
2532 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2533 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2534 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2535 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2536 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2537 PyList_Append(l, tuple);
2539 added_ttx_pages.insert(hash);
2544 case 0x20 ... 0x23: // dvb subtitles
2546 ePyObject tuple = PyTuple_New(5);
2547 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2548 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2549 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2550 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2551 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2552 PyList_Insert(l, 0, tuple);
2560 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2561 it != subs.end(); ++it)
2563 int page_number = it->teletext_page_number & 0xFF;
2564 int magazine_number = it->teletext_magazine_number & 7;
2565 int hash = magazine_number << 8 | page_number;
2566 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2568 ePyObject tuple = PyTuple_New(5);
2569 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2570 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2571 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2572 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2573 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2574 PyList_Append(l, tuple);
2582 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2584 if (m_subtitle_widget)
2586 m_subtitle_pages.push_back(page);
2587 checkSubtitleTiming();
2591 void eDVBServicePlay::checkSubtitleTiming()
2593 // eDebug("checkSubtitleTiming");
2594 if (!m_subtitle_widget)
2598 enum { TELETEXT, DVB } type;
2599 eDVBTeletextSubtitlePage page;
2600 eDVBSubtitlePage dvb_page;
2602 if (!m_subtitle_pages.empty())
2604 page = m_subtitle_pages.front();
2606 show_time = page.m_pts;
2608 else if (!m_dvb_subtitle_pages.empty())
2610 dvb_page = m_dvb_subtitle_pages.front();
2612 show_time = dvb_page.m_show_time;
2620 m_decoder->getPTS(0, pos);
2622 // eDebug("%lld %lld", pos, show_time);
2623 int diff = show_time - pos;
2626 eDebug("[late (%d ms)]", -diff / 90);
2631 eDebug("[invalid]");
2637 if (type == TELETEXT)
2639 eDebug("display teletext subtitle page");
2640 m_subtitle_widget->setPage(page);
2641 m_subtitle_pages.pop_front();
2645 eDebug("display dvb subtitle Page");
2646 m_subtitle_widget->setPage(dvb_page);
2647 m_dvb_subtitle_pages.pop_front();
2651 // eDebug("start subtitle delay %d", diff / 90);
2652 m_subtitle_sync_timer.start(diff / 90, 1);
2658 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2660 if (m_subtitle_widget)
2662 m_dvb_subtitle_pages.push_back(p);
2663 checkSubtitleTiming();
2667 int eDVBServicePlay::getAC3Delay()
2670 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2672 return m_decoder->getAC3Delay();
2677 int eDVBServicePlay::getPCMDelay()
2680 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2682 return m_decoder->getPCMDelay();
2687 void eDVBServicePlay::setAC3Delay(int delay)
2690 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2692 m_decoder->setAC3Delay(delay);
2695 void eDVBServicePlay::setPCMDelay(int delay)
2698 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2700 m_decoder->setPCMDelay(delay);
2703 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2705 eDebug("!!!!!!!!!! Video Event type %d, aspect %d, %dx%d", event.type, event.aspect, event.width, event.height);
2706 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2707 m_event((iPlayableService*)this, evVideoSizeChanged);
2710 DEFINE_REF(eDVBServicePlay)
2712 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2716 case iServiceInformation::sTransponderData:
2717 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2721 return iStaticServiceInformation::getInfoObject(ref, w);
2724 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");