1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/base/nconfig.h> // access to python config
10 #include <lib/dvb/dvb.h>
11 #include <lib/dvb/db.h>
12 #include <lib/dvb/decoder.h>
14 #include <lib/components/file_eraser.h>
15 #include <lib/service/servicedvbrecord.h>
16 #include <lib/service/event.h>
17 #include <lib/dvb/metaparser.h>
18 #include <lib/dvb/tstools.h>
19 #include <lib/python/python.h>
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 #define TSPATH "/media/hdd"
36 class eStaticServiceDVBInformation: public iStaticServiceInformation
38 DECLARE_REF(eStaticServiceDVBInformation);
40 RESULT getName(const eServiceReference &ref, std::string &name);
41 int getLength(const eServiceReference &ref);
42 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
43 PyObject *getInfoObject(const eServiceReference &ref, int);
46 DEFINE_REF(eStaticServiceDVBInformation);
48 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
50 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
51 if ( !ref.name.empty() )
53 if (service.getParentTransportStreamID().get()) // linkage subservice
55 ePtr<iServiceHandler> service_center;
56 if (!eServiceCenter::getInstance(service_center))
58 eServiceReferenceDVB parent = service;
59 parent.setTransportStreamID( service.getParentTransportStreamID() );
60 parent.setServiceID( service.getParentServiceID() );
61 parent.setParentTransportStreamID(eTransportStreamID(0));
62 parent.setParentServiceID(eServiceID(0));
64 ePtr<iStaticServiceInformation> service_info;
65 if (!service_center->info(parent, service_info))
67 if (!service_info->getName(parent, name))
69 // just show short name
70 unsigned int pos = name.find("\xc2\x86");
71 if ( pos != std::string::npos )
73 pos = name.find("\xc2\x87");
74 if ( pos != std::string::npos )
90 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
95 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
97 ePtr<eDVBResourceManager> res_mgr;
98 if ( eDVBResourceManager::getInstance( res_mgr ) )
99 eDebug("isPlayable... no res manager!!");
102 eDVBChannelID chid, chid_ignore;
103 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
104 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
105 return res_mgr->canAllocateChannel(chid, chid_ignore);
110 static void PutToDict(ePyObject &dict, const char*key, long value)
112 ePyObject item = PyString_FromFormat("%d", value);
115 if (PyDict_SetItemString(dict, key, item))
116 eDebug("put %s to dict failed", key);
120 eDebug("could not create PyObject for %s", key);
123 extern void PutToDict(ePyObject &dict, const char*key, const char *value);
125 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
128 PutToDict(dict, "type", "Satellite");
129 PutToDict(dict, "frequency", feparm.frequency);
130 PutToDict(dict, "symbolrate", feparm.symbol_rate);
131 PutToDict(dict, "orbital position", feparm.orbital_position);
132 switch (feparm.inversion)
134 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
135 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
137 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
139 PutToDict(dict, "inversion", tmp);
142 case eDVBFrontendParametersSatellite::FEC::fNone: tmp="NONE"; break;
143 case eDVBFrontendParametersSatellite::FEC::f1_2: tmp="1/2"; break;
144 case eDVBFrontendParametersSatellite::FEC::f2_3: tmp="2/3"; break;
145 case eDVBFrontendParametersSatellite::FEC::f3_4: tmp="3/4"; break;
146 case eDVBFrontendParametersSatellite::FEC::f5_6: tmp="5/6"; break;
147 case eDVBFrontendParametersSatellite::FEC::f7_8: tmp="7/8"; break;
148 case eDVBFrontendParametersSatellite::FEC::f3_5: tmp="3/5"; break;
149 case eDVBFrontendParametersSatellite::FEC::f4_5: tmp="4/5"; break;
150 case eDVBFrontendParametersSatellite::FEC::f8_9: tmp="8/9"; break;
151 case eDVBFrontendParametersSatellite::FEC::f9_10: tmp="9/10"; break;
153 case eDVBFrontendParametersSatellite::FEC::fAuto: tmp="AUTO"; break;
155 PutToDict(dict, "fec inner", tmp);
156 switch (feparm.modulation)
158 case eDVBFrontendParametersSatellite::Modulation::Auto: tmp="AUTO"; break;
159 case eDVBFrontendParametersSatellite::Modulation::QPSK: tmp="QPSK"; break;
160 case eDVBFrontendParametersSatellite::Modulation::M8PSK: tmp="8PSK"; break;
161 case eDVBFrontendParametersSatellite::Modulation::QAM_16: tmp="QAM16"; break;
163 PutToDict(dict, "modulation", tmp);
164 switch(feparm.polarisation)
166 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
167 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
168 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR LEFT"; break;
170 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR RIGHT"; break;
172 PutToDict(dict, "polarization", tmp);
173 switch(feparm.system)
176 case eDVBFrontendParametersSatellite::System::DVB_S: tmp="DVB-S"; break;
177 case eDVBFrontendParametersSatellite::System::DVB_S2:
178 switch(feparm.roll_off)
180 case eDVBFrontendParametersSatellite::RollOff::alpha_0_35: tmp="0.35"; break;
181 case eDVBFrontendParametersSatellite::RollOff::alpha_0_25: tmp="0.25"; break;
182 case eDVBFrontendParametersSatellite::RollOff::alpha_0_20: tmp="0.20"; break;
184 case eDVBFrontendParametersSatellite::RollOff::alpha_auto: tmp="AUTO"; break;
186 PutToDict(dict, "roll off", tmp);
190 PutToDict(dict, "system", tmp);
193 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
195 PutToDict(dict, "type", "Terrestrial");
196 PutToDict(dict, "frequency", feparm.frequency);
198 switch (feparm.bandwidth)
200 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz: tmp="8 MHz"; break;
201 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz: tmp="7 MHz"; break;
202 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz: tmp="6 MHz"; break;
204 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto: tmp="AUTO"; break;
206 PutToDict(dict, "bandwidth", tmp);
207 switch (feparm.code_rate_LP)
209 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
210 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
211 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
212 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
213 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
215 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
217 PutToDict(dict, "code rate lp", tmp);
218 switch (feparm.code_rate_HP)
220 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
221 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
222 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
223 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
224 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
226 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
228 PutToDict(dict, "code rate hp", tmp);
229 switch (feparm.modulation)
231 case eDVBFrontendParametersTerrestrial::Modulation::QPSK: tmp="QPSK"; break;
232 case eDVBFrontendParametersTerrestrial::Modulation::QAM16: tmp="QAM16"; break;
233 case eDVBFrontendParametersTerrestrial::Modulation::QAM64: tmp="QAM64"; break;
235 case eDVBFrontendParametersTerrestrial::Modulation::Auto: tmp="AUTO"; break;
237 PutToDict(dict, "constellation", tmp);
238 switch (feparm.transmission_mode)
240 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k: tmp="2k"; break;
241 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k: tmp="8k"; break;
243 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto: tmp="AUTO"; break;
245 PutToDict(dict, "transmission mode", tmp);
246 switch (feparm.guard_interval)
248 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32: tmp="1/32"; break;
249 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16: tmp="1/16"; break;
250 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8: tmp="1/8"; break;
251 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4: tmp="1/4"; break;
253 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto: tmp="AUTO"; break;
255 PutToDict(dict, "guard interval", tmp);
256 switch (feparm.hierarchy)
258 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone: tmp="NONE"; break;
259 case eDVBFrontendParametersTerrestrial::Hierarchy::H1: tmp="1"; break;
260 case eDVBFrontendParametersTerrestrial::Hierarchy::H2: tmp="2"; break;
261 case eDVBFrontendParametersTerrestrial::Hierarchy::H4: tmp="4"; break;
263 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto: tmp="AUTO"; break;
265 PutToDict(dict, "hierarchy", tmp);
266 switch (feparm.inversion)
268 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
269 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
271 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
273 PutToDict(dict, "inversion", tmp);
276 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
279 PutToDict(dict, "type", "Cable");
280 PutToDict(dict, "frequency", feparm.frequency);
281 PutToDict(dict, "symbolrate", feparm.symbol_rate);
282 switch (feparm.modulation)
284 case eDVBFrontendParametersCable::Modulation::QAM16: tmp="QAM16"; break;
285 case eDVBFrontendParametersCable::Modulation::QAM32: tmp="QAM32"; break;
286 case eDVBFrontendParametersCable::Modulation::QAM64: tmp="QAM64"; break;
287 case eDVBFrontendParametersCable::Modulation::QAM128: tmp="QAM128"; break;
288 case eDVBFrontendParametersCable::Modulation::QAM256: tmp="QAM256"; break;
290 case eDVBFrontendParametersCable::Modulation::Auto: tmp="AUTO"; break;
292 PutToDict(dict, "modulation", tmp);
293 switch (feparm.inversion)
295 case eDVBFrontendParametersCable::Inversion::On: tmp="ON"; break;
296 case eDVBFrontendParametersCable::Inversion::Off: tmp="OFF"; break;
298 case eDVBFrontendParametersCable::Inversion::Unknown: tmp="AUTO"; break;
300 PutToDict(dict, "inversion", tmp);
301 switch (feparm.fec_inner)
303 case eDVBFrontendParametersCable::FEC::fNone: tmp="NONE"; break;
304 case eDVBFrontendParametersCable::FEC::f1_2: tmp="1/2"; break;
305 case eDVBFrontendParametersCable::FEC::f2_3: tmp="2/3"; break;
306 case eDVBFrontendParametersCable::FEC::f3_4: tmp="3/4"; break;
307 case eDVBFrontendParametersCable::FEC::f5_6: tmp="5/6"; break;
308 case eDVBFrontendParametersCable::FEC::f7_8: tmp="7/8"; break;
309 case eDVBFrontendParametersCable::FEC::f8_9: tmp="8/9"; break;
311 case eDVBFrontendParametersCable::FEC::fAuto: tmp="AUTO"; break;
313 PutToDict(dict, "fec inner", tmp);
316 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
318 if (r.type == eServiceReference::idDVB)
320 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
323 case iServiceInformation::sTransponderData:
325 ePtr<eDVBResourceManager> res;
326 if (!eDVBResourceManager::getInstance(res))
328 ePtr<iDVBChannelList> db;
329 if (!res->getChannelList(db))
332 ref.getChannelID(chid);
333 ePtr<iDVBFrontendParameters> feparm;
334 if (!db->getChannelFrontendData(chid, feparm))
337 if (!feparm->getSystem(system))
339 ePyObject dict = PyDict_New();
342 case iDVBFrontend::feSatellite:
344 eDVBFrontendParametersSatellite s;
346 PutSatelliteDataToDict(dict, s);
349 case iDVBFrontend::feTerrestrial:
351 eDVBFrontendParametersTerrestrial t;
353 PutTerrestrialDataToDict(dict, t);
356 case iDVBFrontend::feCable:
358 eDVBFrontendParametersCable c;
360 PutCableDataToDict(dict, c);
364 eDebug("unknown frontend type %d", system);
379 DEFINE_REF(eStaticServiceDVBBouquetInformation);
381 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
383 ePtr<iDVBChannelList> db;
384 ePtr<eDVBResourceManager> res;
387 if ((err = eDVBResourceManager::getInstance(res)) != 0)
389 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
392 if ((err = res->getChannelList(db)) != 0)
394 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
399 if ((err = db->getBouquet(ref, bouquet)) != 0)
401 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
405 if ( bouquet && bouquet->m_bouquet_name.length() )
407 name = bouquet->m_bouquet_name;
414 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
416 if (ref.flags & eServiceReference::isGroup)
418 ePtr<iDVBChannelList> db;
419 ePtr<eDVBResourceManager> res;
421 if (eDVBResourceManager::getInstance(res))
423 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
427 if (res->getChannelList(db))
429 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
434 if (db->getBouquet(ref, bouquet))
436 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
441 eDVBChannelID chid, chid_ignore;
442 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
443 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
445 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
446 int tmp=res->canAllocateChannel(chid, chid_ignore);
449 m_playable_service = *it;
456 m_playable_service = eServiceReference();
460 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
465 #include <lib/dvb/epgcache.h>
467 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
469 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
472 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
474 DECLARE_REF(eStaticServiceDVBPVRInformation);
475 eServiceReference m_ref;
476 eDVBMetaParser m_parser;
478 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
479 RESULT getName(const eServiceReference &ref, std::string &name);
480 int getLength(const eServiceReference &ref);
481 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
482 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
483 int getInfo(const eServiceReference &ref, int w);
484 std::string getInfoString(const eServiceReference &ref,int w);
487 DEFINE_REF(eStaticServiceDVBPVRInformation);
489 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
492 m_parser.parseFile(ref.path);
495 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
497 ASSERT(ref == m_ref);
498 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
502 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
504 ASSERT(ref == m_ref);
508 if (tstools.openFile(ref.path.c_str()))
512 if (tstools.calcLen(len))
518 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
522 case iServiceInformation::sDescription:
523 return iServiceInformation::resIsString;
524 case iServiceInformation::sServiceref:
525 return iServiceInformation::resIsString;
526 case iServiceInformation::sTimeCreate:
527 if (m_parser.m_time_create)
528 return m_parser.m_time_create;
530 return iServiceInformation::resNA;
532 return iServiceInformation::resNA;
536 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
540 case iServiceInformation::sDescription:
541 return m_parser.m_description;
542 case iServiceInformation::sServiceref:
543 return m_parser.m_ref.toString();
544 case iServiceInformation::sTags:
545 return m_parser.m_tags;
551 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
553 if (!ref.path.empty())
555 ePtr<eServiceEvent> event = new eServiceEvent;
556 std::string filename = ref.path;
557 filename.erase(filename.length()-2, 2);
559 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
569 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
571 DECLARE_REF(eDVBPVRServiceOfflineOperations);
572 eServiceReferenceDVB m_ref;
574 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
576 RESULT deleteFromDisk(int simulate);
577 RESULT getListOfFilenames(std::list<std::string> &);
580 DEFINE_REF(eDVBPVRServiceOfflineOperations);
582 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
586 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
592 std::list<std::string> res;
593 if (getListOfFilenames(res))
596 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
598 eDebug("FATAL !! can't get background file eraser");
600 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
602 eDebug("Removing %s...", i->c_str());
604 eraser->erase(i->c_str());
606 ::unlink(i->c_str());
613 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
616 res.push_back(m_ref.path);
618 // handling for old splitted recordings (enigma 1)
623 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
625 if (stat(buf, &s) < 0)
630 res.push_back(m_ref.path + ".meta");
631 res.push_back(m_ref.path + ".ap");
632 res.push_back(m_ref.path + ".cuts");
633 std::string tmp = m_ref.path;
634 tmp.erase(m_ref.path.length()-3);
635 res.push_back(tmp + ".eit");
639 DEFINE_REF(eServiceFactoryDVB)
641 eServiceFactoryDVB::eServiceFactoryDVB()
643 ePtr<eServiceCenter> sc;
645 eServiceCenter::getPrivInstance(sc);
647 sc->addServiceFactory(eServiceFactoryDVB::id, this);
649 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
650 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
653 eServiceFactoryDVB::~eServiceFactoryDVB()
655 ePtr<eServiceCenter> sc;
657 eServiceCenter::getPrivInstance(sc);
659 sc->removeServiceFactory(eServiceFactoryDVB::id);
662 DEFINE_REF(eDVBServiceList);
664 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
668 eDVBServiceList::~eDVBServiceList()
672 RESULT eDVBServiceList::startQuery()
674 ePtr<iDVBChannelList> db;
675 ePtr<eDVBResourceManager> res;
678 if ((err = eDVBResourceManager::getInstance(res)) != 0)
680 eDebug("no resource manager");
683 if ((err = res->getChannelList(db)) != 0)
685 eDebug("no channel list");
689 ePtr<eDVBChannelQuery> q;
691 if (!m_parent.path.empty())
693 eDVBChannelQuery::compile(q, m_parent.path);
696 eDebug("compile query failed");
701 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
703 eDebug("startQuery failed");
710 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
712 eServiceReferenceDVB ref;
717 while (!m_query->getNextResult(ref))
721 list.sort(iListableServiceCompare(this));
726 // The first argument of this function is a format string to specify the order and
727 // the content of the returned list
728 // useable format options are
729 // R = Service Reference (as swig object .. this is very slow)
730 // S = Service Reference (as python string object .. same as ref.toString())
731 // C = Service Reference (as python string object .. same as ref.toCompareString())
732 // N = Service Name (as python string object)
733 // when exactly one return value per service is selected in the format string,
734 // then each value is directly a list entry
735 // when more than one value is returned per service, then the list is a list of
737 // unknown format string chars are returned as python None values !
738 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
741 std::list<eServiceReference> tmplist;
744 if (!format || !(retcount=strlen(format)))
745 format = "R"; // just return service reference swig object ...
747 if (!getContent(tmplist, sorted))
749 int services=tmplist.size();
750 ePtr<iStaticServiceInformation> sptr;
751 eServiceCenterPtr service_center;
753 if (strchr(format, 'N'))
754 eServiceCenter::getPrivInstance(service_center);
756 ret = PyList_New(services);
757 std::list<eServiceReference>::iterator it(tmplist.begin());
759 for (int cnt=0; cnt < services; ++cnt)
761 eServiceReference &ref=*it++;
762 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
763 for (int i=0; i < retcount; ++i)
768 case 'R': // service reference (swig)object
769 tmp = NEW_eServiceReference(ref);
771 case 'C': // service reference compare string
772 tmp = PyString_FromString(ref.toCompareString().c_str());
774 case 'S': // service reference string
775 tmp = PyString_FromString(ref.toString().c_str());
777 case 'N': // service name
780 service_center->info(ref, sptr);
784 sptr->getName(ref, name);
786 tmp = PyString_FromString(name.c_str());
790 tmp = PyString_FromString("<n/a>");
803 PyTuple_SET_ITEM(tuple, i, tmp);
805 PyList_SET_ITEM(ret, cnt, tmp);
809 PyList_SET_ITEM(ret, cnt, tuple);
812 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
815 RESULT eDVBServiceList::getNext(eServiceReference &ref)
820 return m_query->getNextResult((eServiceReferenceDVB&)ref);
823 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
825 if (m_parent.flags & eServiceReference::canDescent) // bouquet
827 ePtr<iDVBChannelList> db;
828 ePtr<eDVBResourceManager> resm;
830 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
833 if (db->getBouquet(m_parent, m_bouquet) != 0)
844 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
848 return m_bouquet->addService(ref, before);
851 RESULT eDVBServiceList::removeService(eServiceReference &ref)
855 return m_bouquet->removeService(ref);
858 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
862 return m_bouquet->moveService(ref, pos);
865 RESULT eDVBServiceList::flushChanges()
869 return m_bouquet->flushChanges();
872 RESULT eDVBServiceList::setListName(const std::string &name)
876 return m_bouquet->setListName(name);
879 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
881 ePtr<eDVBService> service;
882 int r = lookupService(service, ref);
885 // check resources...
886 ptr = new eDVBServicePlay(ref, service);
890 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
892 if (ref.path.empty())
894 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
903 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
905 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
906 if (list->startQuery())
916 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
918 /* is a listable service? */
919 if (ref.flags & eServiceReference::canDescent) // bouquet
921 if ( !ref.name.empty() ) // satellites or providers list
922 ptr = m_StaticServiceDVBInfo;
923 else // a dvb bouquet
924 ptr = m_StaticServiceDVBBouquetInfo;
926 else if (!ref.path.empty()) /* do we have a PVR service? */
927 ptr = new eStaticServiceDVBPVRInformation(ref);
928 else // normal dvb service
930 ePtr<eDVBService> service;
931 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
932 ptr = m_StaticServiceDVBInfo;
934 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
940 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
942 if (ref.path.empty())
948 ptr = new eDVBPVRServiceOfflineOperations(ref);
953 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
955 // TODO: handle the listing itself
956 // if (ref.... == -1) .. return "... bouquets ...";
957 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
959 ePtr<iDVBChannelList> db;
960 ePtr<eDVBResourceManager> res;
963 if ((err = eDVBResourceManager::getInstance(res)) != 0)
965 eDebug("no resource manager");
968 if ((err = res->getChannelList(db)) != 0)
970 eDebug("no channel list");
974 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
975 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
977 eDebug("getService failed!");
984 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
985 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
987 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
989 m_is_pvr = !m_reference.path.empty();
991 m_timeshift_enabled = m_timeshift_active = 0;
994 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
995 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
996 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
998 m_cuesheet_changed = 0;
999 m_cutlist_enabled = 1;
1001 m_subtitle_widget = 0;
1005 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
1008 eDVBServicePlay::~eDVBServicePlay()
1010 delete m_subtitle_widget;
1013 void eDVBServicePlay::gotNewEvent()
1017 ePtr<eServiceEvent> m_event_now, m_event_next;
1018 getEvent(m_event_now, 0);
1019 getEvent(m_event_next, 1);
1022 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1024 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1026 m_event((iPlayableService*)this, evUpdatedEventInfo);
1029 void eDVBServicePlay::serviceEvent(int event)
1031 m_tune_state = event;
1035 case eDVBServicePMTHandler::eventTuned:
1037 ePtr<iDVBDemux> m_demux;
1038 if (!m_service_handler.getDataDemux(m_demux))
1040 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1041 int sid = ref.getParentServiceID().get();
1043 sid = ref.getServiceID().get();
1044 if ( ref.getParentTransportStreamID().get() &&
1045 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1046 m_event_handler.startOther(m_demux, sid);
1048 m_event_handler.start(m_demux, sid);
1052 case eDVBServicePMTHandler::eventNoResources:
1053 case eDVBServicePMTHandler::eventNoPAT:
1054 case eDVBServicePMTHandler::eventNoPATEntry:
1055 case eDVBServicePMTHandler::eventNoPMT:
1056 case eDVBServicePMTHandler::eventTuneFailed:
1058 eDebug("DVB service failed to tune - error %d", event);
1059 m_event((iPlayableService*)this, evTuneFailed);
1062 case eDVBServicePMTHandler::eventNewProgramInfo:
1064 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1065 if (m_timeshift_enabled)
1066 updateTimeshiftPids();
1067 if (!m_timeshift_active)
1069 if (m_first_program_info && m_is_pvr)
1071 m_first_program_info = 0;
1074 m_event((iPlayableService*)this, evUpdatedInfo);
1077 case eDVBServicePMTHandler::eventEOF:
1078 m_event((iPlayableService*)this, evEOF);
1080 case eDVBServicePMTHandler::eventSOF:
1081 m_event((iPlayableService*)this, evSOF);
1086 void eDVBServicePlay::serviceEventTimeshift(int event)
1090 case eDVBServicePMTHandler::eventNewProgramInfo:
1091 if (m_timeshift_active)
1094 case eDVBServicePMTHandler::eventSOF:
1095 m_event((iPlayableService*)this, evSOF);
1097 case eDVBServicePMTHandler::eventEOF:
1103 RESULT eDVBServicePlay::start()
1106 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1107 two (one for decoding, one for data source), as we must be prepared
1108 to start recording from the data demux. */
1110 m_cue = new eCueSheet();
1112 m_event(this, evStart);
1114 m_first_program_info = 1;
1115 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1116 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1118 /* inject EIT if there is a stored one */
1121 std::string filename = service.path;
1122 filename.erase(filename.length()-2, 2);
1124 ePtr<eServiceEvent> event = new eServiceEvent;
1125 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1127 ePtr<eServiceEvent> empty;
1128 m_event_handler.inject(event, 0);
1129 m_event_handler.inject(empty, 1);
1136 m_event(this, evStart);
1139 m_event((iPlayableService*)this, evSeekableStatusChanged);
1143 RESULT eDVBServicePlay::stop()
1145 /* add bookmark for last play position */
1148 pts_t play_position;
1149 if (!getPlayPosition(play_position))
1151 /* remove last position */
1152 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1154 if (i->what == 3) /* current play position */
1156 m_cue_entries.erase(i);
1157 i = m_cue_entries.begin();
1163 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1164 m_cuesheet_changed = 1;
1168 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1170 m_service_handler_timeshift.free();
1171 m_service_handler.free();
1173 if (m_is_pvr && m_cuesheet_changed)
1176 /* save cuesheet only when main file is accessible. */
1177 if (!::stat(m_reference.path.c_str(), &s))
1184 RESULT eDVBServicePlay::setTarget(int target)
1186 m_is_primary = !target;
1190 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1192 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1196 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1198 /* note: we check for timeshift to be enabled,
1199 not neccessary active. if you pause when timeshift
1200 is not active, you should activate it when unpausing */
1201 if ((!m_is_pvr) && (!m_timeshift_enabled))
1211 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1214 return m_decoder->setSlowMotion(ratio);
1219 RESULT eDVBServicePlay::setFastForward(int ratio)
1221 int skipmode, ffratio;
1227 } else if (ratio > 0)
1235 } else // if (ratio < 0)
1241 if (m_skipmode != skipmode)
1243 eDebug("setting cue skipmode to %d", skipmode);
1245 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1248 m_skipmode = skipmode;
1253 return m_decoder->setFastForward(ffratio);
1256 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1258 if (m_is_pvr || m_timeshift_enabled)
1268 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1269 RESULT eDVBServicePlay::getLength(pts_t &len)
1271 ePtr<iDVBPVRChannel> pvr_channel;
1273 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1276 return pvr_channel->getLength(len);
1279 RESULT eDVBServicePlay::pause()
1281 if (!m_is_paused && m_decoder)
1284 return m_decoder->freeze(0);
1289 RESULT eDVBServicePlay::unpause()
1291 if (m_is_paused && m_decoder)
1294 return m_decoder->unfreeze();
1299 RESULT eDVBServicePlay::seekTo(pts_t to)
1301 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1303 if (!m_decode_demux)
1306 ePtr<iDVBPVRChannel> pvr_channel;
1308 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1314 m_cue->seekTo(0, to);
1318 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1320 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1322 if (!m_decode_demux)
1325 ePtr<iDVBPVRChannel> pvr_channel;
1327 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1332 /* HACK until we have skip-AP api */
1333 if ((to > 0) && (to < 100))
1341 m_cue->seekTo(mode, to);
1345 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1347 ePtr<iDVBPVRChannel> pvr_channel;
1349 if (!m_decode_demux)
1352 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1357 /* if there is a decoder, use audio or video PTS */
1360 r = m_decoder->getPTS(0, pos);
1366 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1369 RESULT eDVBServicePlay::setTrickmode(int trick)
1372 m_decoder->setTrickmode(trick);
1376 RESULT eDVBServicePlay::isCurrentlySeekable()
1378 return m_is_pvr || m_timeshift_active;
1381 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1387 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1393 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1399 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1405 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1411 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1414 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1415 (m_timeshift_enabled || !m_is_pvr))
1417 if (!m_timeshift_enabled)
1419 /* we need enough diskspace */
1421 if (statfs(TSPATH "/.", &fs) < 0)
1423 eDebug("statfs failed!");
1427 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1429 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1439 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1450 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1456 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1462 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1468 RESULT eDVBServicePlay::getName(std::string &name)
1472 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1473 return i->getName(m_reference, name);
1477 m_dvb_service->getName(m_reference, name);
1481 else if (!m_reference.name.empty())
1482 eStaticServiceDVBInformation().getName(m_reference, name);
1484 name = "DVB service";
1488 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1490 return m_event_handler.getEvent(evt, nownext);
1493 int eDVBServicePlay::getInfo(int w)
1495 eDVBServicePMTHandler::program program;
1498 return resIsPyObject;
1500 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1502 int no_program_info = 0;
1504 if (h.getProgramInfo(program))
1505 no_program_info = 1;
1509 #if HAVE_DVB_API_VERSION >= 3
1511 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1512 return m_videoEventData.height;
1515 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1516 return m_videoEventData.width;
1519 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1522 #if HAVE_DVB_API_VERSION >= 3
1523 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1524 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1527 #warning "FIXMEE implement sAspect for old DVB API"
1529 if (no_program_info)
1531 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1533 ePtr<eServiceEvent> evt;
1534 if (!m_event_handler.getEvent(evt, 0))
1536 ePtr<eComponentData> data;
1537 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1539 if ( data->getStreamContent() == 1 )
1541 switch(data->getComponentType())
1544 case 1: // 4:3 SD PAL
1546 case 3: // 16:9 SD PAL
1547 case 4: // > 16:9 PAL
1548 case 5: // 4:3 SD NTSC
1550 case 7: // 16:9 SD NTSC
1551 case 8: // > 16:9 NTSC
1554 case 9: // 4:3 HD PAL
1556 case 0xB: // 16:9 HD PAL
1557 case 0xC: // > 16:9 HD PAL
1558 case 0xD: // 4:3 HD NTSC
1560 case 0xF: // 16:9 HD NTSC
1561 case 0x10: // > 16:9 HD PAL
1562 return data->getComponentType();
1569 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1570 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1571 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1572 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1573 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1574 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1575 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1576 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1577 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1578 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1579 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1580 case sProvider: if (!m_dvb_service) return -1; return -2;
1581 case sServiceref: return resIsString;
1582 case sDVBState: return m_tune_state;
1588 std::string eDVBServicePlay::getInfoString(int w)
1593 if (!m_dvb_service) return "";
1594 return m_dvb_service->m_provider_name;
1596 return m_reference.toString();
1600 return iServiceInformation::getInfoString(w);
1603 PyObject *eDVBServicePlay::getInfoObject(int w)
1608 return m_service_handler.getCaIds();
1609 case sTransponderData:
1610 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1614 return iServiceInformation::getInfoObject(w);
1617 int eDVBServicePlay::getNumberOfTracks()
1619 eDVBServicePMTHandler::program program;
1620 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1621 if (h.getProgramInfo(program))
1623 return program.audioStreams.size();
1626 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1628 int ret = selectAudioStream(i);
1630 if (m_decoder->start())
1636 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1638 eDVBServicePMTHandler::program program;
1639 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1641 if (h.getProgramInfo(program))
1644 if (i >= program.audioStreams.size())
1647 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1648 info.m_description = "MPEG";
1649 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1650 info.m_description = "AC3";
1651 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1652 info.m_description = "AAC";
1653 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1654 info.m_description = "DTS";
1656 info.m_description = "???";
1658 if (program.audioStreams[i].component_tag != -1)
1660 ePtr<eServiceEvent> evt;
1661 if (!m_event_handler.getEvent(evt, 0))
1663 ePtr<eComponentData> data;
1664 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1665 info.m_language = data->getText();
1669 if (info.m_language.empty())
1670 info.m_language = program.audioStreams[i].language_code;
1675 int eDVBServicePlay::selectAudioStream(int i)
1677 eDVBServicePMTHandler::program program;
1678 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1680 if (h.getProgramInfo(program))
1683 if ((unsigned int)i >= program.audioStreams.size())
1689 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1692 if (m_radiotext_parser)
1693 m_radiotext_parser->start(program.audioStreams[i].pid);
1695 if (m_dvb_service && !m_is_pvr)
1697 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1699 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1700 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1704 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1705 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1709 h.resetCachedProgram();
1714 int eDVBServicePlay::getCurrentChannel()
1716 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1719 RESULT eDVBServicePlay::selectChannel(int i)
1721 if (i < LEFT || i > RIGHT || i == STEREO)
1724 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1726 m_decoder->setAudioChannel(i);
1730 std::string eDVBServicePlay::getRadioText(int x)
1732 if (m_radiotext_parser)
1736 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1741 void eDVBServicePlay::radioTextUpdated()
1743 m_event((iPlayableService*)this, evUpdatedRadioText);
1746 int eDVBServiceBase::getFrontendInfo(int w)
1748 eUsePtr<iDVBChannel> channel;
1749 if(m_service_handler.getChannel(channel))
1751 ePtr<iDVBFrontend> fe;
1752 if(channel->getFrontend(fe))
1754 return fe->readFrontendData(w);
1757 PyObject *eDVBServiceBase::getFrontendData(bool original)
1761 eUsePtr<iDVBChannel> channel;
1762 if(!m_service_handler.getChannel(channel))
1764 ePtr<iDVBFrontend> fe;
1765 if(!channel->getFrontend(fe))
1767 ret = fe->readTransponderData(original);
1770 ePtr<iDVBFrontendParameters> feparm;
1771 channel->getCurrentFrontendParameters(feparm);
1774 eDVBFrontendParametersSatellite osat;
1775 if (!feparm->getDVBS(osat))
1777 void PutToDict(ePyObject &, const char*, long);
1778 void PutToDict(ePyObject &, const char*, const char*);
1779 PutToDict(ret, "orbital_position", osat.orbital_position);
1780 const char *tmp = "UNKNOWN";
1781 switch(osat.polarisation)
1783 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1784 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1785 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1786 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1789 PutToDict(ret, "polarization", tmp);
1800 int eDVBServicePlay::getNumberOfSubservices()
1802 ePtr<eServiceEvent> evt;
1803 if (!m_event_handler.getEvent(evt, 0))
1804 return evt->getNumOfLinkageServices();
1808 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1810 ePtr<eServiceEvent> evt;
1811 if (!m_event_handler.getEvent(evt, 0))
1813 if (!evt->getLinkageService(sub, m_reference, n))
1816 sub.type=eServiceReference::idInvalid;
1820 RESULT eDVBServicePlay::startTimeshift()
1822 ePtr<iDVBDemux> demux;
1824 eDebug("Start timeshift!");
1826 if (m_timeshift_enabled)
1829 /* start recording with the data demux. */
1830 if (m_service_handler.getDataDemux(demux))
1833 demux->createTSRecorder(m_record);
1837 char templ[]=TSPATH "/timeshift.XXXXXX";
1838 m_timeshift_fd = mkstemp(templ);
1839 m_timeshift_file = templ;
1841 eDebug("recording to %s", templ);
1843 if (m_timeshift_fd < 0)
1849 m_record->setTargetFD(m_timeshift_fd);
1851 m_timeshift_enabled = 1;
1853 updateTimeshiftPids();
1859 RESULT eDVBServicePlay::stopTimeshift()
1861 if (!m_timeshift_enabled)
1866 m_timeshift_enabled = 0;
1871 close(m_timeshift_fd);
1872 eDebug("remove timeshift file");
1873 remove(m_timeshift_file.c_str());
1878 int eDVBServicePlay::isTimeshiftActive()
1880 return m_timeshift_enabled && m_timeshift_active;
1883 RESULT eDVBServicePlay::activateTimeshift()
1885 if (!m_timeshift_enabled)
1888 if (!m_timeshift_active)
1890 switchToTimeshift();
1897 PyObject *eDVBServicePlay::getCutList()
1899 ePyObject list = PyList_New(0);
1901 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1903 ePyObject tuple = PyTuple_New(2);
1904 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1905 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1906 PyList_Append(list, tuple);
1913 void eDVBServicePlay::setCutList(ePyObject list)
1915 if (!PyList_Check(list))
1917 int size = PyList_Size(list);
1920 m_cue_entries.clear();
1922 for (i=0; i<size; ++i)
1924 ePyObject tuple = PyList_GET_ITEM(list, i);
1925 if (!PyTuple_Check(tuple))
1927 eDebug("non-tuple in cutlist");
1930 if (PyTuple_Size(tuple) != 2)
1932 eDebug("cutlist entries need to be a 2-tuple");
1935 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1936 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1938 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1941 pts_t pts = PyLong_AsLongLong(ppts);
1942 int type = PyInt_AsLong(ptype);
1943 m_cue_entries.insert(cueEntry(pts, type));
1944 eDebug("adding %08llx, %d", pts, type);
1946 m_cuesheet_changed = 1;
1948 cutlistToCuesheet();
1949 m_event((iPlayableService*)this, evCuesheetChanged);
1952 void eDVBServicePlay::setCutListEnable(int enable)
1954 m_cutlist_enabled = enable;
1955 cutlistToCuesheet();
1958 void eDVBServicePlay::updateTimeshiftPids()
1963 eDVBServicePMTHandler::program program;
1964 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1966 if (h.getProgramInfo(program))
1970 std::set<int> pids_to_record;
1971 pids_to_record.insert(0); // PAT
1972 if (program.pmtPid != -1)
1973 pids_to_record.insert(program.pmtPid); // PMT
1975 if (program.textPid != -1)
1976 pids_to_record.insert(program.textPid); // Videotext
1978 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1979 i(program.videoStreams.begin());
1980 i != program.videoStreams.end(); ++i)
1981 pids_to_record.insert(i->pid);
1983 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1984 i(program.audioStreams.begin());
1985 i != program.audioStreams.end(); ++i)
1986 pids_to_record.insert(i->pid);
1988 std::set<int> new_pids, obsolete_pids;
1990 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1991 m_pids_active.begin(), m_pids_active.end(),
1992 std::inserter(new_pids, new_pids.begin()));
1994 std::set_difference(
1995 m_pids_active.begin(), m_pids_active.end(),
1996 pids_to_record.begin(), pids_to_record.end(),
1997 std::inserter(new_pids, new_pids.begin())
2000 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2001 m_record->addPID(*i);
2003 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2004 m_record->removePID(*i);
2008 void eDVBServicePlay::switchToLive()
2010 if (!m_timeshift_active)
2016 m_teletext_parser = 0;
2017 m_radiotext_parser = 0;
2018 m_subtitle_parser = 0;
2019 m_new_dvb_subtitle_page_connection = 0;
2020 m_new_subtitle_page_connection = 0;
2021 m_radiotext_updated_connection = 0;
2023 /* free the timeshift service handler, we need the resources */
2024 m_service_handler_timeshift.free();
2025 m_timeshift_active = 0;
2027 m_event((iPlayableService*)this, evSeekableStatusChanged);
2032 void eDVBServicePlay::switchToTimeshift()
2034 if (m_timeshift_active)
2039 m_teletext_parser = 0;
2040 m_radiotext_parser = 0;
2041 m_subtitle_parser = 0;
2042 m_new_subtitle_page_connection = 0;
2043 m_new_dvb_subtitle_page_connection = 0;
2044 m_radiotext_updated_connection = 0;
2046 m_timeshift_active = 1;
2048 m_event((iPlayableService*)this, evSeekableStatusChanged);
2050 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2051 r.path = m_timeshift_file;
2053 m_cue = new eCueSheet();
2054 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2055 updateDecoder(); /* mainly to switch off PCR */
2058 void eDVBServicePlay::updateDecoder()
2060 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2062 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2064 bool defaultac3=false;
2065 std::string default_ac3;
2067 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2068 defaultac3 = default_ac3 == "True";
2070 eDVBServicePMTHandler::program program;
2071 if (h.getProgramInfo(program))
2072 eDebug("getting program info failed.");
2075 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2076 if (!program.videoStreams.empty())
2078 eDebugNoNewLine(" (");
2079 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2080 i(program.videoStreams.begin());
2081 i != program.videoStreams.end(); ++i)
2088 if (i != program.videoStreams.begin())
2089 eDebugNoNewLine(", ");
2090 eDebugNoNewLine("%04x", i->pid);
2092 eDebugNoNewLine(")");
2094 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2095 if (!program.audioStreams.empty())
2097 eDebugNoNewLine(" (");
2098 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2099 i(program.audioStreams.begin());
2100 i != program.audioStreams.end(); ++i)
2102 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2104 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2110 if (i != program.audioStreams.begin())
2111 eDebugNoNewLine(", ");
2112 eDebugNoNewLine("%04x", i->pid);
2114 eDebugNoNewLine(")");
2116 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2117 pcrpid = program.pcrPid;
2118 eDebug(", and the text pid is %04x", program.textPid);
2119 tpid = program.textPid;
2124 h.getDecodeDemux(m_decode_demux);
2127 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2129 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2132 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2133 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2134 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2135 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2136 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2143 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2144 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2145 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2147 else // subservice or recording
2149 eServiceReferenceDVB ref;
2150 m_service_handler.getServiceReference(ref);
2151 eServiceReferenceDVB parent = ref.getParentServiceReference();
2156 ePtr<eDVBResourceManager> res_mgr;
2157 if (!eDVBResourceManager::getInstance(res_mgr))
2159 ePtr<iDVBChannelList> db;
2160 if (!res_mgr->getChannelList(db))
2162 ePtr<eDVBService> origService;
2163 if (!db->getService(parent, origService))
2165 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2166 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2172 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2173 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2175 m_decoder->setVideoPID(vpid, vpidtype);
2176 m_decoder->setAudioPID(apid, apidtype);
2177 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2179 m_decoder->setSyncPCR(pcrpid);
2182 ePtr<iDVBDemux> data_demux;
2183 if (!h.getDataDemux(data_demux))
2185 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
2186 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
2187 m_radiotext_parser->start(apid);
2192 m_decoder->setSyncPCR(-1);
2194 m_decoder->setTextPID(tpid);
2196 m_teletext_parser->start(program.textPid);
2199 m_decoder->setTrickmode(1);
2203 if (vpid > 0 && vpid < 0x2000)
2207 std::string radio_pic;
2208 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2209 m_decoder->setRadioPic(radio_pic);
2212 m_decoder->setAudioChannel(achannel);
2214 // how we can do this better?
2215 // update cache pid when the user changed the audio track or video track
2216 // TODO handling of difference audio types.. default audio types..
2218 /* don't worry about non-existing services, nor pvr services */
2219 if (m_dvb_service && !m_is_pvr)
2221 if (apidtype == eDVBAudio::aMPEG)
2223 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2224 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2228 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2229 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2231 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2232 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2233 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2234 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2237 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2240 void eDVBServicePlay::loadCuesheet()
2242 std::string filename = m_reference.path + ".cuts";
2244 m_cue_entries.clear();
2246 FILE *f = fopen(filename.c_str(), "rb");
2250 eDebug("loading cuts..");
2253 unsigned long long where;
2256 if (!fread(&where, sizeof(where), 1, f))
2258 if (!fread(&what, sizeof(what), 1, f))
2261 #if BYTE_ORDER == LITTLE_ENDIAN
2262 where = bswap_64(where);
2269 m_cue_entries.insert(cueEntry(where, what));
2272 eDebug("%d entries", m_cue_entries.size());
2274 eDebug("cutfile not found!");
2276 m_cuesheet_changed = 0;
2277 cutlistToCuesheet();
2278 m_event((iPlayableService*)this, evCuesheetChanged);
2281 void eDVBServicePlay::saveCuesheet()
2283 std::string filename = m_reference.path + ".cuts";
2285 FILE *f = fopen(filename.c_str(), "wb");
2289 unsigned long long where;
2292 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2294 #if BYTE_ORDER == BIG_ENDIAN
2297 where = bswap_64(i->where);
2299 what = htonl(i->what);
2300 fwrite(&where, sizeof(where), 1, f);
2301 fwrite(&what, sizeof(what), 1, f);
2307 m_cuesheet_changed = 0;
2310 void eDVBServicePlay::cutlistToCuesheet()
2314 eDebug("no cue sheet");
2319 if (!m_cutlist_enabled)
2321 m_cue->commitSpans();
2322 eDebug("cutlists were disabled");
2326 pts_t in = 0, out = 0, length = 0;
2330 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2334 if (i == m_cue_entries.end())
2337 if (i->what == 0) /* in */
2341 } else if (i->what == 1) /* out */
2343 else /* mark (2) or last play position (3) */
2351 m_cue->addSourceSpan(in, out);
2355 if (i == m_cue_entries.end())
2358 m_cue->commitSpans();
2361 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2363 if (m_subtitle_widget)
2364 disableSubtitles(parent);
2367 int tuplesize = PyTuple_Size(tuple);
2370 if (!PyTuple_Check(tuple))
2376 entry = PyTuple_GET_ITEM(tuple, 0);
2378 if (!PyInt_Check(entry))
2381 type = PyInt_AsLong(entry);
2383 if (type == 1) // teletext subtitles
2385 int page, magazine, pid;
2389 if (!m_teletext_parser)
2391 eDebug("enable teletext subtitles.. no parser !!!");
2395 entry = PyTuple_GET_ITEM(tuple, 1);
2396 if (!PyInt_Check(entry))
2398 pid = PyInt_AsLong(entry);
2400 entry = PyTuple_GET_ITEM(tuple, 2);
2401 if (!PyInt_Check(entry))
2403 page = PyInt_AsLong(entry);
2405 entry = PyTuple_GET_ITEM(tuple, 3);
2406 if (!PyInt_Check(entry))
2408 magazine = PyInt_AsLong(entry);
2410 m_subtitle_widget = new eSubtitleWidget(parent);
2411 m_subtitle_widget->resize(parent->size()); /* full size */
2412 m_teletext_parser->setPageAndMagazine(page, magazine);
2414 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2418 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2419 if (!m_subtitle_parser)
2421 eDebug("enable dvb subtitles.. no parser !!!");
2427 entry = PyTuple_GET_ITEM(tuple, 1);
2428 if (!PyInt_Check(entry))
2430 pid = PyInt_AsLong(entry);
2432 entry = PyTuple_GET_ITEM(tuple, 2);
2433 if (!PyInt_Check(entry))
2435 composition_page_id = PyInt_AsLong(entry);
2437 entry = PyTuple_GET_ITEM(tuple, 3);
2438 if (!PyInt_Check(entry))
2440 ancillary_page_id = PyInt_AsLong(entry);
2442 m_subtitle_widget = new eSubtitleWidget(parent);
2443 m_subtitle_widget->resize(parent->size()); /* full size */
2444 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2446 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2452 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2453 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2454 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2458 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2460 delete m_subtitle_widget;
2461 m_subtitle_widget = 0;
2462 if (m_subtitle_parser)
2464 m_subtitle_parser->stop();
2465 m_dvb_subtitle_pages.clear();
2467 if (m_teletext_parser)
2469 m_teletext_parser->setPageAndMagazine(-1, -1);
2470 m_subtitle_pages.clear();
2473 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2477 PyObject *eDVBServicePlay::getCachedSubtitle()
2481 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2484 unsigned int data = (unsigned int)tmp;
2485 int pid = (data&0xFFFF0000)>>16;
2486 ePyObject tuple = PyTuple_New(4);
2487 eDVBServicePMTHandler::program program;
2488 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2489 if (!h.getProgramInfo(program))
2491 if (program.textPid==pid) // teletext
2492 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2494 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2495 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2496 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2497 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2505 PyObject *eDVBServicePlay::getSubtitleList()
2507 if (!m_teletext_parser)
2510 ePyObject l = PyList_New(0);
2511 std::set<int> added_ttx_pages;
2513 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2514 m_teletext_parser->m_found_subtitle_pages;
2516 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2517 eDVBServicePMTHandler::program program;
2518 if (h.getProgramInfo(program))
2519 eDebug("getting program info failed.");
2522 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2523 it != program.subtitleStreams.end(); ++it)
2525 switch(it->subtitling_type)
2527 case 0x01: // ebu teletext subtitles
2529 int page_number = it->teletext_page_number & 0xFF;
2530 int magazine_number = it->teletext_magazine_number & 7;
2531 int hash = magazine_number << 8 | page_number;
2532 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2534 ePyObject tuple = PyTuple_New(5);
2535 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2536 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2537 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2538 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2539 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2540 PyList_Append(l, tuple);
2542 added_ttx_pages.insert(hash);
2547 case 0x20 ... 0x23: // dvb subtitles
2549 ePyObject tuple = PyTuple_New(5);
2550 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2551 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2552 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2553 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2554 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2555 PyList_Insert(l, 0, tuple);
2563 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2564 it != subs.end(); ++it)
2566 int page_number = it->teletext_page_number & 0xFF;
2567 int magazine_number = it->teletext_magazine_number & 7;
2568 int hash = magazine_number << 8 | page_number;
2569 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2571 ePyObject tuple = PyTuple_New(5);
2572 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2573 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2574 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2575 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2576 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2577 PyList_Append(l, tuple);
2585 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2587 if (m_subtitle_widget)
2589 m_subtitle_pages.push_back(page);
2590 checkSubtitleTiming();
2594 void eDVBServicePlay::checkSubtitleTiming()
2596 // eDebug("checkSubtitleTiming");
2597 if (!m_subtitle_widget)
2601 enum { TELETEXT, DVB } type;
2602 eDVBTeletextSubtitlePage page;
2603 eDVBSubtitlePage dvb_page;
2605 if (!m_subtitle_pages.empty())
2607 page = m_subtitle_pages.front();
2609 show_time = page.m_pts;
2611 else if (!m_dvb_subtitle_pages.empty())
2613 dvb_page = m_dvb_subtitle_pages.front();
2615 show_time = dvb_page.m_show_time;
2623 m_decoder->getPTS(0, pos);
2625 // eDebug("%lld %lld", pos, show_time);
2626 int diff = show_time - pos;
2629 eDebug("[late (%d ms)]", -diff / 90);
2634 eDebug("[invalid]");
2640 if (type == TELETEXT)
2642 eDebug("display teletext subtitle page");
2643 m_subtitle_widget->setPage(page);
2644 m_subtitle_pages.pop_front();
2648 eDebug("display dvb subtitle Page");
2649 m_subtitle_widget->setPage(dvb_page);
2650 m_dvb_subtitle_pages.pop_front();
2654 // eDebug("start subtitle delay %d", diff / 90);
2655 m_subtitle_sync_timer.start(diff / 90, 1);
2661 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2663 if (m_subtitle_widget)
2665 m_dvb_subtitle_pages.push_back(p);
2666 checkSubtitleTiming();
2670 int eDVBServicePlay::getAC3Delay()
2673 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2675 return m_decoder->getAC3Delay();
2680 int eDVBServicePlay::getPCMDelay()
2683 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2685 return m_decoder->getPCMDelay();
2690 void eDVBServicePlay::setAC3Delay(int delay)
2693 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2695 m_decoder->setAC3Delay(delay);
2698 void eDVBServicePlay::setPCMDelay(int delay)
2701 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2703 m_decoder->setPCMDelay(delay);
2706 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2708 eDebug("!!!!!!!!!! Video Event type %d, aspect %d, %dx%d", event.type, event.aspect, event.width, event.height);
2709 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2710 m_event((iPlayableService*)this, evVideoSizeChanged);
2713 DEFINE_REF(eDVBServicePlay)
2715 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2719 case iServiceInformation::sTransponderData:
2720 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2724 return iStaticServiceInformation::getInfoObject(ref, w);
2727 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");