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 eBackgroundFileEraser::getInstance()->erase(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 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
1989 i(program.subtitleStreams.begin());
1990 i != program.subtitleStreams.end(); ++i)
1991 pids_to_record.insert(i->pid);
1993 std::set<int> new_pids, obsolete_pids;
1995 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1996 m_pids_active.begin(), m_pids_active.end(),
1997 std::inserter(new_pids, new_pids.begin()));
1999 std::set_difference(
2000 m_pids_active.begin(), m_pids_active.end(),
2001 pids_to_record.begin(), pids_to_record.end(),
2002 std::inserter(new_pids, new_pids.begin())
2005 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2006 m_record->addPID(*i);
2008 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2009 m_record->removePID(*i);
2013 void eDVBServicePlay::switchToLive()
2015 if (!m_timeshift_active)
2021 m_teletext_parser = 0;
2022 m_radiotext_parser = 0;
2023 m_subtitle_parser = 0;
2024 m_new_dvb_subtitle_page_connection = 0;
2025 m_new_subtitle_page_connection = 0;
2026 m_radiotext_updated_connection = 0;
2027 m_video_event_connection = 0;
2029 /* free the timeshift service handler, we need the resources */
2030 m_service_handler_timeshift.free();
2031 m_timeshift_active = 0;
2033 m_event((iPlayableService*)this, evSeekableStatusChanged);
2038 void eDVBServicePlay::switchToTimeshift()
2040 if (m_timeshift_active)
2045 m_teletext_parser = 0;
2046 m_radiotext_parser = 0;
2047 m_subtitle_parser = 0;
2048 m_new_subtitle_page_connection = 0;
2049 m_new_dvb_subtitle_page_connection = 0;
2050 m_radiotext_updated_connection = 0;
2051 m_video_event_connection = 0;
2053 m_timeshift_active = 1;
2055 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2056 r.path = m_timeshift_file;
2058 m_cue = new eCueSheet();
2059 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2060 updateDecoder(); /* mainly to switch off PCR */
2062 m_event((iPlayableService*)this, evSeekableStatusChanged);
2065 void eDVBServicePlay::updateDecoder()
2067 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2069 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2071 bool defaultac3=false;
2072 std::string default_ac3;
2074 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2075 defaultac3 = default_ac3 == "True";
2077 eDVBServicePMTHandler::program program;
2078 if (h.getProgramInfo(program))
2079 eDebug("getting program info failed.");
2082 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2083 if (!program.videoStreams.empty())
2085 eDebugNoNewLine(" (");
2086 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2087 i(program.videoStreams.begin());
2088 i != program.videoStreams.end(); ++i)
2095 if (i != program.videoStreams.begin())
2096 eDebugNoNewLine(", ");
2097 eDebugNoNewLine("%04x", i->pid);
2099 eDebugNoNewLine(")");
2101 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2102 if (!program.audioStreams.empty())
2104 eDebugNoNewLine(" (");
2105 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2106 i(program.audioStreams.begin());
2107 i != program.audioStreams.end(); ++i)
2109 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2111 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2117 if (i != program.audioStreams.begin())
2118 eDebugNoNewLine(", ");
2119 eDebugNoNewLine("%04x", i->pid);
2121 eDebugNoNewLine(")");
2123 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2124 pcrpid = program.pcrPid;
2125 eDebug(", and the text pid is %04x", program.textPid);
2126 tpid = program.textPid;
2131 h.getDecodeDemux(m_decode_demux);
2134 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2136 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2139 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2140 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2141 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2142 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2143 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2150 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2151 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2152 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2154 else // subservice or recording
2156 eServiceReferenceDVB ref;
2157 m_service_handler.getServiceReference(ref);
2158 eServiceReferenceDVB parent = ref.getParentServiceReference();
2163 ePtr<eDVBResourceManager> res_mgr;
2164 if (!eDVBResourceManager::getInstance(res_mgr))
2166 ePtr<iDVBChannelList> db;
2167 if (!res_mgr->getChannelList(db))
2169 ePtr<eDVBService> origService;
2170 if (!db->getService(parent, origService))
2172 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2173 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2179 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2180 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2182 m_decoder->setVideoPID(vpid, vpidtype);
2183 m_decoder->setAudioPID(apid, apidtype);
2184 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2186 m_decoder->setSyncPCR(pcrpid);
2189 ePtr<iDVBDemux> data_demux;
2190 if (!h.getDataDemux(data_demux))
2192 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
2193 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
2194 m_radiotext_parser->start(apid);
2199 m_decoder->setSyncPCR(-1);
2201 m_decoder->setTextPID(tpid);
2203 m_teletext_parser->start(program.textPid);
2206 m_decoder->setTrickmode(1);
2210 if (vpid > 0 && vpid < 0x2000)
2214 std::string radio_pic;
2215 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2216 m_decoder->setRadioPic(radio_pic);
2219 m_decoder->setAudioChannel(achannel);
2221 // how we can do this better?
2222 // update cache pid when the user changed the audio track or video track
2223 // TODO handling of difference audio types.. default audio types..
2225 /* don't worry about non-existing services, nor pvr services */
2226 if (m_dvb_service && !m_is_pvr)
2228 if (apidtype == eDVBAudio::aMPEG)
2230 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2231 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2235 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2236 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2238 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2239 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2240 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2241 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2244 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2247 void eDVBServicePlay::loadCuesheet()
2249 std::string filename = m_reference.path + ".cuts";
2251 m_cue_entries.clear();
2253 FILE *f = fopen(filename.c_str(), "rb");
2257 eDebug("loading cuts..");
2260 unsigned long long where;
2263 if (!fread(&where, sizeof(where), 1, f))
2265 if (!fread(&what, sizeof(what), 1, f))
2268 #if BYTE_ORDER == LITTLE_ENDIAN
2269 where = bswap_64(where);
2276 m_cue_entries.insert(cueEntry(where, what));
2279 eDebug("%d entries", m_cue_entries.size());
2281 eDebug("cutfile not found!");
2283 m_cuesheet_changed = 0;
2284 cutlistToCuesheet();
2285 m_event((iPlayableService*)this, evCuesheetChanged);
2288 void eDVBServicePlay::saveCuesheet()
2290 std::string filename = m_reference.path + ".cuts";
2292 FILE *f = fopen(filename.c_str(), "wb");
2296 unsigned long long where;
2299 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2301 #if BYTE_ORDER == BIG_ENDIAN
2304 where = bswap_64(i->where);
2306 what = htonl(i->what);
2307 fwrite(&where, sizeof(where), 1, f);
2308 fwrite(&what, sizeof(what), 1, f);
2314 m_cuesheet_changed = 0;
2317 void eDVBServicePlay::cutlistToCuesheet()
2321 eDebug("no cue sheet");
2326 if (!m_cutlist_enabled)
2328 m_cue->commitSpans();
2329 eDebug("cutlists were disabled");
2333 pts_t in = 0, out = 0, length = 0;
2337 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2341 if (i == m_cue_entries.end())
2344 if (i->what == 0) /* in */
2348 } else if (i->what == 1) /* out */
2350 else /* mark (2) or last play position (3) */
2358 m_cue->addSourceSpan(in, out);
2362 if (i == m_cue_entries.end())
2365 m_cue->commitSpans();
2368 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2370 if (m_subtitle_widget)
2371 disableSubtitles(parent);
2374 int tuplesize = PyTuple_Size(tuple);
2377 if (!PyTuple_Check(tuple))
2383 entry = PyTuple_GET_ITEM(tuple, 0);
2385 if (!PyInt_Check(entry))
2388 type = PyInt_AsLong(entry);
2390 if (type == 1) // teletext subtitles
2392 int page, magazine, pid;
2396 if (!m_teletext_parser)
2398 eDebug("enable teletext subtitles.. no parser !!!");
2402 entry = PyTuple_GET_ITEM(tuple, 1);
2403 if (!PyInt_Check(entry))
2405 pid = PyInt_AsLong(entry);
2407 entry = PyTuple_GET_ITEM(tuple, 2);
2408 if (!PyInt_Check(entry))
2410 page = PyInt_AsLong(entry);
2412 entry = PyTuple_GET_ITEM(tuple, 3);
2413 if (!PyInt_Check(entry))
2415 magazine = PyInt_AsLong(entry);
2417 m_subtitle_widget = new eSubtitleWidget(parent);
2418 m_subtitle_widget->resize(parent->size()); /* full size */
2419 m_teletext_parser->setPageAndMagazine(page, magazine);
2421 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2425 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2426 if (!m_subtitle_parser)
2428 eDebug("enable dvb subtitles.. no parser !!!");
2434 entry = PyTuple_GET_ITEM(tuple, 1);
2435 if (!PyInt_Check(entry))
2437 pid = PyInt_AsLong(entry);
2439 entry = PyTuple_GET_ITEM(tuple, 2);
2440 if (!PyInt_Check(entry))
2442 composition_page_id = PyInt_AsLong(entry);
2444 entry = PyTuple_GET_ITEM(tuple, 3);
2445 if (!PyInt_Check(entry))
2447 ancillary_page_id = PyInt_AsLong(entry);
2449 m_subtitle_widget = new eSubtitleWidget(parent);
2450 m_subtitle_widget->resize(parent->size()); /* full size */
2451 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2453 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2459 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2460 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2461 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2465 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2467 delete m_subtitle_widget;
2468 m_subtitle_widget = 0;
2469 if (m_subtitle_parser)
2471 m_subtitle_parser->stop();
2472 m_dvb_subtitle_pages.clear();
2474 if (m_teletext_parser)
2476 m_teletext_parser->setPageAndMagazine(-1, -1);
2477 m_subtitle_pages.clear();
2480 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2484 PyObject *eDVBServicePlay::getCachedSubtitle()
2488 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2491 unsigned int data = (unsigned int)tmp;
2492 int pid = (data&0xFFFF0000)>>16;
2493 ePyObject tuple = PyTuple_New(4);
2494 eDVBServicePMTHandler::program program;
2495 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2496 if (!h.getProgramInfo(program))
2498 if (program.textPid==pid) // teletext
2499 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2501 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2502 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2503 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2504 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2512 PyObject *eDVBServicePlay::getSubtitleList()
2514 if (!m_teletext_parser)
2517 ePyObject l = PyList_New(0);
2518 std::set<int> added_ttx_pages;
2520 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2521 m_teletext_parser->m_found_subtitle_pages;
2523 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2524 eDVBServicePMTHandler::program program;
2525 if (h.getProgramInfo(program))
2526 eDebug("getting program info failed.");
2529 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2530 it != program.subtitleStreams.end(); ++it)
2532 switch(it->subtitling_type)
2534 case 0x01: // ebu teletext subtitles
2536 int page_number = it->teletext_page_number & 0xFF;
2537 int magazine_number = it->teletext_magazine_number & 7;
2538 int hash = magazine_number << 8 | page_number;
2539 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2541 ePyObject tuple = PyTuple_New(5);
2542 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2543 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2544 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2545 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2546 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2547 PyList_Append(l, tuple);
2549 added_ttx_pages.insert(hash);
2554 case 0x20 ... 0x23: // dvb subtitles
2556 ePyObject tuple = PyTuple_New(5);
2557 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2558 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2559 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2560 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2561 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2562 PyList_Insert(l, 0, tuple);
2570 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2571 it != subs.end(); ++it)
2573 int page_number = it->teletext_page_number & 0xFF;
2574 int magazine_number = it->teletext_magazine_number & 7;
2575 int hash = magazine_number << 8 | page_number;
2576 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2578 ePyObject tuple = PyTuple_New(5);
2579 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2580 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2581 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2582 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2583 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2584 PyList_Append(l, tuple);
2592 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2594 if (m_subtitle_widget)
2596 m_subtitle_pages.push_back(page);
2597 checkSubtitleTiming();
2601 void eDVBServicePlay::checkSubtitleTiming()
2603 // eDebug("checkSubtitleTiming");
2604 if (!m_subtitle_widget)
2608 enum { TELETEXT, DVB } type;
2609 eDVBTeletextSubtitlePage page;
2610 eDVBSubtitlePage dvb_page;
2612 if (!m_subtitle_pages.empty())
2614 page = m_subtitle_pages.front();
2616 show_time = page.m_pts;
2618 else if (!m_dvb_subtitle_pages.empty())
2620 dvb_page = m_dvb_subtitle_pages.front();
2622 show_time = dvb_page.m_show_time;
2630 m_decoder->getPTS(0, pos);
2632 // eDebug("%lld %lld", pos, show_time);
2633 int diff = show_time - pos;
2636 eDebug("[late (%d ms)]", -diff / 90);
2641 eDebug("[invalid]");
2647 if (type == TELETEXT)
2649 eDebug("display teletext subtitle page");
2650 m_subtitle_widget->setPage(page);
2651 m_subtitle_pages.pop_front();
2655 eDebug("display dvb subtitle Page");
2656 m_subtitle_widget->setPage(dvb_page);
2657 m_dvb_subtitle_pages.pop_front();
2661 // eDebug("start subtitle delay %d", diff / 90);
2662 m_subtitle_sync_timer.start(diff / 90, 1);
2668 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2670 if (m_subtitle_widget)
2672 m_dvb_subtitle_pages.push_back(p);
2673 checkSubtitleTiming();
2677 int eDVBServicePlay::getAC3Delay()
2680 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2682 return m_decoder->getAC3Delay();
2687 int eDVBServicePlay::getPCMDelay()
2690 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2692 return m_decoder->getPCMDelay();
2697 void eDVBServicePlay::setAC3Delay(int delay)
2700 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2702 m_decoder->setAC3Delay(delay);
2705 void eDVBServicePlay::setPCMDelay(int delay)
2708 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2710 m_decoder->setPCMDelay(delay);
2713 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2715 memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2716 m_event((iPlayableService*)this, evVideoSizeChanged);
2719 DEFINE_REF(eDVBServicePlay)
2721 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2725 case iServiceInformation::sTransponderData:
2726 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2730 return iStaticServiceInformation::getInfoObject(ref, w);
2733 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");