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("isPlayble... 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);
374 DEFINE_REF(eStaticServiceDVBBouquetInformation);
376 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
378 ePtr<iDVBChannelList> db;
379 ePtr<eDVBResourceManager> res;
382 if ((err = eDVBResourceManager::getInstance(res)) != 0)
384 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
387 if ((err = res->getChannelList(db)) != 0)
389 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
394 if ((err = db->getBouquet(ref, bouquet)) != 0)
396 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
400 if ( bouquet && bouquet->m_bouquet_name.length() )
402 name = bouquet->m_bouquet_name;
409 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
411 if (ref.flags & eServiceReference::isGroup)
413 ePtr<iDVBChannelList> db;
414 ePtr<eDVBResourceManager> res;
416 if (eDVBResourceManager::getInstance(res))
418 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
422 if (res->getChannelList(db))
424 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
429 if (db->getBouquet(ref, bouquet))
431 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
436 eDVBChannelID chid, chid_ignore;
437 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
438 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
440 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
441 int tmp=res->canAllocateChannel(chid, chid_ignore);
444 m_playable_service = *it;
451 m_playable_service = eServiceReference();
455 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
460 #include <lib/dvb/epgcache.h>
462 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
464 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
467 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
469 DECLARE_REF(eStaticServiceDVBPVRInformation);
470 eServiceReference m_ref;
471 eDVBMetaParser m_parser;
473 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
474 RESULT getName(const eServiceReference &ref, std::string &name);
475 int getLength(const eServiceReference &ref);
476 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
477 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
478 int getInfo(const eServiceReference &ref, int w);
479 std::string getInfoString(const eServiceReference &ref,int w);
482 DEFINE_REF(eStaticServiceDVBPVRInformation);
484 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
487 m_parser.parseFile(ref.path);
490 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
492 ASSERT(ref == m_ref);
493 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
497 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
499 ASSERT(ref == m_ref);
503 if (tstools.openFile(ref.path.c_str()))
507 if (tstools.calcLen(len))
513 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
517 case iServiceInformation::sDescription:
518 return iServiceInformation::resIsString;
519 case iServiceInformation::sServiceref:
520 return iServiceInformation::resIsString;
521 case iServiceInformation::sTimeCreate:
522 if (m_parser.m_time_create)
523 return m_parser.m_time_create;
525 return iServiceInformation::resNA;
527 return iServiceInformation::resNA;
531 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
535 case iServiceInformation::sDescription:
536 return m_parser.m_description;
537 case iServiceInformation::sServiceref:
538 return m_parser.m_ref.toString();
539 case iServiceInformation::sTags:
540 return m_parser.m_tags;
546 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
548 if (!ref.path.empty())
550 ePtr<eServiceEvent> event = new eServiceEvent;
551 std::string filename = ref.path;
552 filename.erase(filename.length()-2, 2);
554 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
564 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
566 DECLARE_REF(eDVBPVRServiceOfflineOperations);
567 eServiceReferenceDVB m_ref;
569 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
571 RESULT deleteFromDisk(int simulate);
572 RESULT getListOfFilenames(std::list<std::string> &);
575 DEFINE_REF(eDVBPVRServiceOfflineOperations);
577 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
581 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
587 std::list<std::string> res;
588 if (getListOfFilenames(res))
591 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
593 eDebug("FATAL !! can't get background file eraser");
595 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
597 eDebug("Removing %s...", i->c_str());
599 eraser->erase(i->c_str());
601 ::unlink(i->c_str());
608 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
611 res.push_back(m_ref.path);
613 // handling for old splitted recordings (enigma 1)
618 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
620 if (stat(buf, &s) < 0)
625 res.push_back(m_ref.path + ".meta");
626 res.push_back(m_ref.path + ".ap");
627 res.push_back(m_ref.path + ".cuts");
628 std::string tmp = m_ref.path;
629 tmp.erase(m_ref.path.length()-3);
630 res.push_back(tmp + ".eit");
634 DEFINE_REF(eServiceFactoryDVB)
636 eServiceFactoryDVB::eServiceFactoryDVB()
638 ePtr<eServiceCenter> sc;
640 eServiceCenter::getPrivInstance(sc);
642 sc->addServiceFactory(eServiceFactoryDVB::id, this);
644 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
645 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
648 eServiceFactoryDVB::~eServiceFactoryDVB()
650 ePtr<eServiceCenter> sc;
652 eServiceCenter::getPrivInstance(sc);
654 sc->removeServiceFactory(eServiceFactoryDVB::id);
657 DEFINE_REF(eDVBServiceList);
659 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
663 eDVBServiceList::~eDVBServiceList()
667 RESULT eDVBServiceList::startQuery()
669 ePtr<iDVBChannelList> db;
670 ePtr<eDVBResourceManager> res;
673 if ((err = eDVBResourceManager::getInstance(res)) != 0)
675 eDebug("no resource manager");
678 if ((err = res->getChannelList(db)) != 0)
680 eDebug("no channel list");
684 ePtr<eDVBChannelQuery> q;
686 if (!m_parent.path.empty())
688 eDVBChannelQuery::compile(q, m_parent.path);
691 eDebug("compile query failed");
696 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
698 eDebug("startQuery failed");
705 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
707 eServiceReferenceDVB ref;
712 while (!m_query->getNextResult(ref))
716 list.sort(iListableServiceCompare(this));
721 // The first argument of this function is a format string to specify the order and
722 // the content of the returned list
723 // useable format options are
724 // R = Service Reference (as swig object .. this is very slow)
725 // S = Service Reference (as python string object .. same as ref.toString())
726 // C = Service Reference (as python string object .. same as ref.toCompareString())
727 // N = Service Name (as python string object)
728 // when exactly one return value per service is selected in the format string,
729 // then each value is directly a list entry
730 // when more than one value is returned per service, then the list is a list of
732 // unknown format string chars are returned as python None values !
733 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
736 std::list<eServiceReference> tmplist;
739 if (!format || !(retcount=strlen(format)))
740 format = "R"; // just return service reference swig object ...
742 if (!getContent(tmplist, sorted))
744 int services=tmplist.size();
745 ePtr<iStaticServiceInformation> sptr;
746 eServiceCenterPtr service_center;
748 if (strchr(format, 'N'))
749 eServiceCenter::getPrivInstance(service_center);
751 ret = PyList_New(services);
752 std::list<eServiceReference>::iterator it(tmplist.begin());
754 for (int cnt=0; cnt < services; ++cnt)
756 eServiceReference &ref=*it++;
757 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
758 for (int i=0; i < retcount; ++i)
763 case 'R': // service reference (swig)object
764 tmp = NEW_eServiceReference(ref);
766 case 'C': // service reference compare string
767 tmp = PyString_FromString(ref.toCompareString().c_str());
769 case 'S': // service reference string
770 tmp = PyString_FromString(ref.toString().c_str());
772 case 'N': // service name
775 service_center->info(ref, sptr);
779 sptr->getName(ref, name);
781 tmp = PyString_FromString(name.c_str());
785 tmp = PyString_FromString("<n/a>");
798 PyTuple_SET_ITEM(tuple, i, tmp);
800 PyList_SET_ITEM(ret, cnt, tmp);
804 PyList_SET_ITEM(ret, cnt, tuple);
807 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
810 RESULT eDVBServiceList::getNext(eServiceReference &ref)
815 return m_query->getNextResult((eServiceReferenceDVB&)ref);
818 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
820 if (m_parent.flags & eServiceReference::canDescent) // bouquet
822 ePtr<iDVBChannelList> db;
823 ePtr<eDVBResourceManager> resm;
825 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
828 if (db->getBouquet(m_parent, m_bouquet) != 0)
839 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
843 return m_bouquet->addService(ref, before);
846 RESULT eDVBServiceList::removeService(eServiceReference &ref)
850 return m_bouquet->removeService(ref);
853 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
857 return m_bouquet->moveService(ref, pos);
860 RESULT eDVBServiceList::flushChanges()
864 return m_bouquet->flushChanges();
867 RESULT eDVBServiceList::setListName(const std::string &name)
871 return m_bouquet->setListName(name);
874 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
876 ePtr<eDVBService> service;
877 int r = lookupService(service, ref);
880 // check resources...
881 ptr = new eDVBServicePlay(ref, service);
885 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
887 if (ref.path.empty())
889 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
898 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
900 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
901 if (list->startQuery())
911 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
913 /* is a listable service? */
914 if (ref.flags & eServiceReference::canDescent) // bouquet
916 if ( !ref.name.empty() ) // satellites or providers list
917 ptr = m_StaticServiceDVBInfo;
918 else // a dvb bouquet
919 ptr = m_StaticServiceDVBBouquetInfo;
921 else if (!ref.path.empty()) /* do we have a PVR service? */
922 ptr = new eStaticServiceDVBPVRInformation(ref);
923 else // normal dvb service
925 ePtr<eDVBService> service;
926 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
927 ptr = m_StaticServiceDVBInfo;
929 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
935 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
937 if (ref.path.empty())
943 ptr = new eDVBPVRServiceOfflineOperations(ref);
948 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
950 // TODO: handle the listing itself
951 // if (ref.... == -1) .. return "... bouquets ...";
952 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
954 ePtr<iDVBChannelList> db;
955 ePtr<eDVBResourceManager> res;
958 if ((err = eDVBResourceManager::getInstance(res)) != 0)
960 eDebug("no resource manager");
963 if ((err = res->getChannelList(db)) != 0)
965 eDebug("no channel list");
969 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
970 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
972 eDebug("getService failed!");
979 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
980 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
982 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
984 m_is_pvr = !m_reference.path.empty();
986 m_timeshift_enabled = m_timeshift_active = 0;
989 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
990 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
991 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
993 m_cuesheet_changed = 0;
994 m_cutlist_enabled = 1;
996 m_subtitle_widget = 0;
1000 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
1003 eDVBServicePlay::~eDVBServicePlay()
1005 delete m_subtitle_widget;
1008 void eDVBServicePlay::gotNewEvent()
1012 ePtr<eServiceEvent> m_event_now, m_event_next;
1013 getEvent(m_event_now, 0);
1014 getEvent(m_event_next, 1);
1017 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1019 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1021 m_event((iPlayableService*)this, evUpdatedEventInfo);
1024 void eDVBServicePlay::serviceEvent(int event)
1026 m_tune_state = event;
1030 case eDVBServicePMTHandler::eventTuned:
1032 ePtr<iDVBDemux> m_demux;
1033 if (!m_service_handler.getDataDemux(m_demux))
1035 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1036 int sid = ref.getParentServiceID().get();
1038 sid = ref.getServiceID().get();
1039 if ( ref.getParentTransportStreamID().get() &&
1040 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1041 m_event_handler.startOther(m_demux, sid);
1043 m_event_handler.start(m_demux, sid);
1047 case eDVBServicePMTHandler::eventNoPAT:
1048 case eDVBServicePMTHandler::eventNoPATEntry:
1049 case eDVBServicePMTHandler::eventNoPMT:
1050 case eDVBServicePMTHandler::eventTuneFailed:
1052 eDebug("DVB service failed to tune - error %d", event);
1053 m_event((iPlayableService*)this, evTuneFailed);
1056 case eDVBServicePMTHandler::eventNewProgramInfo:
1058 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1059 if (m_timeshift_enabled)
1060 updateTimeshiftPids();
1061 if (!m_timeshift_active)
1063 if (m_first_program_info && m_is_pvr)
1065 m_first_program_info = 0;
1068 m_event((iPlayableService*)this, evUpdatedInfo);
1071 case eDVBServicePMTHandler::eventEOF:
1072 m_event((iPlayableService*)this, evEOF);
1074 case eDVBServicePMTHandler::eventSOF:
1075 m_event((iPlayableService*)this, evSOF);
1080 void eDVBServicePlay::serviceEventTimeshift(int event)
1084 case eDVBServicePMTHandler::eventNewProgramInfo:
1085 if (m_timeshift_active)
1088 case eDVBServicePMTHandler::eventSOF:
1089 m_event((iPlayableService*)this, evSOF);
1091 case eDVBServicePMTHandler::eventEOF:
1097 RESULT eDVBServicePlay::start()
1100 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1101 two (one for decoding, one for data source), as we must be prepared
1102 to start recording from the data demux. */
1104 m_cue = new eCueSheet();
1106 m_first_program_info = 1;
1107 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1108 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1110 /* inject EIT if there is a stored one */
1113 std::string filename = service.path;
1114 filename.erase(filename.length()-2, 2);
1116 ePtr<eServiceEvent> event = new eServiceEvent;
1117 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1119 ePtr<eServiceEvent> empty;
1120 m_event_handler.inject(event, 0);
1121 m_event_handler.inject(empty, 1);
1128 m_event(this, evStart);
1129 m_event((iPlayableService*)this, evSeekableStatusChanged);
1133 RESULT eDVBServicePlay::stop()
1135 /* add bookmark for last play position */
1138 pts_t play_position;
1139 if (!getPlayPosition(play_position))
1141 /* remove last position */
1142 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1144 if (i->what == 3) /* current play position */
1146 m_cue_entries.erase(i);
1147 i = m_cue_entries.begin();
1153 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1154 m_cuesheet_changed = 1;
1158 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1160 m_service_handler_timeshift.free();
1161 m_service_handler.free();
1163 if (m_is_pvr && m_cuesheet_changed)
1166 /* save cuesheet only when main file is accessible. */
1167 if (!::stat(m_reference.path.c_str(), &s))
1174 RESULT eDVBServicePlay::setTarget(int target)
1176 m_is_primary = !target;
1180 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1182 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1186 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1188 /* note: we check for timeshift to be enabled,
1189 not neccessary active. if you pause when timeshift
1190 is not active, you should activate it when unpausing */
1191 if ((!m_is_pvr) && (!m_timeshift_enabled))
1201 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1204 return m_decoder->setSlowMotion(ratio);
1209 RESULT eDVBServicePlay::setFastForward(int ratio)
1211 int skipmode, ffratio;
1217 } else if (ratio > 0)
1225 } else // if (ratio < 0)
1231 if (m_skipmode != skipmode)
1233 eDebug("setting cue skipmode to %d", skipmode);
1235 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1238 m_skipmode = skipmode;
1243 return m_decoder->setFastForward(ffratio);
1246 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1248 if (m_is_pvr || m_timeshift_enabled)
1258 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1259 RESULT eDVBServicePlay::getLength(pts_t &len)
1261 ePtr<iDVBPVRChannel> pvr_channel;
1263 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1266 return pvr_channel->getLength(len);
1269 RESULT eDVBServicePlay::pause()
1271 if (!m_is_paused && m_decoder)
1274 return m_decoder->freeze(0);
1279 RESULT eDVBServicePlay::unpause()
1281 if (m_is_paused && m_decoder)
1284 return m_decoder->unfreeze();
1289 RESULT eDVBServicePlay::seekTo(pts_t to)
1291 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1293 if (!m_decode_demux)
1296 ePtr<iDVBPVRChannel> pvr_channel;
1298 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1304 m_cue->seekTo(0, to);
1308 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1310 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1312 if (!m_decode_demux)
1315 ePtr<iDVBPVRChannel> pvr_channel;
1317 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1322 /* HACK until we have skip-AP api */
1323 if ((to > 0) && (to < 100))
1331 m_cue->seekTo(mode, to);
1335 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1337 ePtr<iDVBPVRChannel> pvr_channel;
1339 if (!m_decode_demux)
1342 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1347 /* if there is a decoder, use audio or video PTS */
1350 r = m_decoder->getPTS(0, pos);
1356 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1359 RESULT eDVBServicePlay::setTrickmode(int trick)
1362 m_decoder->setTrickmode(trick);
1366 RESULT eDVBServicePlay::isCurrentlySeekable()
1368 return m_is_pvr || m_timeshift_active;
1371 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1377 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1383 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1389 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1395 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1401 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1404 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1405 (m_timeshift_enabled || !m_is_pvr))
1407 if (!m_timeshift_enabled)
1409 /* we need enough diskspace */
1411 if (statfs(TSPATH "/.", &fs) < 0)
1413 eDebug("statfs failed!");
1417 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1419 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1429 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1440 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1446 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1452 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1458 RESULT eDVBServicePlay::getName(std::string &name)
1462 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1463 return i->getName(m_reference, name);
1467 m_dvb_service->getName(m_reference, name);
1471 else if (!m_reference.name.empty())
1472 eStaticServiceDVBInformation().getName(m_reference, name);
1474 name = "DVB service";
1478 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1480 return m_event_handler.getEvent(evt, nownext);
1483 int eDVBServicePlay::getInfo(int w)
1485 eDVBServicePMTHandler::program program;
1488 return resIsPyObject;
1490 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1492 int no_program_info = 0;
1494 if (h.getProgramInfo(program))
1495 no_program_info = 1;
1499 #if HAVE_DVB_API_VERSION >= 3
1501 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1502 return m_videoEventData.height;
1505 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1506 return m_videoEventData.width;
1509 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1512 #if HAVE_DVB_API_VERSION >= 3
1513 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1514 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1517 #warning "FIXMEE implement sAspect for old DVB API"
1519 if (no_program_info)
1521 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1523 ePtr<eServiceEvent> evt;
1524 if (!m_event_handler.getEvent(evt, 0))
1526 ePtr<eComponentData> data;
1527 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1529 if ( data->getStreamContent() == 1 )
1531 switch(data->getComponentType())
1534 case 1: // 4:3 SD PAL
1536 case 3: // 16:9 SD PAL
1537 case 4: // > 16:9 PAL
1538 case 5: // 4:3 SD NTSC
1540 case 7: // 16:9 SD NTSC
1541 case 8: // > 16:9 NTSC
1544 case 9: // 4:3 HD PAL
1546 case 0xB: // 16:9 HD PAL
1547 case 0xC: // > 16:9 HD PAL
1548 case 0xD: // 4:3 HD NTSC
1550 case 0xF: // 16:9 HD NTSC
1551 case 0x10: // > 16:9 HD PAL
1552 return data->getComponentType();
1559 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1560 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1561 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1562 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1563 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1564 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1565 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1566 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1567 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1568 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1569 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1570 case sProvider: if (!m_dvb_service) return -1; return -2;
1571 case sServiceref: return resIsString;
1572 case sDVBState: return m_tune_state;
1578 std::string eDVBServicePlay::getInfoString(int w)
1583 if (!m_dvb_service) return "";
1584 return m_dvb_service->m_provider_name;
1586 return m_reference.toString();
1590 return iServiceInformation::getInfoString(w);
1593 PyObject *eDVBServicePlay::getInfoObject(int w)
1598 return m_service_handler.getCaIds();
1599 case sTransponderData:
1600 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1604 return iServiceInformation::getInfoObject(w);
1607 int eDVBServicePlay::getNumberOfTracks()
1609 eDVBServicePMTHandler::program program;
1610 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1611 if (h.getProgramInfo(program))
1613 return program.audioStreams.size();
1616 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1618 int ret = selectAudioStream(i);
1620 if (m_decoder->start())
1626 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1628 eDVBServicePMTHandler::program program;
1629 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1631 if (h.getProgramInfo(program))
1634 if (i >= program.audioStreams.size())
1637 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1638 info.m_description = "MPEG";
1639 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1640 info.m_description = "AC3";
1641 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1642 info.m_description = "AAC";
1643 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1644 info.m_description = "DTS";
1646 info.m_description = "???";
1648 if (program.audioStreams[i].component_tag != -1)
1650 ePtr<eServiceEvent> evt;
1651 if (!m_event_handler.getEvent(evt, 0))
1653 ePtr<eComponentData> data;
1654 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1655 info.m_language = data->getText();
1659 if (info.m_language.empty())
1660 info.m_language = program.audioStreams[i].language_code;
1665 int eDVBServicePlay::selectAudioStream(int i)
1667 eDVBServicePMTHandler::program program;
1668 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1670 if (h.getProgramInfo(program))
1673 if ((unsigned int)i >= program.audioStreams.size())
1679 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1682 if (m_radiotext_parser)
1683 m_radiotext_parser->start(program.audioStreams[i].pid);
1685 if (m_dvb_service && !m_is_pvr)
1687 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1689 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1690 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1694 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1695 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1699 h.resetCachedProgram();
1704 int eDVBServicePlay::getCurrentChannel()
1706 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1709 RESULT eDVBServicePlay::selectChannel(int i)
1711 if (i < LEFT || i > RIGHT || i == STEREO)
1714 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1716 m_decoder->setAudioChannel(i);
1720 std::string eDVBServicePlay::getRadioText(int x)
1722 if (m_radiotext_parser)
1726 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1731 void eDVBServicePlay::radioTextUpdated()
1733 m_event((iPlayableService*)this, evUpdatedRadioText);
1736 int eDVBServiceBase::getFrontendInfo(int w)
1738 eUsePtr<iDVBChannel> channel;
1739 if(m_service_handler.getChannel(channel))
1741 ePtr<iDVBFrontend> fe;
1742 if(channel->getFrontend(fe))
1744 return fe->readFrontendData(w);
1747 PyObject *eDVBServiceBase::getFrontendData(bool original)
1751 eUsePtr<iDVBChannel> channel;
1752 if(!m_service_handler.getChannel(channel))
1754 ePtr<iDVBFrontend> fe;
1755 if(!channel->getFrontend(fe))
1757 ret = fe->readTransponderData(original);
1760 ePtr<iDVBFrontendParameters> feparm;
1761 channel->getCurrentFrontendParameters(feparm);
1764 eDVBFrontendParametersSatellite osat;
1765 if (!feparm->getDVBS(osat))
1767 void PutToDict(ePyObject &, const char*, long);
1768 void PutToDict(ePyObject &, const char*, const char*);
1769 PutToDict(ret, "orbital_position", osat.orbital_position);
1770 const char *tmp = "UNKNOWN";
1771 switch(osat.polarisation)
1773 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1774 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1775 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1776 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1779 PutToDict(ret, "polarization", tmp);
1790 int eDVBServicePlay::getNumberOfSubservices()
1792 ePtr<eServiceEvent> evt;
1793 if (!m_event_handler.getEvent(evt, 0))
1794 return evt->getNumOfLinkageServices();
1798 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1800 ePtr<eServiceEvent> evt;
1801 if (!m_event_handler.getEvent(evt, 0))
1803 if (!evt->getLinkageService(sub, m_reference, n))
1806 sub.type=eServiceReference::idInvalid;
1810 RESULT eDVBServicePlay::startTimeshift()
1812 ePtr<iDVBDemux> demux;
1814 eDebug("Start timeshift!");
1816 if (m_timeshift_enabled)
1819 /* start recording with the data demux. */
1820 if (m_service_handler.getDataDemux(demux))
1823 demux->createTSRecorder(m_record);
1827 char templ[]=TSPATH "/timeshift.XXXXXX";
1828 m_timeshift_fd = mkstemp(templ);
1829 m_timeshift_file = templ;
1831 eDebug("recording to %s", templ);
1833 if (m_timeshift_fd < 0)
1839 m_record->setTargetFD(m_timeshift_fd);
1841 m_timeshift_enabled = 1;
1843 updateTimeshiftPids();
1849 RESULT eDVBServicePlay::stopTimeshift()
1851 if (!m_timeshift_enabled)
1856 m_timeshift_enabled = 0;
1861 close(m_timeshift_fd);
1862 eDebug("remove timeshift file");
1863 remove(m_timeshift_file.c_str());
1868 int eDVBServicePlay::isTimeshiftActive()
1870 return m_timeshift_enabled && m_timeshift_active;
1873 RESULT eDVBServicePlay::activateTimeshift()
1875 if (!m_timeshift_enabled)
1878 if (!m_timeshift_active)
1880 switchToTimeshift();
1887 PyObject *eDVBServicePlay::getCutList()
1889 ePyObject list = PyList_New(0);
1891 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1893 ePyObject tuple = PyTuple_New(2);
1894 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1895 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1896 PyList_Append(list, tuple);
1903 void eDVBServicePlay::setCutList(ePyObject list)
1905 if (!PyList_Check(list))
1907 int size = PyList_Size(list);
1910 m_cue_entries.clear();
1912 for (i=0; i<size; ++i)
1914 ePyObject tuple = PyList_GET_ITEM(list, i);
1915 if (!PyTuple_Check(tuple))
1917 eDebug("non-tuple in cutlist");
1920 if (PyTuple_Size(tuple) != 2)
1922 eDebug("cutlist entries need to be a 2-tuple");
1925 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1926 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1928 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1931 pts_t pts = PyLong_AsLongLong(ppts);
1932 int type = PyInt_AsLong(ptype);
1933 m_cue_entries.insert(cueEntry(pts, type));
1934 eDebug("adding %08llx, %d", pts, type);
1936 m_cuesheet_changed = 1;
1938 cutlistToCuesheet();
1939 m_event((iPlayableService*)this, evCuesheetChanged);
1942 void eDVBServicePlay::setCutListEnable(int enable)
1944 m_cutlist_enabled = enable;
1945 cutlistToCuesheet();
1948 void eDVBServicePlay::updateTimeshiftPids()
1953 eDVBServicePMTHandler::program program;
1954 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1956 if (h.getProgramInfo(program))
1960 std::set<int> pids_to_record;
1961 pids_to_record.insert(0); // PAT
1962 if (program.pmtPid != -1)
1963 pids_to_record.insert(program.pmtPid); // PMT
1965 if (program.textPid != -1)
1966 pids_to_record.insert(program.textPid); // Videotext
1968 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1969 i(program.videoStreams.begin());
1970 i != program.videoStreams.end(); ++i)
1971 pids_to_record.insert(i->pid);
1973 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1974 i(program.audioStreams.begin());
1975 i != program.audioStreams.end(); ++i)
1976 pids_to_record.insert(i->pid);
1978 std::set<int> new_pids, obsolete_pids;
1980 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1981 m_pids_active.begin(), m_pids_active.end(),
1982 std::inserter(new_pids, new_pids.begin()));
1984 std::set_difference(
1985 m_pids_active.begin(), m_pids_active.end(),
1986 pids_to_record.begin(), pids_to_record.end(),
1987 std::inserter(new_pids, new_pids.begin())
1990 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1991 m_record->addPID(*i);
1993 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1994 m_record->removePID(*i);
1998 void eDVBServicePlay::switchToLive()
2000 if (!m_timeshift_active)
2006 m_teletext_parser = 0;
2007 m_radiotext_parser = 0;
2008 m_subtitle_parser = 0;
2009 m_new_dvb_subtitle_page_connection = 0;
2010 m_new_subtitle_page_connection = 0;
2011 m_radiotext_updated_connection = 0;
2013 /* free the timeshift service handler, we need the resources */
2014 m_service_handler_timeshift.free();
2015 m_timeshift_active = 0;
2017 m_event((iPlayableService*)this, evSeekableStatusChanged);
2022 void eDVBServicePlay::switchToTimeshift()
2024 if (m_timeshift_active)
2029 m_teletext_parser = 0;
2030 m_radiotext_parser = 0;
2031 m_subtitle_parser = 0;
2032 m_new_subtitle_page_connection = 0;
2033 m_new_dvb_subtitle_page_connection = 0;
2034 m_radiotext_updated_connection = 0;
2036 m_timeshift_active = 1;
2038 m_event((iPlayableService*)this, evSeekableStatusChanged);
2040 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2041 r.path = m_timeshift_file;
2043 m_cue = new eCueSheet();
2044 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2045 updateDecoder(); /* mainly to switch off PCR */
2048 void eDVBServicePlay::updateDecoder()
2050 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2052 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2054 bool defaultac3=false;
2055 std::string default_ac3;
2057 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2058 defaultac3 = default_ac3 == "True";
2060 eDVBServicePMTHandler::program program;
2061 if (h.getProgramInfo(program))
2062 eDebug("getting program info failed.");
2065 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2066 if (!program.videoStreams.empty())
2068 eDebugNoNewLine(" (");
2069 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2070 i(program.videoStreams.begin());
2071 i != program.videoStreams.end(); ++i)
2078 if (i != program.videoStreams.begin())
2079 eDebugNoNewLine(", ");
2080 eDebugNoNewLine("%04x", i->pid);
2082 eDebugNoNewLine(")");
2084 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2085 if (!program.audioStreams.empty())
2087 eDebugNoNewLine(" (");
2088 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2089 i(program.audioStreams.begin());
2090 i != program.audioStreams.end(); ++i)
2092 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2094 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2100 if (i != program.audioStreams.begin())
2101 eDebugNoNewLine(", ");
2102 eDebugNoNewLine("%04x", i->pid);
2104 eDebugNoNewLine(")");
2106 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2107 pcrpid = program.pcrPid;
2108 eDebug(", and the text pid is %04x", program.textPid);
2109 tpid = program.textPid;
2114 h.getDecodeDemux(m_decode_demux);
2117 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2119 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2122 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2123 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2124 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2125 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2126 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2133 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2134 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2135 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2137 else // subservice or recording
2139 eServiceReferenceDVB ref;
2140 m_service_handler.getServiceReference(ref);
2141 eServiceReferenceDVB parent = ref.getParentServiceReference();
2146 ePtr<eDVBResourceManager> res_mgr;
2147 if (!eDVBResourceManager::getInstance(res_mgr))
2149 ePtr<iDVBChannelList> db;
2150 if (!res_mgr->getChannelList(db))
2152 ePtr<eDVBService> origService;
2153 if (!db->getService(parent, origService))
2155 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2156 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2162 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2163 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2165 m_decoder->setVideoPID(vpid, vpidtype);
2166 m_decoder->setAudioPID(apid, apidtype);
2167 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2169 m_decoder->setSyncPCR(pcrpid);
2172 ePtr<iDVBDemux> data_demux;
2173 if (!h.getDataDemux(data_demux))
2175 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
2176 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
2177 m_radiotext_parser->start(apid);
2182 m_decoder->setSyncPCR(-1);
2184 m_decoder->setTextPID(tpid);
2186 m_teletext_parser->start(program.textPid);
2189 m_decoder->setTrickmode(1);
2193 if (vpid > 0 && vpid < 0x2000)
2197 std::string radio_pic;
2198 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2199 m_decoder->setRadioPic(radio_pic);
2202 m_decoder->setAudioChannel(achannel);
2204 // how we can do this better?
2205 // update cache pid when the user changed the audio track or video track
2206 // TODO handling of difference audio types.. default audio types..
2208 /* don't worry about non-existing services, nor pvr services */
2209 if (m_dvb_service && !m_is_pvr)
2211 if (apidtype == eDVBAudio::aMPEG)
2213 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2214 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2218 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2219 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2221 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2222 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2223 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2224 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2227 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2230 void eDVBServicePlay::loadCuesheet()
2232 std::string filename = m_reference.path + ".cuts";
2234 m_cue_entries.clear();
2236 FILE *f = fopen(filename.c_str(), "rb");
2240 eDebug("loading cuts..");
2243 unsigned long long where;
2246 if (!fread(&where, sizeof(where), 1, f))
2248 if (!fread(&what, sizeof(what), 1, f))
2251 #if BYTE_ORDER == LITTLE_ENDIAN
2252 where = bswap_64(where);
2259 m_cue_entries.insert(cueEntry(where, what));
2262 eDebug("%d entries", m_cue_entries.size());
2264 eDebug("cutfile not found!");
2266 m_cuesheet_changed = 0;
2267 cutlistToCuesheet();
2268 m_event((iPlayableService*)this, evCuesheetChanged);
2271 void eDVBServicePlay::saveCuesheet()
2273 std::string filename = m_reference.path + ".cuts";
2275 FILE *f = fopen(filename.c_str(), "wb");
2279 unsigned long long where;
2282 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2284 #if BYTE_ORDER == BIG_ENDIAN
2287 where = bswap_64(i->where);
2289 what = htonl(i->what);
2290 fwrite(&where, sizeof(where), 1, f);
2291 fwrite(&what, sizeof(what), 1, f);
2297 m_cuesheet_changed = 0;
2300 void eDVBServicePlay::cutlistToCuesheet()
2304 eDebug("no cue sheet");
2309 if (!m_cutlist_enabled)
2311 m_cue->commitSpans();
2312 eDebug("cutlists were disabled");
2316 pts_t in = 0, out = 0, length = 0;
2320 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2324 if (i == m_cue_entries.end())
2327 if (i->what == 0) /* in */
2331 } else if (i->what == 1) /* out */
2333 else /* mark (2) or last play position (3) */
2341 m_cue->addSourceSpan(in, out);
2345 if (i == m_cue_entries.end())
2348 m_cue->commitSpans();
2351 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2353 if (m_subtitle_widget)
2354 disableSubtitles(parent);
2357 int tuplesize = PyTuple_Size(tuple);
2360 if (!PyTuple_Check(tuple))
2366 entry = PyTuple_GET_ITEM(tuple, 0);
2368 if (!PyInt_Check(entry))
2371 type = PyInt_AsLong(entry);
2373 if (type == 1) // teletext subtitles
2375 int page, magazine, pid;
2379 if (!m_teletext_parser)
2381 eDebug("enable teletext subtitles.. no parser !!!");
2385 entry = PyTuple_GET_ITEM(tuple, 1);
2386 if (!PyInt_Check(entry))
2388 pid = PyInt_AsLong(entry);
2390 entry = PyTuple_GET_ITEM(tuple, 2);
2391 if (!PyInt_Check(entry))
2393 page = PyInt_AsLong(entry);
2395 entry = PyTuple_GET_ITEM(tuple, 3);
2396 if (!PyInt_Check(entry))
2398 magazine = PyInt_AsLong(entry);
2400 m_subtitle_widget = new eSubtitleWidget(parent);
2401 m_subtitle_widget->resize(parent->size()); /* full size */
2402 m_teletext_parser->setPageAndMagazine(page, magazine);
2404 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2408 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2409 if (!m_subtitle_parser)
2411 eDebug("enable dvb subtitles.. no parser !!!");
2417 entry = PyTuple_GET_ITEM(tuple, 1);
2418 if (!PyInt_Check(entry))
2420 pid = PyInt_AsLong(entry);
2422 entry = PyTuple_GET_ITEM(tuple, 2);
2423 if (!PyInt_Check(entry))
2425 composition_page_id = PyInt_AsLong(entry);
2427 entry = PyTuple_GET_ITEM(tuple, 3);
2428 if (!PyInt_Check(entry))
2430 ancillary_page_id = PyInt_AsLong(entry);
2432 m_subtitle_widget = new eSubtitleWidget(parent);
2433 m_subtitle_widget->resize(parent->size()); /* full size */
2434 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2436 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2442 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2443 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2444 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2448 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2450 delete m_subtitle_widget;
2451 m_subtitle_widget = 0;
2452 if (m_subtitle_parser)
2454 m_subtitle_parser->stop();
2455 m_dvb_subtitle_pages.clear();
2457 if (m_teletext_parser)
2459 m_teletext_parser->setPageAndMagazine(-1, -1);
2460 m_subtitle_pages.clear();
2463 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2467 PyObject *eDVBServicePlay::getCachedSubtitle()
2471 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2474 unsigned int data = (unsigned int)tmp;
2475 int pid = (data&0xFFFF0000)>>16;
2476 ePyObject tuple = PyTuple_New(4);
2477 eDVBServicePMTHandler::program program;
2478 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2479 if (!h.getProgramInfo(program))
2481 if (program.textPid==pid) // teletext
2482 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2484 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2485 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2486 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2487 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2495 PyObject *eDVBServicePlay::getSubtitleList()
2497 if (!m_teletext_parser)
2500 ePyObject l = PyList_New(0);
2501 std::set<int> added_ttx_pages;
2503 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2504 m_teletext_parser->m_found_subtitle_pages;
2506 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2507 eDVBServicePMTHandler::program program;
2508 if (h.getProgramInfo(program))
2509 eDebug("getting program info failed.");
2512 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2513 it != program.subtitleStreams.end(); ++it)
2515 switch(it->subtitling_type)
2517 case 0x01: // ebu teletext subtitles
2519 int page_number = it->teletext_page_number & 0xFF;
2520 int magazine_number = it->teletext_magazine_number & 7;
2521 int hash = magazine_number << 8 | page_number;
2522 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2524 ePyObject tuple = PyTuple_New(5);
2525 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2526 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2527 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2528 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2529 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2530 PyList_Append(l, tuple);
2532 added_ttx_pages.insert(hash);
2537 case 0x20 ... 0x23: // dvb subtitles
2539 ePyObject tuple = PyTuple_New(5);
2540 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2541 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2542 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2543 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2544 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2545 PyList_Insert(l, 0, tuple);
2553 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2554 it != subs.end(); ++it)
2556 int page_number = it->teletext_page_number & 0xFF;
2557 int magazine_number = it->teletext_magazine_number & 7;
2558 int hash = magazine_number << 8 | page_number;
2559 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2561 ePyObject tuple = PyTuple_New(5);
2562 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2563 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2564 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2565 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2566 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2567 PyList_Append(l, tuple);
2575 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2577 if (m_subtitle_widget)
2579 m_subtitle_pages.push_back(page);
2580 checkSubtitleTiming();
2584 void eDVBServicePlay::checkSubtitleTiming()
2586 // eDebug("checkSubtitleTiming");
2587 if (!m_subtitle_widget)
2591 enum { TELETEXT, DVB } type;
2592 eDVBTeletextSubtitlePage page;
2593 eDVBSubtitlePage dvb_page;
2595 if (!m_subtitle_pages.empty())
2597 page = m_subtitle_pages.front();
2599 show_time = page.m_pts;
2601 else if (!m_dvb_subtitle_pages.empty())
2603 dvb_page = m_dvb_subtitle_pages.front();
2605 show_time = dvb_page.m_show_time;
2613 m_decoder->getPTS(0, pos);
2615 // eDebug("%lld %lld", pos, show_time);
2616 int diff = show_time - pos;
2619 eDebug("[late (%d ms)]", -diff / 90);
2624 eDebug("[invalid]");
2630 if (type == TELETEXT)
2632 eDebug("display teletext subtitle page");
2633 m_subtitle_widget->setPage(page);
2634 m_subtitle_pages.pop_front();
2638 eDebug("display dvb subtitle Page");
2639 m_subtitle_widget->setPage(dvb_page);
2640 m_dvb_subtitle_pages.pop_front();
2644 // eDebug("start subtitle delay %d", diff / 90);
2645 m_subtitle_sync_timer.start(diff / 90, 1);
2651 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2653 if (m_subtitle_widget)
2655 m_dvb_subtitle_pages.push_back(p);
2656 checkSubtitleTiming();
2660 int eDVBServicePlay::getAC3Delay()
2663 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2665 return m_decoder->getAC3Delay();
2670 int eDVBServicePlay::getPCMDelay()
2673 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2675 return m_decoder->getPCMDelay();
2680 void eDVBServicePlay::setAC3Delay(int delay)
2683 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2685 m_decoder->setAC3Delay(delay);
2688 void eDVBServicePlay::setPCMDelay(int delay)
2691 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2693 m_decoder->setPCMDelay(delay);
2696 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2698 eDebug("!!!!!!!!!! Video Event type %d, aspect %d, %dx%d", event.type, event.aspect, event.width, event.height);
2699 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2700 m_event((iPlayableService*)this, evVideoSizeChanged);
2703 DEFINE_REF(eDVBServicePlay)
2705 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");