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::eventNoPAT:
1053 case eDVBServicePMTHandler::eventNoPATEntry:
1054 case eDVBServicePMTHandler::eventNoPMT:
1055 case eDVBServicePMTHandler::eventTuneFailed:
1057 eDebug("DVB service failed to tune - error %d", event);
1058 m_event((iPlayableService*)this, evTuneFailed);
1061 case eDVBServicePMTHandler::eventNewProgramInfo:
1063 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1064 if (m_timeshift_enabled)
1065 updateTimeshiftPids();
1066 if (!m_timeshift_active)
1068 if (m_first_program_info && m_is_pvr)
1070 m_first_program_info = 0;
1073 m_event((iPlayableService*)this, evUpdatedInfo);
1076 case eDVBServicePMTHandler::eventEOF:
1077 m_event((iPlayableService*)this, evEOF);
1079 case eDVBServicePMTHandler::eventSOF:
1080 m_event((iPlayableService*)this, evSOF);
1085 void eDVBServicePlay::serviceEventTimeshift(int event)
1089 case eDVBServicePMTHandler::eventNewProgramInfo:
1090 if (m_timeshift_active)
1093 case eDVBServicePMTHandler::eventSOF:
1094 m_event((iPlayableService*)this, evSOF);
1096 case eDVBServicePMTHandler::eventEOF:
1102 RESULT eDVBServicePlay::start()
1105 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1106 two (one for decoding, one for data source), as we must be prepared
1107 to start recording from the data demux. */
1109 m_cue = new eCueSheet();
1111 m_first_program_info = 1;
1112 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1113 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1115 /* inject EIT if there is a stored one */
1118 std::string filename = service.path;
1119 filename.erase(filename.length()-2, 2);
1121 ePtr<eServiceEvent> event = new eServiceEvent;
1122 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1124 ePtr<eServiceEvent> empty;
1125 m_event_handler.inject(event, 0);
1126 m_event_handler.inject(empty, 1);
1133 m_event(this, evStart);
1134 m_event((iPlayableService*)this, evSeekableStatusChanged);
1138 RESULT eDVBServicePlay::stop()
1140 /* add bookmark for last play position */
1143 pts_t play_position;
1144 if (!getPlayPosition(play_position))
1146 /* remove last position */
1147 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1149 if (i->what == 3) /* current play position */
1151 m_cue_entries.erase(i);
1152 i = m_cue_entries.begin();
1158 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1159 m_cuesheet_changed = 1;
1163 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1165 m_service_handler_timeshift.free();
1166 m_service_handler.free();
1168 if (m_is_pvr && m_cuesheet_changed)
1171 /* save cuesheet only when main file is accessible. */
1172 if (!::stat(m_reference.path.c_str(), &s))
1179 RESULT eDVBServicePlay::setTarget(int target)
1181 m_is_primary = !target;
1185 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1187 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1191 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1193 /* note: we check for timeshift to be enabled,
1194 not neccessary active. if you pause when timeshift
1195 is not active, you should activate it when unpausing */
1196 if ((!m_is_pvr) && (!m_timeshift_enabled))
1206 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1209 return m_decoder->setSlowMotion(ratio);
1214 RESULT eDVBServicePlay::setFastForward(int ratio)
1216 int skipmode, ffratio;
1222 } else if (ratio > 0)
1230 } else // if (ratio < 0)
1236 if (m_skipmode != skipmode)
1238 eDebug("setting cue skipmode to %d", skipmode);
1240 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1243 m_skipmode = skipmode;
1248 return m_decoder->setFastForward(ffratio);
1251 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1253 if (m_is_pvr || m_timeshift_enabled)
1263 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1264 RESULT eDVBServicePlay::getLength(pts_t &len)
1266 ePtr<iDVBPVRChannel> pvr_channel;
1268 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1271 return pvr_channel->getLength(len);
1274 RESULT eDVBServicePlay::pause()
1276 if (!m_is_paused && m_decoder)
1279 return m_decoder->freeze(0);
1284 RESULT eDVBServicePlay::unpause()
1286 if (m_is_paused && m_decoder)
1289 return m_decoder->unfreeze();
1294 RESULT eDVBServicePlay::seekTo(pts_t to)
1296 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1298 if (!m_decode_demux)
1301 ePtr<iDVBPVRChannel> pvr_channel;
1303 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1309 m_cue->seekTo(0, to);
1313 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1315 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1317 if (!m_decode_demux)
1320 ePtr<iDVBPVRChannel> pvr_channel;
1322 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1327 /* HACK until we have skip-AP api */
1328 if ((to > 0) && (to < 100))
1336 m_cue->seekTo(mode, to);
1340 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1342 ePtr<iDVBPVRChannel> pvr_channel;
1344 if (!m_decode_demux)
1347 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1352 /* if there is a decoder, use audio or video PTS */
1355 r = m_decoder->getPTS(0, pos);
1361 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1364 RESULT eDVBServicePlay::setTrickmode(int trick)
1367 m_decoder->setTrickmode(trick);
1371 RESULT eDVBServicePlay::isCurrentlySeekable()
1373 return m_is_pvr || m_timeshift_active;
1376 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1382 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1388 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1394 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1400 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1406 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1409 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1410 (m_timeshift_enabled || !m_is_pvr))
1412 if (!m_timeshift_enabled)
1414 /* we need enough diskspace */
1416 if (statfs(TSPATH "/.", &fs) < 0)
1418 eDebug("statfs failed!");
1422 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1424 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1434 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1445 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1451 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1457 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1463 RESULT eDVBServicePlay::getName(std::string &name)
1467 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1468 return i->getName(m_reference, name);
1472 m_dvb_service->getName(m_reference, name);
1476 else if (!m_reference.name.empty())
1477 eStaticServiceDVBInformation().getName(m_reference, name);
1479 name = "DVB service";
1483 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1485 return m_event_handler.getEvent(evt, nownext);
1488 int eDVBServicePlay::getInfo(int w)
1490 eDVBServicePMTHandler::program program;
1493 return resIsPyObject;
1495 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1497 int no_program_info = 0;
1499 if (h.getProgramInfo(program))
1500 no_program_info = 1;
1504 #if HAVE_DVB_API_VERSION >= 3
1506 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1507 return m_videoEventData.height;
1510 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1511 return m_videoEventData.width;
1514 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1517 #if HAVE_DVB_API_VERSION >= 3
1518 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1519 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1522 #warning "FIXMEE implement sAspect for old DVB API"
1524 if (no_program_info)
1526 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1528 ePtr<eServiceEvent> evt;
1529 if (!m_event_handler.getEvent(evt, 0))
1531 ePtr<eComponentData> data;
1532 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1534 if ( data->getStreamContent() == 1 )
1536 switch(data->getComponentType())
1539 case 1: // 4:3 SD PAL
1541 case 3: // 16:9 SD PAL
1542 case 4: // > 16:9 PAL
1543 case 5: // 4:3 SD NTSC
1545 case 7: // 16:9 SD NTSC
1546 case 8: // > 16:9 NTSC
1549 case 9: // 4:3 HD PAL
1551 case 0xB: // 16:9 HD PAL
1552 case 0xC: // > 16:9 HD PAL
1553 case 0xD: // 4:3 HD NTSC
1555 case 0xF: // 16:9 HD NTSC
1556 case 0x10: // > 16:9 HD PAL
1557 return data->getComponentType();
1564 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1565 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1566 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1567 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1568 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1569 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1570 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1571 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1572 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1573 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1574 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1575 case sProvider: if (!m_dvb_service) return -1; return -2;
1576 case sServiceref: return resIsString;
1577 case sDVBState: return m_tune_state;
1583 std::string eDVBServicePlay::getInfoString(int w)
1588 if (!m_dvb_service) return "";
1589 return m_dvb_service->m_provider_name;
1591 return m_reference.toString();
1595 return iServiceInformation::getInfoString(w);
1598 PyObject *eDVBServicePlay::getInfoObject(int w)
1603 return m_service_handler.getCaIds();
1604 case sTransponderData:
1605 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1609 return iServiceInformation::getInfoObject(w);
1612 int eDVBServicePlay::getNumberOfTracks()
1614 eDVBServicePMTHandler::program program;
1615 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1616 if (h.getProgramInfo(program))
1618 return program.audioStreams.size();
1621 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1623 int ret = selectAudioStream(i);
1625 if (m_decoder->start())
1631 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1633 eDVBServicePMTHandler::program program;
1634 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1636 if (h.getProgramInfo(program))
1639 if (i >= program.audioStreams.size())
1642 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1643 info.m_description = "MPEG";
1644 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1645 info.m_description = "AC3";
1646 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1647 info.m_description = "AAC";
1648 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1649 info.m_description = "DTS";
1651 info.m_description = "???";
1653 if (program.audioStreams[i].component_tag != -1)
1655 ePtr<eServiceEvent> evt;
1656 if (!m_event_handler.getEvent(evt, 0))
1658 ePtr<eComponentData> data;
1659 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1660 info.m_language = data->getText();
1664 if (info.m_language.empty())
1665 info.m_language = program.audioStreams[i].language_code;
1670 int eDVBServicePlay::selectAudioStream(int i)
1672 eDVBServicePMTHandler::program program;
1673 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1675 if (h.getProgramInfo(program))
1678 if ((unsigned int)i >= program.audioStreams.size())
1684 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1687 if (m_radiotext_parser)
1688 m_radiotext_parser->start(program.audioStreams[i].pid);
1690 if (m_dvb_service && !m_is_pvr)
1692 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1694 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1695 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1699 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1700 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1704 h.resetCachedProgram();
1709 int eDVBServicePlay::getCurrentChannel()
1711 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1714 RESULT eDVBServicePlay::selectChannel(int i)
1716 if (i < LEFT || i > RIGHT || i == STEREO)
1719 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1721 m_decoder->setAudioChannel(i);
1725 std::string eDVBServicePlay::getRadioText(int x)
1727 if (m_radiotext_parser)
1731 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1736 void eDVBServicePlay::radioTextUpdated()
1738 m_event((iPlayableService*)this, evUpdatedRadioText);
1741 int eDVBServiceBase::getFrontendInfo(int w)
1743 eUsePtr<iDVBChannel> channel;
1744 if(m_service_handler.getChannel(channel))
1746 ePtr<iDVBFrontend> fe;
1747 if(channel->getFrontend(fe))
1749 return fe->readFrontendData(w);
1752 PyObject *eDVBServiceBase::getFrontendData(bool original)
1756 eUsePtr<iDVBChannel> channel;
1757 if(!m_service_handler.getChannel(channel))
1759 ePtr<iDVBFrontend> fe;
1760 if(!channel->getFrontend(fe))
1762 ret = fe->readTransponderData(original);
1765 ePtr<iDVBFrontendParameters> feparm;
1766 channel->getCurrentFrontendParameters(feparm);
1769 eDVBFrontendParametersSatellite osat;
1770 if (!feparm->getDVBS(osat))
1772 void PutToDict(ePyObject &, const char*, long);
1773 void PutToDict(ePyObject &, const char*, const char*);
1774 PutToDict(ret, "orbital_position", osat.orbital_position);
1775 const char *tmp = "UNKNOWN";
1776 switch(osat.polarisation)
1778 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1779 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1780 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1781 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1784 PutToDict(ret, "polarization", tmp);
1795 int eDVBServicePlay::getNumberOfSubservices()
1797 ePtr<eServiceEvent> evt;
1798 if (!m_event_handler.getEvent(evt, 0))
1799 return evt->getNumOfLinkageServices();
1803 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1805 ePtr<eServiceEvent> evt;
1806 if (!m_event_handler.getEvent(evt, 0))
1808 if (!evt->getLinkageService(sub, m_reference, n))
1811 sub.type=eServiceReference::idInvalid;
1815 RESULT eDVBServicePlay::startTimeshift()
1817 ePtr<iDVBDemux> demux;
1819 eDebug("Start timeshift!");
1821 if (m_timeshift_enabled)
1824 /* start recording with the data demux. */
1825 if (m_service_handler.getDataDemux(demux))
1828 demux->createTSRecorder(m_record);
1832 char templ[]=TSPATH "/timeshift.XXXXXX";
1833 m_timeshift_fd = mkstemp(templ);
1834 m_timeshift_file = templ;
1836 eDebug("recording to %s", templ);
1838 if (m_timeshift_fd < 0)
1844 m_record->setTargetFD(m_timeshift_fd);
1846 m_timeshift_enabled = 1;
1848 updateTimeshiftPids();
1854 RESULT eDVBServicePlay::stopTimeshift()
1856 if (!m_timeshift_enabled)
1861 m_timeshift_enabled = 0;
1866 close(m_timeshift_fd);
1867 eDebug("remove timeshift file");
1868 remove(m_timeshift_file.c_str());
1873 int eDVBServicePlay::isTimeshiftActive()
1875 return m_timeshift_enabled && m_timeshift_active;
1878 RESULT eDVBServicePlay::activateTimeshift()
1880 if (!m_timeshift_enabled)
1883 if (!m_timeshift_active)
1885 switchToTimeshift();
1892 PyObject *eDVBServicePlay::getCutList()
1894 ePyObject list = PyList_New(0);
1896 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1898 ePyObject tuple = PyTuple_New(2);
1899 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1900 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1901 PyList_Append(list, tuple);
1908 void eDVBServicePlay::setCutList(ePyObject list)
1910 if (!PyList_Check(list))
1912 int size = PyList_Size(list);
1915 m_cue_entries.clear();
1917 for (i=0; i<size; ++i)
1919 ePyObject tuple = PyList_GET_ITEM(list, i);
1920 if (!PyTuple_Check(tuple))
1922 eDebug("non-tuple in cutlist");
1925 if (PyTuple_Size(tuple) != 2)
1927 eDebug("cutlist entries need to be a 2-tuple");
1930 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1931 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1933 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1936 pts_t pts = PyLong_AsLongLong(ppts);
1937 int type = PyInt_AsLong(ptype);
1938 m_cue_entries.insert(cueEntry(pts, type));
1939 eDebug("adding %08llx, %d", pts, type);
1941 m_cuesheet_changed = 1;
1943 cutlistToCuesheet();
1944 m_event((iPlayableService*)this, evCuesheetChanged);
1947 void eDVBServicePlay::setCutListEnable(int enable)
1949 m_cutlist_enabled = enable;
1950 cutlistToCuesheet();
1953 void eDVBServicePlay::updateTimeshiftPids()
1958 eDVBServicePMTHandler::program program;
1959 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1961 if (h.getProgramInfo(program))
1965 std::set<int> pids_to_record;
1966 pids_to_record.insert(0); // PAT
1967 if (program.pmtPid != -1)
1968 pids_to_record.insert(program.pmtPid); // PMT
1970 if (program.textPid != -1)
1971 pids_to_record.insert(program.textPid); // Videotext
1973 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1974 i(program.videoStreams.begin());
1975 i != program.videoStreams.end(); ++i)
1976 pids_to_record.insert(i->pid);
1978 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1979 i(program.audioStreams.begin());
1980 i != program.audioStreams.end(); ++i)
1981 pids_to_record.insert(i->pid);
1983 std::set<int> new_pids, obsolete_pids;
1985 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1986 m_pids_active.begin(), m_pids_active.end(),
1987 std::inserter(new_pids, new_pids.begin()));
1989 std::set_difference(
1990 m_pids_active.begin(), m_pids_active.end(),
1991 pids_to_record.begin(), pids_to_record.end(),
1992 std::inserter(new_pids, new_pids.begin())
1995 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1996 m_record->addPID(*i);
1998 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1999 m_record->removePID(*i);
2003 void eDVBServicePlay::switchToLive()
2005 if (!m_timeshift_active)
2011 m_teletext_parser = 0;
2012 m_radiotext_parser = 0;
2013 m_subtitle_parser = 0;
2014 m_new_dvb_subtitle_page_connection = 0;
2015 m_new_subtitle_page_connection = 0;
2016 m_radiotext_updated_connection = 0;
2018 /* free the timeshift service handler, we need the resources */
2019 m_service_handler_timeshift.free();
2020 m_timeshift_active = 0;
2022 m_event((iPlayableService*)this, evSeekableStatusChanged);
2027 void eDVBServicePlay::switchToTimeshift()
2029 if (m_timeshift_active)
2034 m_teletext_parser = 0;
2035 m_radiotext_parser = 0;
2036 m_subtitle_parser = 0;
2037 m_new_subtitle_page_connection = 0;
2038 m_new_dvb_subtitle_page_connection = 0;
2039 m_radiotext_updated_connection = 0;
2041 m_timeshift_active = 1;
2043 m_event((iPlayableService*)this, evSeekableStatusChanged);
2045 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2046 r.path = m_timeshift_file;
2048 m_cue = new eCueSheet();
2049 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2050 updateDecoder(); /* mainly to switch off PCR */
2053 void eDVBServicePlay::updateDecoder()
2055 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2057 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2059 bool defaultac3=false;
2060 std::string default_ac3;
2062 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2063 defaultac3 = default_ac3 == "True";
2065 eDVBServicePMTHandler::program program;
2066 if (h.getProgramInfo(program))
2067 eDebug("getting program info failed.");
2070 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2071 if (!program.videoStreams.empty())
2073 eDebugNoNewLine(" (");
2074 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2075 i(program.videoStreams.begin());
2076 i != program.videoStreams.end(); ++i)
2083 if (i != program.videoStreams.begin())
2084 eDebugNoNewLine(", ");
2085 eDebugNoNewLine("%04x", i->pid);
2087 eDebugNoNewLine(")");
2089 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2090 if (!program.audioStreams.empty())
2092 eDebugNoNewLine(" (");
2093 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2094 i(program.audioStreams.begin());
2095 i != program.audioStreams.end(); ++i)
2097 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2099 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2105 if (i != program.audioStreams.begin())
2106 eDebugNoNewLine(", ");
2107 eDebugNoNewLine("%04x", i->pid);
2109 eDebugNoNewLine(")");
2111 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2112 pcrpid = program.pcrPid;
2113 eDebug(", and the text pid is %04x", program.textPid);
2114 tpid = program.textPid;
2119 h.getDecodeDemux(m_decode_demux);
2122 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2124 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2127 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2128 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2129 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2130 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2131 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2138 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2139 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2140 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2142 else // subservice or recording
2144 eServiceReferenceDVB ref;
2145 m_service_handler.getServiceReference(ref);
2146 eServiceReferenceDVB parent = ref.getParentServiceReference();
2151 ePtr<eDVBResourceManager> res_mgr;
2152 if (!eDVBResourceManager::getInstance(res_mgr))
2154 ePtr<iDVBChannelList> db;
2155 if (!res_mgr->getChannelList(db))
2157 ePtr<eDVBService> origService;
2158 if (!db->getService(parent, origService))
2160 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2161 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2167 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2168 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2170 m_decoder->setVideoPID(vpid, vpidtype);
2171 m_decoder->setAudioPID(apid, apidtype);
2172 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2174 m_decoder->setSyncPCR(pcrpid);
2177 ePtr<iDVBDemux> data_demux;
2178 if (!h.getDataDemux(data_demux))
2180 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
2181 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
2182 m_radiotext_parser->start(apid);
2187 m_decoder->setSyncPCR(-1);
2189 m_decoder->setTextPID(tpid);
2191 m_teletext_parser->start(program.textPid);
2194 m_decoder->setTrickmode(1);
2198 if (vpid > 0 && vpid < 0x2000)
2202 std::string radio_pic;
2203 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2204 m_decoder->setRadioPic(radio_pic);
2207 m_decoder->setAudioChannel(achannel);
2209 // how we can do this better?
2210 // update cache pid when the user changed the audio track or video track
2211 // TODO handling of difference audio types.. default audio types..
2213 /* don't worry about non-existing services, nor pvr services */
2214 if (m_dvb_service && !m_is_pvr)
2216 if (apidtype == eDVBAudio::aMPEG)
2218 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2219 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2223 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2224 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2226 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2227 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2228 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2229 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2232 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2235 void eDVBServicePlay::loadCuesheet()
2237 std::string filename = m_reference.path + ".cuts";
2239 m_cue_entries.clear();
2241 FILE *f = fopen(filename.c_str(), "rb");
2245 eDebug("loading cuts..");
2248 unsigned long long where;
2251 if (!fread(&where, sizeof(where), 1, f))
2253 if (!fread(&what, sizeof(what), 1, f))
2256 #if BYTE_ORDER == LITTLE_ENDIAN
2257 where = bswap_64(where);
2264 m_cue_entries.insert(cueEntry(where, what));
2267 eDebug("%d entries", m_cue_entries.size());
2269 eDebug("cutfile not found!");
2271 m_cuesheet_changed = 0;
2272 cutlistToCuesheet();
2273 m_event((iPlayableService*)this, evCuesheetChanged);
2276 void eDVBServicePlay::saveCuesheet()
2278 std::string filename = m_reference.path + ".cuts";
2280 FILE *f = fopen(filename.c_str(), "wb");
2284 unsigned long long where;
2287 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2289 #if BYTE_ORDER == BIG_ENDIAN
2292 where = bswap_64(i->where);
2294 what = htonl(i->what);
2295 fwrite(&where, sizeof(where), 1, f);
2296 fwrite(&what, sizeof(what), 1, f);
2302 m_cuesheet_changed = 0;
2305 void eDVBServicePlay::cutlistToCuesheet()
2309 eDebug("no cue sheet");
2314 if (!m_cutlist_enabled)
2316 m_cue->commitSpans();
2317 eDebug("cutlists were disabled");
2321 pts_t in = 0, out = 0, length = 0;
2325 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2329 if (i == m_cue_entries.end())
2332 if (i->what == 0) /* in */
2336 } else if (i->what == 1) /* out */
2338 else /* mark (2) or last play position (3) */
2346 m_cue->addSourceSpan(in, out);
2350 if (i == m_cue_entries.end())
2353 m_cue->commitSpans();
2356 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2358 if (m_subtitle_widget)
2359 disableSubtitles(parent);
2362 int tuplesize = PyTuple_Size(tuple);
2365 if (!PyTuple_Check(tuple))
2371 entry = PyTuple_GET_ITEM(tuple, 0);
2373 if (!PyInt_Check(entry))
2376 type = PyInt_AsLong(entry);
2378 if (type == 1) // teletext subtitles
2380 int page, magazine, pid;
2384 if (!m_teletext_parser)
2386 eDebug("enable teletext subtitles.. no parser !!!");
2390 entry = PyTuple_GET_ITEM(tuple, 1);
2391 if (!PyInt_Check(entry))
2393 pid = PyInt_AsLong(entry);
2395 entry = PyTuple_GET_ITEM(tuple, 2);
2396 if (!PyInt_Check(entry))
2398 page = PyInt_AsLong(entry);
2400 entry = PyTuple_GET_ITEM(tuple, 3);
2401 if (!PyInt_Check(entry))
2403 magazine = PyInt_AsLong(entry);
2405 m_subtitle_widget = new eSubtitleWidget(parent);
2406 m_subtitle_widget->resize(parent->size()); /* full size */
2407 m_teletext_parser->setPageAndMagazine(page, magazine);
2409 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2413 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2414 if (!m_subtitle_parser)
2416 eDebug("enable dvb subtitles.. no parser !!!");
2422 entry = PyTuple_GET_ITEM(tuple, 1);
2423 if (!PyInt_Check(entry))
2425 pid = PyInt_AsLong(entry);
2427 entry = PyTuple_GET_ITEM(tuple, 2);
2428 if (!PyInt_Check(entry))
2430 composition_page_id = PyInt_AsLong(entry);
2432 entry = PyTuple_GET_ITEM(tuple, 3);
2433 if (!PyInt_Check(entry))
2435 ancillary_page_id = PyInt_AsLong(entry);
2437 m_subtitle_widget = new eSubtitleWidget(parent);
2438 m_subtitle_widget->resize(parent->size()); /* full size */
2439 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2441 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2447 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2448 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2449 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2453 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2455 delete m_subtitle_widget;
2456 m_subtitle_widget = 0;
2457 if (m_subtitle_parser)
2459 m_subtitle_parser->stop();
2460 m_dvb_subtitle_pages.clear();
2462 if (m_teletext_parser)
2464 m_teletext_parser->setPageAndMagazine(-1, -1);
2465 m_subtitle_pages.clear();
2468 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2472 PyObject *eDVBServicePlay::getCachedSubtitle()
2476 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2479 unsigned int data = (unsigned int)tmp;
2480 int pid = (data&0xFFFF0000)>>16;
2481 ePyObject tuple = PyTuple_New(4);
2482 eDVBServicePMTHandler::program program;
2483 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2484 if (!h.getProgramInfo(program))
2486 if (program.textPid==pid) // teletext
2487 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2489 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2490 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2491 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2492 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2500 PyObject *eDVBServicePlay::getSubtitleList()
2502 if (!m_teletext_parser)
2505 ePyObject l = PyList_New(0);
2506 std::set<int> added_ttx_pages;
2508 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2509 m_teletext_parser->m_found_subtitle_pages;
2511 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2512 eDVBServicePMTHandler::program program;
2513 if (h.getProgramInfo(program))
2514 eDebug("getting program info failed.");
2517 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2518 it != program.subtitleStreams.end(); ++it)
2520 switch(it->subtitling_type)
2522 case 0x01: // ebu teletext subtitles
2524 int page_number = it->teletext_page_number & 0xFF;
2525 int magazine_number = it->teletext_magazine_number & 7;
2526 int hash = magazine_number << 8 | page_number;
2527 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2529 ePyObject tuple = PyTuple_New(5);
2530 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2531 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2532 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2533 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2534 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2535 PyList_Append(l, tuple);
2537 added_ttx_pages.insert(hash);
2542 case 0x20 ... 0x23: // dvb subtitles
2544 ePyObject tuple = PyTuple_New(5);
2545 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2546 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2547 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2548 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2549 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2550 PyList_Insert(l, 0, tuple);
2558 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2559 it != subs.end(); ++it)
2561 int page_number = it->teletext_page_number & 0xFF;
2562 int magazine_number = it->teletext_magazine_number & 7;
2563 int hash = magazine_number << 8 | page_number;
2564 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2566 ePyObject tuple = PyTuple_New(5);
2567 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2568 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2569 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2570 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2571 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2572 PyList_Append(l, tuple);
2580 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2582 if (m_subtitle_widget)
2584 m_subtitle_pages.push_back(page);
2585 checkSubtitleTiming();
2589 void eDVBServicePlay::checkSubtitleTiming()
2591 // eDebug("checkSubtitleTiming");
2592 if (!m_subtitle_widget)
2596 enum { TELETEXT, DVB } type;
2597 eDVBTeletextSubtitlePage page;
2598 eDVBSubtitlePage dvb_page;
2600 if (!m_subtitle_pages.empty())
2602 page = m_subtitle_pages.front();
2604 show_time = page.m_pts;
2606 else if (!m_dvb_subtitle_pages.empty())
2608 dvb_page = m_dvb_subtitle_pages.front();
2610 show_time = dvb_page.m_show_time;
2618 m_decoder->getPTS(0, pos);
2620 // eDebug("%lld %lld", pos, show_time);
2621 int diff = show_time - pos;
2624 eDebug("[late (%d ms)]", -diff / 90);
2629 eDebug("[invalid]");
2635 if (type == TELETEXT)
2637 eDebug("display teletext subtitle page");
2638 m_subtitle_widget->setPage(page);
2639 m_subtitle_pages.pop_front();
2643 eDebug("display dvb subtitle Page");
2644 m_subtitle_widget->setPage(dvb_page);
2645 m_dvb_subtitle_pages.pop_front();
2649 // eDebug("start subtitle delay %d", diff / 90);
2650 m_subtitle_sync_timer.start(diff / 90, 1);
2656 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2658 if (m_subtitle_widget)
2660 m_dvb_subtitle_pages.push_back(p);
2661 checkSubtitleTiming();
2665 int eDVBServicePlay::getAC3Delay()
2668 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2670 return m_decoder->getAC3Delay();
2675 int eDVBServicePlay::getPCMDelay()
2678 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2680 return m_decoder->getPCMDelay();
2685 void eDVBServicePlay::setAC3Delay(int delay)
2688 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2690 m_decoder->setAC3Delay(delay);
2693 void eDVBServicePlay::setPCMDelay(int delay)
2696 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2698 m_decoder->setPCMDelay(delay);
2701 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2703 eDebug("!!!!!!!!!! Video Event type %d, aspect %d, %dx%d", event.type, event.aspect, event.width, event.height);
2704 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2705 m_event((iPlayableService*)this, evVideoSizeChanged);
2708 DEFINE_REF(eDVBServicePlay)
2710 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2714 case iServiceInformation::sTransponderData:
2715 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2719 return iStaticServiceInformation::getInfoObject(ref, w);
2722 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");