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/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
36 DECLARE_REF(eStaticServiceDVBInformation);
38 RESULT getName(const eServiceReference &ref, std::string &name);
39 int getLength(const eServiceReference &ref);
40 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41 PyObject *getInfoObject(const eServiceReference &ref, int);
44 DEFINE_REF(eStaticServiceDVBInformation);
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
48 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49 if ( !ref.name.empty() )
51 if (service.getParentTransportStreamID().get()) // linkage subservice
53 ePtr<iServiceHandler> service_center;
54 if (!eServiceCenter::getInstance(service_center))
56 eServiceReferenceDVB parent = service;
57 parent.setTransportStreamID( service.getParentTransportStreamID() );
58 parent.setServiceID( service.getParentServiceID() );
59 parent.setParentTransportStreamID(eTransportStreamID(0));
60 parent.setParentServiceID(eServiceID(0));
62 ePtr<iStaticServiceInformation> service_info;
63 if (!service_center->info(parent, service_info))
65 if (!service_info->getName(parent, name))
66 name=buildShortName(name) + " - ";
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
86 ePtr<eDVBResourceManager> res_mgr;
87 if ( eDVBResourceManager::getInstance( res_mgr ) )
88 eDebug("isPlayable... no res manager!!");
91 eDVBChannelID chid, chid_ignore;
92 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94 return res_mgr->canAllocateChannel(chid, chid_ignore);
99 static void PutToDictAsStr(ePyObject &dict, const char*key, long value)
101 ePyObject item = PyString_FromFormat("%d", value);
104 if (PyDict_SetItemString(dict, key, item))
105 eDebug("put %s to dict failed", key);
109 eDebug("could not create PyObject for %s", key);
112 extern void PutToDict(ePyObject &dict, const char*key, long value); // defined in dvb/frontend.cpp
113 extern void PutToDict(ePyObject &dict, const char*key, ePyObject item); // defined in dvb/frontend.cpp
114 extern void PutToDict(ePyObject &dict, const char*key, const char *value); // defined in dvb/frontend.cpp
116 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
119 PutToDict(dict, "type", "Satellite");
120 PutToDictAsStr(dict, "frequency", feparm.frequency);
121 PutToDictAsStr(dict, "symbolrate", feparm.symbol_rate);
122 PutToDictAsStr(dict, "orbital position", feparm.orbital_position);
123 switch (feparm.inversion)
125 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
126 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
128 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
130 PutToDict(dict, "inversion", tmp);
133 case eDVBFrontendParametersSatellite::FEC::fNone: tmp="NONE"; break;
134 case eDVBFrontendParametersSatellite::FEC::f1_2: tmp="1/2"; break;
135 case eDVBFrontendParametersSatellite::FEC::f2_3: tmp="2/3"; break;
136 case eDVBFrontendParametersSatellite::FEC::f3_4: tmp="3/4"; break;
137 case eDVBFrontendParametersSatellite::FEC::f5_6: tmp="5/6"; break;
138 case eDVBFrontendParametersSatellite::FEC::f7_8: tmp="7/8"; break;
139 case eDVBFrontendParametersSatellite::FEC::f3_5: tmp="3/5"; break;
140 case eDVBFrontendParametersSatellite::FEC::f4_5: tmp="4/5"; break;
141 case eDVBFrontendParametersSatellite::FEC::f8_9: tmp="8/9"; break;
142 case eDVBFrontendParametersSatellite::FEC::f9_10: tmp="9/10"; break;
144 case eDVBFrontendParametersSatellite::FEC::fAuto: tmp="AUTO"; break;
146 PutToDict(dict, "fec inner", tmp);
147 switch (feparm.modulation)
149 case eDVBFrontendParametersSatellite::Modulation::Auto: tmp="AUTO"; break;
150 case eDVBFrontendParametersSatellite::Modulation::QPSK: tmp="QPSK"; break;
151 case eDVBFrontendParametersSatellite::Modulation::M8PSK: tmp="8PSK"; break;
152 case eDVBFrontendParametersSatellite::Modulation::QAM_16: tmp="QAM16"; break;
154 PutToDict(dict, "modulation", tmp);
155 switch(feparm.polarisation)
157 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
158 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
159 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR LEFT"; break;
161 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR RIGHT"; break;
163 PutToDict(dict, "polarization", tmp);
164 switch(feparm.system)
167 case eDVBFrontendParametersSatellite::System::DVB_S: tmp="DVB-S"; break;
168 case eDVBFrontendParametersSatellite::System::DVB_S2:
169 switch(feparm.rolloff)
172 case eDVBFrontendParametersSatellite::RollOff::alpha_0_35: tmp="0.35"; break;
173 case eDVBFrontendParametersSatellite::RollOff::alpha_0_25: tmp="0.25"; break;
174 case eDVBFrontendParametersSatellite::RollOff::alpha_0_20: tmp="0.20"; break;
176 PutToDict(dict, "roll off", tmp);
179 case eDVBFrontendParametersSatellite::Pilot::On: tmp="ON"; break;
180 case eDVBFrontendParametersSatellite::Pilot::Off: tmp="OFF"; break;
182 case eDVBFrontendParametersSatellite::Pilot::Unknown: tmp="AUTO"; break;
184 PutToDict(dict, "pilot", tmp);
188 PutToDict(dict, "system", tmp);
191 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
193 PutToDict(dict, "type", "Terrestrial");
194 PutToDictAsStr(dict, "frequency", feparm.frequency);
196 switch (feparm.bandwidth)
198 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz: tmp="8 MHz"; break;
199 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz: tmp="7 MHz"; break;
200 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz: tmp="6 MHz"; break;
202 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto: tmp="AUTO"; break;
204 PutToDict(dict, "bandwidth", tmp);
205 switch (feparm.code_rate_LP)
207 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
208 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
209 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
210 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
211 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
213 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
215 PutToDict(dict, "code rate lp", tmp);
216 switch (feparm.code_rate_HP)
218 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
219 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
220 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
221 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
222 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
224 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
226 PutToDict(dict, "code rate hp", tmp);
227 switch (feparm.modulation)
229 case eDVBFrontendParametersTerrestrial::Modulation::QPSK: tmp="QPSK"; break;
230 case eDVBFrontendParametersTerrestrial::Modulation::QAM16: tmp="QAM16"; break;
231 case eDVBFrontendParametersTerrestrial::Modulation::QAM64: tmp="QAM64"; break;
233 case eDVBFrontendParametersTerrestrial::Modulation::Auto: tmp="AUTO"; break;
235 PutToDict(dict, "constellation", tmp);
236 switch (feparm.transmission_mode)
238 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k: tmp="2k"; break;
239 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k: tmp="8k"; break;
241 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto: tmp="AUTO"; break;
243 PutToDict(dict, "transmission mode", tmp);
244 switch (feparm.guard_interval)
246 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32: tmp="1/32"; break;
247 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16: tmp="1/16"; break;
248 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8: tmp="1/8"; break;
249 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4: tmp="1/4"; break;
251 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto: tmp="AUTO"; break;
253 PutToDict(dict, "guard interval", tmp);
254 switch (feparm.hierarchy)
256 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone: tmp="NONE"; break;
257 case eDVBFrontendParametersTerrestrial::Hierarchy::H1: tmp="1"; break;
258 case eDVBFrontendParametersTerrestrial::Hierarchy::H2: tmp="2"; break;
259 case eDVBFrontendParametersTerrestrial::Hierarchy::H4: tmp="4"; break;
261 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto: tmp="AUTO"; break;
263 PutToDict(dict, "hierarchy", tmp);
264 switch (feparm.inversion)
266 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
267 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
269 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
271 PutToDict(dict, "inversion", tmp);
274 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
277 PutToDict(dict, "type", "Cable");
278 PutToDictAsStr(dict, "frequency", feparm.frequency);
279 PutToDictAsStr(dict, "symbolrate", feparm.symbol_rate);
280 switch (feparm.modulation)
282 case eDVBFrontendParametersCable::Modulation::QAM16: tmp="QAM16"; break;
283 case eDVBFrontendParametersCable::Modulation::QAM32: tmp="QAM32"; break;
284 case eDVBFrontendParametersCable::Modulation::QAM64: tmp="QAM64"; break;
285 case eDVBFrontendParametersCable::Modulation::QAM128: tmp="QAM128"; break;
286 case eDVBFrontendParametersCable::Modulation::QAM256: tmp="QAM256"; break;
288 case eDVBFrontendParametersCable::Modulation::Auto: tmp="AUTO"; break;
290 PutToDict(dict, "modulation", tmp);
291 switch (feparm.inversion)
293 case eDVBFrontendParametersCable::Inversion::On: tmp="ON"; break;
294 case eDVBFrontendParametersCable::Inversion::Off: tmp="OFF"; break;
296 case eDVBFrontendParametersCable::Inversion::Unknown: tmp="AUTO"; break;
298 PutToDict(dict, "inversion", tmp);
299 switch (feparm.fec_inner)
301 case eDVBFrontendParametersCable::FEC::fNone: tmp="NONE"; break;
302 case eDVBFrontendParametersCable::FEC::f1_2: tmp="1/2"; break;
303 case eDVBFrontendParametersCable::FEC::f2_3: tmp="2/3"; break;
304 case eDVBFrontendParametersCable::FEC::f3_4: tmp="3/4"; break;
305 case eDVBFrontendParametersCable::FEC::f5_6: tmp="5/6"; break;
306 case eDVBFrontendParametersCable::FEC::f7_8: tmp="7/8"; break;
307 case eDVBFrontendParametersCable::FEC::f8_9: tmp="8/9"; break;
309 case eDVBFrontendParametersCable::FEC::fAuto: tmp="AUTO"; break;
311 PutToDict(dict, "fec inner", tmp);
314 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
316 if (r.type == eServiceReference::idDVB)
318 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
321 case iServiceInformation::sTransponderData:
323 ePtr<eDVBResourceManager> res;
324 if (!eDVBResourceManager::getInstance(res))
326 ePtr<iDVBChannelList> db;
327 if (!res->getChannelList(db))
330 ref.getChannelID(chid);
331 ePtr<iDVBFrontendParameters> feparm;
332 if (!db->getChannelFrontendData(chid, feparm))
335 if (!feparm->getSystem(system))
337 ePyObject dict = PyDict_New();
340 case iDVBFrontend::feSatellite:
342 eDVBFrontendParametersSatellite s;
344 PutSatelliteDataToDict(dict, s);
347 case iDVBFrontend::feTerrestrial:
349 eDVBFrontendParametersTerrestrial t;
351 PutTerrestrialDataToDict(dict, t);
354 case iDVBFrontend::feCable:
356 eDVBFrontendParametersCable c;
358 PutCableDataToDict(dict, c);
362 eDebug("unknown frontend type %d", system);
377 DEFINE_REF(eStaticServiceDVBBouquetInformation);
379 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
381 ePtr<iDVBChannelList> db;
382 ePtr<eDVBResourceManager> res;
385 if ((err = eDVBResourceManager::getInstance(res)) != 0)
387 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
390 if ((err = res->getChannelList(db)) != 0)
392 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
397 if ((err = db->getBouquet(ref, bouquet)) != 0)
399 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
403 if ( bouquet && bouquet->m_bouquet_name.length() )
405 name = bouquet->m_bouquet_name;
412 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
414 if (ref.flags & eServiceReference::isGroup)
416 ePtr<iDVBChannelList> db;
417 ePtr<eDVBResourceManager> res;
419 if (eDVBResourceManager::getInstance(res))
421 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
425 if (res->getChannelList(db))
427 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
432 if (db->getBouquet(ref, bouquet))
434 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
438 int prio_order = eDVBFrontend::getTypePriorityOrder();
440 eDVBChannelID chid, chid_ignore;
441 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
442 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
444 static unsigned char prio_map[6][3] = {
445 { 3, 2, 1 }, // -S -C -T
446 { 3, 1, 2 }, // -S -T -C
447 { 2, 3, 1 }, // -C -S -T
448 { 1, 3, 2 }, // -C -T -S
449 { 1, 2, 3 }, // -T -C -S
450 { 2, 1, 3 } // -T -S -C
452 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
453 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
458 case 30000: // cached DVB-T channel
459 case 1: // DVB-T frontend
460 tmp = prio_map[prio_order][2];
462 case 40000: // cached DVB-C channel
464 tmp = prio_map[prio_order][1];
467 tmp = prio_map[prio_order][0];
472 m_playable_service = *it;
479 m_playable_service = eServiceReference();
483 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
488 #include <lib/dvb/epgcache.h>
490 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
492 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
495 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
497 DECLARE_REF(eStaticServiceDVBPVRInformation);
498 eServiceReference m_ref;
499 eDVBMetaParser m_parser;
501 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
502 RESULT getName(const eServiceReference &ref, std::string &name);
503 int getLength(const eServiceReference &ref);
504 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
505 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
506 int getInfo(const eServiceReference &ref, int w);
507 std::string getInfoString(const eServiceReference &ref,int w);
510 DEFINE_REF(eStaticServiceDVBPVRInformation);
512 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
515 m_parser.parseFile(ref.path);
518 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
520 ASSERT(ref == m_ref);
521 if (m_parser.m_name.size())
522 name = m_parser.m_name;
526 size_t n = name.rfind('/');
527 if (n != std::string::npos)
528 name = name.substr(n + 1);
533 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
535 ASSERT(ref == m_ref);
539 if (tstools.openFile(ref.path.c_str()))
543 if (tstools.calcLen(len))
549 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
553 case iServiceInformation::sDescription:
554 return iServiceInformation::resIsString;
555 case iServiceInformation::sServiceref:
556 return iServiceInformation::resIsString;
557 case iServiceInformation::sTimeCreate:
558 if (m_parser.m_time_create)
559 return m_parser.m_time_create;
561 return iServiceInformation::resNA;
563 return iServiceInformation::resNA;
567 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
571 case iServiceInformation::sDescription:
572 return m_parser.m_description;
573 case iServiceInformation::sServiceref:
574 return m_parser.m_ref.toString();
575 case iServiceInformation::sTags:
576 return m_parser.m_tags;
582 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
584 if (!ref.path.empty())
586 ePtr<eServiceEvent> event = new eServiceEvent;
587 std::string filename = ref.path;
588 filename.erase(filename.length()-2, 2);
590 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
600 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
602 DECLARE_REF(eDVBPVRServiceOfflineOperations);
603 eServiceReferenceDVB m_ref;
605 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
607 RESULT deleteFromDisk(int simulate);
608 RESULT getListOfFilenames(std::list<std::string> &);
611 DEFINE_REF(eDVBPVRServiceOfflineOperations);
613 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
617 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
623 std::list<std::string> res;
624 if (getListOfFilenames(res))
627 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
629 eDebug("FATAL !! can't get background file eraser");
631 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
633 eDebug("Removing %s...", i->c_str());
635 eraser->erase(i->c_str());
637 ::unlink(i->c_str());
644 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
647 res.push_back(m_ref.path);
649 // handling for old splitted recordings (enigma 1)
654 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
656 if (stat(buf, &s) < 0)
661 res.push_back(m_ref.path + ".meta");
662 res.push_back(m_ref.path + ".ap");
663 res.push_back(m_ref.path + ".cuts");
664 std::string tmp = m_ref.path;
665 tmp.erase(m_ref.path.length()-3);
666 res.push_back(tmp + ".eit");
670 DEFINE_REF(eServiceFactoryDVB)
672 eServiceFactoryDVB::eServiceFactoryDVB()
674 ePtr<eServiceCenter> sc;
676 eServiceCenter::getPrivInstance(sc);
679 std::list<std::string> extensions;
680 extensions.push_back("ts");
681 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
684 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
685 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
688 eServiceFactoryDVB::~eServiceFactoryDVB()
690 ePtr<eServiceCenter> sc;
692 eServiceCenter::getPrivInstance(sc);
694 sc->removeServiceFactory(eServiceFactoryDVB::id);
697 DEFINE_REF(eDVBServiceList);
699 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
703 eDVBServiceList::~eDVBServiceList()
707 RESULT eDVBServiceList::startQuery()
709 ePtr<iDVBChannelList> db;
710 ePtr<eDVBResourceManager> res;
713 if ((err = eDVBResourceManager::getInstance(res)) != 0)
715 eDebug("no resource manager");
718 if ((err = res->getChannelList(db)) != 0)
720 eDebug("no channel list");
724 ePtr<eDVBChannelQuery> q;
726 if (!m_parent.path.empty())
728 eDVBChannelQuery::compile(q, m_parent.path);
731 eDebug("compile query failed");
736 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
738 eDebug("startQuery failed");
745 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
747 eServiceReferenceDVB ref;
752 while (!m_query->getNextResult(ref))
756 list.sort(iListableServiceCompare(this));
761 // The first argument of this function is a format string to specify the order and
762 // the content of the returned list
763 // useable format options are
764 // R = Service Reference (as swig object .. this is very slow)
765 // S = Service Reference (as python string object .. same as ref.toString())
766 // C = Service Reference (as python string object .. same as ref.toCompareString())
767 // N = Service Name (as python string object)
768 // n = Short Service Name (short name brakets used) (as python string object)
769 // when exactly one return value per service is selected in the format string,
770 // then each value is directly a list entry
771 // when more than one value is returned per service, then the list is a list of
773 // unknown format string chars are returned as python None values !
774 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
777 std::list<eServiceReference> tmplist;
780 if (!format || !(retcount=strlen(format)))
781 format = "R"; // just return service reference swig object ...
783 if (!getContent(tmplist, sorted))
785 int services=tmplist.size();
786 ePtr<iStaticServiceInformation> sptr;
787 eServiceCenterPtr service_center;
789 if (strchr(format, 'N') || strchr(format, 'n'))
790 eServiceCenter::getPrivInstance(service_center);
792 ret = PyList_New(services);
793 std::list<eServiceReference>::iterator it(tmplist.begin());
795 for (int cnt=0; cnt < services; ++cnt)
797 eServiceReference &ref=*it++;
798 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
799 for (int i=0; i < retcount; ++i)
804 case 'R': // service reference (swig)object
805 tmp = NEW_eServiceReference(ref);
807 case 'C': // service reference compare string
808 tmp = PyString_FromString(ref.toCompareString().c_str());
810 case 'S': // service reference string
811 tmp = PyString_FromString(ref.toString().c_str());
813 case 'N': // service name
816 service_center->info(ref, sptr);
820 sptr->getName(ref, name);
822 // filter short name brakets
824 while((pos = name.find("\xc2\x86")) != std::string::npos)
826 while((pos = name.find("\xc2\x87")) != std::string::npos)
830 tmp = PyString_FromString(name.c_str());
834 tmp = PyString_FromString("<n/a>");
836 case 'n': // short service name
839 service_center->info(ref, sptr);
843 sptr->getName(ref, name);
844 name = buildShortName(name);
846 tmp = PyString_FromString(name.c_str());
850 tmp = PyString_FromString("<n/a>");
863 PyTuple_SET_ITEM(tuple, i, tmp);
865 PyList_SET_ITEM(ret, cnt, tmp);
869 PyList_SET_ITEM(ret, cnt, tuple);
872 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
875 RESULT eDVBServiceList::getNext(eServiceReference &ref)
880 return m_query->getNextResult((eServiceReferenceDVB&)ref);
883 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
885 if (m_parent.flags & eServiceReference::canDescent) // bouquet
887 ePtr<iDVBChannelList> db;
888 ePtr<eDVBResourceManager> resm;
890 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
893 if (db->getBouquet(m_parent, m_bouquet) != 0)
904 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
908 return m_bouquet->addService(ref, before);
911 RESULT eDVBServiceList::removeService(eServiceReference &ref)
915 return m_bouquet->removeService(ref);
918 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
922 return m_bouquet->moveService(ref, pos);
925 RESULT eDVBServiceList::flushChanges()
929 return m_bouquet->flushChanges();
932 RESULT eDVBServiceList::setListName(const std::string &name)
936 return m_bouquet->setListName(name);
939 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
941 ePtr<eDVBService> service;
942 int r = lookupService(service, ref);
945 // check resources...
946 ptr = new eDVBServicePlay(ref, service);
950 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
952 if (ref.path.empty())
954 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
963 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
965 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
966 if (list->startQuery())
976 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
978 /* is a listable service? */
979 if (ref.flags & eServiceReference::canDescent) // bouquet
981 if ( !ref.name.empty() ) // satellites or providers list
982 ptr = m_StaticServiceDVBInfo;
983 else // a dvb bouquet
984 ptr = m_StaticServiceDVBBouquetInfo;
986 else if (!ref.path.empty()) /* do we have a PVR service? */
987 ptr = new eStaticServiceDVBPVRInformation(ref);
988 else // normal dvb service
990 ePtr<eDVBService> service;
991 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
992 ptr = m_StaticServiceDVBInfo;
994 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
1000 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
1002 if (ref.path.empty())
1008 ptr = new eDVBPVRServiceOfflineOperations(ref);
1013 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
1015 // TODO: handle the listing itself
1016 // if (ref.... == -1) .. return "... bouquets ...";
1017 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
1019 ePtr<iDVBChannelList> db;
1020 ePtr<eDVBResourceManager> res;
1023 if ((err = eDVBResourceManager::getInstance(res)) != 0)
1025 eDebug("no resource manager");
1028 if ((err = res->getChannelList(db)) != 0)
1030 eDebug("no channel list");
1034 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
1035 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
1037 eDebug("getService failed!");
1044 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
1045 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
1048 m_is_pvr = !m_reference.path.empty();
1050 m_timeshift_enabled = m_timeshift_active = 0;
1053 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
1054 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
1055 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
1057 m_cuesheet_changed = 0;
1058 m_cutlist_enabled = 1;
1060 m_subtitle_widget = 0;
1064 m_subtitle_sync_timer = eTimer::create(eApp);
1066 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
1069 eDVBServicePlay::~eDVBServicePlay()
1071 delete m_subtitle_widget;
1074 void eDVBServicePlay::gotNewEvent()
1078 ePtr<eServiceEvent> m_event_now, m_event_next;
1079 getEvent(m_event_now, 0);
1080 getEvent(m_event_next, 1);
1083 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1085 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1087 m_event((iPlayableService*)this, evUpdatedEventInfo);
1090 void eDVBServicePlay::serviceEvent(int event)
1092 m_tune_state = event;
1096 case eDVBServicePMTHandler::eventTuned:
1098 ePtr<iDVBDemux> m_demux;
1099 if (!m_service_handler.getDataDemux(m_demux))
1101 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1102 int sid = ref.getParentServiceID().get();
1104 sid = ref.getServiceID().get();
1105 if ( ref.getParentTransportStreamID().get() &&
1106 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1107 m_event_handler.startOther(m_demux, sid);
1109 m_event_handler.start(m_demux, sid);
1111 m_event((iPlayableService*)this, evTunedIn);
1114 case eDVBServicePMTHandler::eventNoResources:
1115 case eDVBServicePMTHandler::eventNoPAT:
1116 case eDVBServicePMTHandler::eventNoPATEntry:
1117 case eDVBServicePMTHandler::eventNoPMT:
1118 case eDVBServicePMTHandler::eventTuneFailed:
1119 case eDVBServicePMTHandler::eventMisconfiguration:
1121 eDebug("DVB service failed to tune - error %d", event);
1122 m_event((iPlayableService*)this, evTuneFailed);
1125 case eDVBServicePMTHandler::eventNewProgramInfo:
1127 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1128 if (m_timeshift_enabled)
1129 updateTimeshiftPids();
1130 if (!m_timeshift_active)
1132 if (m_first_program_info && m_is_pvr)
1134 m_first_program_info = 0;
1137 m_event((iPlayableService*)this, evUpdatedInfo);
1140 case eDVBServicePMTHandler::eventEOF:
1141 m_event((iPlayableService*)this, evEOF);
1143 case eDVBServicePMTHandler::eventSOF:
1144 m_event((iPlayableService*)this, evSOF);
1149 void eDVBServicePlay::serviceEventTimeshift(int event)
1153 case eDVBServicePMTHandler::eventNewProgramInfo:
1154 if (m_timeshift_active)
1157 case eDVBServicePMTHandler::eventSOF:
1158 m_event((iPlayableService*)this, evSOF);
1160 case eDVBServicePMTHandler::eventEOF:
1161 if ((!m_is_paused) && (m_skipmode >= 0))
1167 RESULT eDVBServicePlay::start()
1170 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1171 two (one for decoding, one for data source), as we must be prepared
1172 to start recording from the data demux. */
1174 m_cue = new eCueSheet();
1176 m_event(this, evStart);
1178 m_first_program_info = 1;
1179 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1180 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1182 /* inject EIT if there is a stored one */
1185 std::string filename = service.path;
1186 filename.erase(filename.length()-2, 2);
1188 ePtr<eServiceEvent> event = new eServiceEvent;
1189 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1191 ePtr<eServiceEvent> empty;
1192 m_event_handler.inject(event, 0);
1193 m_event_handler.inject(empty, 1);
1200 m_event(this, evStart);
1205 RESULT eDVBServicePlay::stop()
1207 /* add bookmark for last play position */
1210 pts_t play_position, length;
1211 if (!getPlayPosition(play_position))
1213 /* remove last position */
1214 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1216 if (i->what == 3) /* current play position */
1218 m_cue_entries.erase(i);
1219 i = m_cue_entries.begin();
1225 if (getLength(length))
1230 int perc = play_position * 100LL / length;
1232 /* only store last play position when between 1% and 99% */
1233 if ((1 < perc) && (perc < 99))
1234 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1236 m_cuesheet_changed = 1;
1240 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1242 m_service_handler_timeshift.free();
1243 m_service_handler.free();
1245 if (m_is_pvr && m_cuesheet_changed)
1248 /* save cuesheet only when main file is accessible. */
1249 if (!::stat(m_reference.path.c_str(), &s))
1252 m_event((iPlayableService*)this, evStopped);
1256 RESULT eDVBServicePlay::setTarget(int target)
1258 m_is_primary = !target;
1262 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1264 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1268 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1270 /* note: we check for timeshift to be enabled,
1271 not neccessary active. if you pause when timeshift
1272 is not active, you should activate it when unpausing */
1273 if ((!m_is_pvr) && (!m_timeshift_enabled))
1283 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1286 return m_decoder->setSlowMotion(ratio);
1291 RESULT eDVBServicePlay::setFastForward(int ratio)
1293 int skipmode, ffratio;
1299 } else if (ratio > 0)
1307 } else // if (ratio < 0)
1313 if (m_skipmode != skipmode)
1315 eDebug("setting cue skipmode to %d", skipmode);
1317 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1320 m_skipmode = skipmode;
1325 return m_decoder->setFastForward(ffratio);
1328 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1330 if (m_is_pvr || m_timeshift_enabled)
1340 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1341 RESULT eDVBServicePlay::getLength(pts_t &len)
1343 ePtr<iDVBPVRChannel> pvr_channel;
1345 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1348 return pvr_channel->getLength(len);
1351 RESULT eDVBServicePlay::pause()
1353 if (!m_is_paused && m_decoder)
1356 return m_decoder->freeze(0);
1361 RESULT eDVBServicePlay::unpause()
1363 if (m_is_paused && m_decoder)
1366 return m_decoder->unfreeze();
1371 RESULT eDVBServicePlay::seekTo(pts_t to)
1373 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1375 if (!m_decode_demux)
1378 ePtr<iDVBPVRChannel> pvr_channel;
1380 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1386 m_cue->seekTo(0, to);
1387 m_dvb_subtitle_pages.clear();
1388 m_subtitle_pages.clear();
1393 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1395 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1397 if (!m_decode_demux)
1400 ePtr<iDVBPVRChannel> pvr_channel;
1402 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1407 /* HACK until we have skip-AP api */
1408 if ((to > 0) && (to < 100))
1416 m_cue->seekTo(mode, to);
1417 m_dvb_subtitle_pages.clear();
1418 m_subtitle_pages.clear();
1422 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1424 ePtr<iDVBPVRChannel> pvr_channel;
1426 if (!m_decode_demux)
1429 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1434 /* if there is a decoder, use audio or video PTS */
1437 r = m_decoder->getPTS(0, pos);
1443 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1446 RESULT eDVBServicePlay::setTrickmode(int trick)
1449 m_decoder->setTrickmode(trick);
1453 RESULT eDVBServicePlay::isCurrentlySeekable()
1455 return m_is_pvr || m_timeshift_active;
1458 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1464 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1470 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1476 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1482 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1488 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1491 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1492 (m_timeshift_enabled || !m_is_pvr))
1494 if (!m_timeshift_enabled)
1496 /* query config path */
1498 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1499 eDebug("could not query ts path from config");
1503 /* we need enough diskspace */
1505 if (statfs(tspath.c_str(), &fs) < 0)
1507 eDebug("statfs failed!");
1511 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1513 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1523 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1534 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1540 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1546 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1552 RESULT eDVBServicePlay::getName(std::string &name)
1556 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1557 return i->getName(m_reference, name);
1561 m_dvb_service->getName(m_reference, name);
1565 else if (!m_reference.name.empty())
1566 eStaticServiceDVBInformation().getName(m_reference, name);
1568 name = "DVB service";
1572 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1574 return m_event_handler.getEvent(evt, nownext);
1577 int eDVBServicePlay::getInfo(int w)
1579 eDVBServicePMTHandler::program program;
1582 return resIsPyObject;
1584 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1586 int no_program_info = 0;
1588 if (h.getProgramInfo(program))
1589 no_program_info = 1;
1595 return m_decoder->getVideoHeight();
1599 return m_decoder->getVideoWidth();
1603 return m_decoder->getVideoFrameRate();
1607 return m_decoder->getVideoProgressive();
1613 aspect = m_decoder->getVideoAspect();
1614 if (no_program_info)
1616 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1618 ePtr<eServiceEvent> evt;
1619 if (!m_event_handler.getEvent(evt, 0))
1621 ePtr<eComponentData> data;
1622 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1624 if ( data->getStreamContent() == 1 )
1626 switch(data->getComponentType())
1629 case 1: // 4:3 SD PAL
1631 case 3: // 16:9 SD PAL
1632 case 4: // > 16:9 PAL
1633 case 5: // 4:3 SD NTSC
1635 case 7: // 16:9 SD NTSC
1636 case 8: // > 16:9 NTSC
1639 case 9: // 4:3 HD PAL
1641 case 0xB: // 16:9 HD PAL
1642 case 0xC: // > 16:9 HD PAL
1643 case 0xD: // 4:3 HD NTSC
1645 case 0xF: // 16:9 HD NTSC
1646 case 0x10: // > 16:9 HD PAL
1647 return data->getComponentType();
1657 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1658 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1659 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1660 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1661 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1662 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1663 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1664 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1665 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1666 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1667 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1668 case sProvider: if (!m_dvb_service) return -1; return -2;
1669 case sServiceref: return resIsString;
1670 case sDVBState: return m_tune_state;
1677 std::string eDVBServicePlay::getInfoString(int w)
1682 if (!m_dvb_service) return "";
1683 return m_dvb_service->m_provider_name;
1685 return m_reference.toString();
1689 return iServiceInformation::getInfoString(w);
1692 PyObject *eDVBServicePlay::getInfoObject(int w)
1697 return m_service_handler.getCaIds();
1698 case sTransponderData:
1699 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1703 return iServiceInformation::getInfoObject(w);
1706 int eDVBServicePlay::getNumberOfTracks()
1708 eDVBServicePMTHandler::program program;
1709 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1710 if (h.getProgramInfo(program))
1712 return program.audioStreams.size();
1715 int eDVBServicePlay::getCurrentTrack()
1717 eDVBServicePMTHandler::program program;
1718 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1719 if (h.getProgramInfo(program))
1722 int max = program.audioStreams.size();
1725 for (i = 0; i < max; ++i)
1726 if (program.audioStreams[i].pid == m_current_audio_pid)
1732 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1734 int ret = selectAudioStream(i);
1736 if (m_decoder->start())
1742 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1744 eDVBServicePMTHandler::program program;
1745 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1747 if (h.getProgramInfo(program))
1750 if (i >= program.audioStreams.size())
1753 info.m_pid = program.audioStreams[i].pid;
1755 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1756 info.m_description = "MPEG";
1757 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1758 info.m_description = "AC3";
1759 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1760 info.m_description = "AAC";
1761 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1762 info.m_description = "DTS";
1764 info.m_description = "???";
1766 if (program.audioStreams[i].component_tag != -1)
1768 ePtr<eServiceEvent> evt;
1769 if (!m_event_handler.getEvent(evt, 0))
1771 ePtr<eComponentData> data;
1772 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1773 info.m_language = data->getText();
1777 if (info.m_language.empty())
1778 info.m_language = program.audioStreams[i].language_code;
1783 int eDVBServicePlay::selectAudioStream(int i)
1785 eDVBServicePMTHandler::program program;
1786 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1788 if (h.getProgramInfo(program))
1791 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1799 stream = program.defaultAudioStream;
1801 int apid = -1, apidtype = -1;
1803 if (((unsigned int)stream) < program.audioStreams.size())
1805 apid = program.audioStreams[stream].pid;
1806 apidtype = program.audioStreams[stream].type;
1809 m_current_audio_pid = apid;
1811 if (m_decoder->setAudioPID(apid, apidtype))
1813 eDebug("set audio pid failed");
1817 /* if we are not in PVR mode, timeshift is not active and we are not in pip mode, check if we need to enable the rds reader */
1818 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1821 ePtr<iDVBDemux> data_demux;
1822 if (!h.getDataDemux(data_demux))
1824 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1825 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1829 /* if we decided that we need one, update the pid */
1831 m_rds_decoder->start(apid);
1833 /* store new pid as default only when:
1834 a.) we have an entry in the service db for the current service,
1835 b.) we are not playing back something,
1836 c.) we are not selecting the default entry. (we wouldn't change
1837 anything in the best case, or destroy the default setting in
1838 case the real default is not yet available.)
1840 if (m_dvb_service && !m_is_pvr && ((i != -1)
1841 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1843 if (apidtype == eDVBAudio::aMPEG)
1845 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1846 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1850 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1851 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1855 h.resetCachedProgram();
1860 int eDVBServicePlay::getCurrentChannel()
1862 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1865 RESULT eDVBServicePlay::selectChannel(int i)
1867 if (i < LEFT || i > RIGHT || i == STEREO)
1870 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1872 m_decoder->setAudioChannel(i);
1876 std::string eDVBServicePlay::getText(int x)
1882 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1884 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1889 void eDVBServicePlay::rdsDecoderEvent(int what)
1893 case eDVBRdsDecoder::RadioTextChanged:
1894 m_event((iPlayableService*)this, evUpdatedRadioText);
1896 case eDVBRdsDecoder::RtpTextChanged:
1897 m_event((iPlayableService*)this, evUpdatedRtpText);
1899 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1900 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1902 case eDVBRdsDecoder::RecvRassSlidePic:
1903 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1908 void eDVBServicePlay::showRassSlidePicture()
1914 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1915 if (rass_slide_pic.length())
1916 m_decoder->showSinglePic(rass_slide_pic.c_str());
1918 eDebug("empty filename for rass slide picture received!!");
1921 eDebug("no MPEG Decoder to show iframes avail");
1924 eDebug("showRassSlidePicture called.. but not decoder");
1927 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1933 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1934 if (rass_interactive_pic.length())
1935 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1937 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1940 eDebug("no MPEG Decoder to show iframes avail");
1943 eDebug("showRassInteractivePic called.. but not decoder");
1946 ePyObject eDVBServicePlay::getRassInteractiveMask()
1949 return m_rds_decoder->getRassPictureMask();
1953 int eDVBServiceBase::getFrontendInfo(int w)
1955 eUsePtr<iDVBChannel> channel;
1956 if(m_service_handler.getChannel(channel))
1958 ePtr<iDVBFrontend> fe;
1959 if(channel->getFrontend(fe))
1961 return fe->readFrontendData(w);
1964 PyObject *eDVBServiceBase::getFrontendData()
1966 ePyObject ret = PyDict_New();
1969 eUsePtr<iDVBChannel> channel;
1970 if(!m_service_handler.getChannel(channel))
1972 ePtr<iDVBFrontend> fe;
1973 if(!channel->getFrontend(fe))
1974 fe->getFrontendData(ret);
1982 PyObject *eDVBServiceBase::getFrontendStatus()
1984 ePyObject ret = PyDict_New();
1987 eUsePtr<iDVBChannel> channel;
1988 if(!m_service_handler.getChannel(channel))
1990 ePtr<iDVBFrontend> fe;
1991 if(!channel->getFrontend(fe))
1992 fe->getFrontendStatus(ret);
2000 PyObject *eDVBServiceBase::getTransponderData(bool original)
2002 ePyObject ret = PyDict_New();
2005 eUsePtr<iDVBChannel> channel;
2006 if(!m_service_handler.getChannel(channel))
2008 ePtr<iDVBFrontend> fe;
2009 if(!channel->getFrontend(fe))
2011 fe->getTransponderData(ret, original);
2012 ePtr<iDVBFrontendParameters> feparm;
2013 channel->getCurrentFrontendParameters(feparm);
2016 eDVBFrontendParametersSatellite osat;
2017 if (!feparm->getDVBS(osat))
2019 PutToDict(ret, "orbital_position", osat.orbital_position);
2020 const char *tmp = "UNKNOWN";
2021 switch(osat.polarisation)
2023 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2024 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2025 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2026 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2029 PutToDict(ret, "polarization", tmp);
2040 PyObject *eDVBServiceBase::getAll(bool original)
2042 ePyObject ret = getTransponderData(original);
2045 eUsePtr<iDVBChannel> channel;
2046 if(!m_service_handler.getChannel(channel))
2048 ePtr<iDVBFrontend> fe;
2049 if(!channel->getFrontend(fe))
2051 fe->getFrontendData(ret);
2052 fe->getFrontendStatus(ret);
2059 int eDVBServicePlay::getNumberOfSubservices()
2061 ePtr<eServiceEvent> evt;
2062 if (!m_event_handler.getEvent(evt, 0))
2063 return evt->getNumOfLinkageServices();
2067 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2069 ePtr<eServiceEvent> evt;
2070 if (!m_event_handler.getEvent(evt, 0))
2072 if (!evt->getLinkageService(sub, m_reference, n))
2075 sub.type=eServiceReference::idInvalid;
2079 RESULT eDVBServicePlay::startTimeshift()
2081 ePtr<iDVBDemux> demux;
2083 eDebug("Start timeshift!");
2085 if (m_timeshift_enabled)
2088 /* start recording with the data demux. */
2089 if (m_service_handler.getDataDemux(demux))
2092 demux->createTSRecorder(m_record);
2097 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2098 eDebug("could not query ts path");
2101 tspath.append("/timeshift.XXXXXX");
2103 templ = new char[tspath.length() + 1];
2104 strcpy(templ, tspath.c_str());
2106 m_timeshift_fd = mkstemp(templ);
2107 m_timeshift_file = std::string(templ);
2109 eDebug("recording to %s", templ);
2113 if (m_timeshift_fd < 0)
2119 m_record->setTargetFD(m_timeshift_fd);
2121 m_timeshift_enabled = 1;
2123 updateTimeshiftPids();
2129 RESULT eDVBServicePlay::stopTimeshift()
2131 if (!m_timeshift_enabled)
2136 m_timeshift_enabled = 0;
2141 close(m_timeshift_fd);
2142 eDebug("remove timeshift file");
2143 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2148 int eDVBServicePlay::isTimeshiftActive()
2150 return m_timeshift_enabled && m_timeshift_active;
2153 RESULT eDVBServicePlay::activateTimeshift()
2155 if (!m_timeshift_enabled)
2158 if (!m_timeshift_active)
2160 switchToTimeshift();
2167 PyObject *eDVBServicePlay::getCutList()
2169 ePyObject list = PyList_New(0);
2171 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2173 ePyObject tuple = PyTuple_New(2);
2174 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2175 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2176 PyList_Append(list, tuple);
2183 void eDVBServicePlay::setCutList(ePyObject list)
2185 if (!PyList_Check(list))
2187 int size = PyList_Size(list);
2190 m_cue_entries.clear();
2192 for (i=0; i<size; ++i)
2194 ePyObject tuple = PyList_GET_ITEM(list, i);
2195 if (!PyTuple_Check(tuple))
2197 eDebug("non-tuple in cutlist");
2200 if (PyTuple_Size(tuple) != 2)
2202 eDebug("cutlist entries need to be a 2-tuple");
2205 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2206 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2208 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2211 pts_t pts = PyLong_AsLongLong(ppts);
2212 int type = PyInt_AsLong(ptype);
2213 m_cue_entries.insert(cueEntry(pts, type));
2214 eDebug("adding %08llx, %d", pts, type);
2216 m_cuesheet_changed = 1;
2218 cutlistToCuesheet();
2219 m_event((iPlayableService*)this, evCuesheetChanged);
2222 void eDVBServicePlay::setCutListEnable(int enable)
2224 m_cutlist_enabled = enable;
2225 cutlistToCuesheet();
2228 void eDVBServicePlay::updateTimeshiftPids()
2233 eDVBServicePMTHandler::program program;
2234 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2236 if (h.getProgramInfo(program))
2240 std::set<int> pids_to_record;
2241 pids_to_record.insert(0); // PAT
2242 if (program.pmtPid != -1)
2243 pids_to_record.insert(program.pmtPid); // PMT
2245 if (program.textPid != -1)
2246 pids_to_record.insert(program.textPid); // Videotext
2248 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2249 i(program.videoStreams.begin());
2250 i != program.videoStreams.end(); ++i)
2251 pids_to_record.insert(i->pid);
2253 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2254 i(program.audioStreams.begin());
2255 i != program.audioStreams.end(); ++i)
2256 pids_to_record.insert(i->pid);
2258 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2259 i(program.subtitleStreams.begin());
2260 i != program.subtitleStreams.end(); ++i)
2261 pids_to_record.insert(i->pid);
2263 std::set<int> new_pids, obsolete_pids;
2265 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2266 m_pids_active.begin(), m_pids_active.end(),
2267 std::inserter(new_pids, new_pids.begin()));
2269 std::set_difference(
2270 m_pids_active.begin(), m_pids_active.end(),
2271 pids_to_record.begin(), pids_to_record.end(),
2272 std::inserter(new_pids, new_pids.begin())
2275 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2276 m_record->addPID(*i);
2278 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2279 m_record->removePID(*i);
2283 void eDVBServicePlay::switchToLive()
2285 if (!m_timeshift_active)
2291 m_teletext_parser = 0;
2293 m_subtitle_parser = 0;
2294 m_new_dvb_subtitle_page_connection = 0;
2295 m_new_subtitle_page_connection = 0;
2296 m_rds_decoder_event_connection = 0;
2297 m_video_event_connection = 0;
2299 /* free the timeshift service handler, we need the resources */
2300 m_service_handler_timeshift.free();
2301 m_timeshift_active = 0;
2303 m_event((iPlayableService*)this, evSeekableStatusChanged);
2308 void eDVBServicePlay::switchToTimeshift()
2310 if (m_timeshift_active)
2315 m_teletext_parser = 0;
2317 m_subtitle_parser = 0;
2318 m_new_subtitle_page_connection = 0;
2319 m_new_dvb_subtitle_page_connection = 0;
2320 m_rds_decoder_event_connection = 0;
2321 m_video_event_connection = 0;
2323 m_timeshift_active = 1;
2325 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2326 r.path = m_timeshift_file;
2328 m_cue = new eCueSheet();
2329 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2331 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2333 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2335 m_event((iPlayableService*)this, evSeekableStatusChanged);
2338 void eDVBServicePlay::updateDecoder()
2340 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2342 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2344 eDVBServicePMTHandler::program program;
2345 if (h.getProgramInfo(program))
2346 eDebug("getting program info failed.");
2349 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2350 if (!program.videoStreams.empty())
2352 eDebugNoNewLine(" (");
2353 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2354 i(program.videoStreams.begin());
2355 i != program.videoStreams.end(); ++i)
2362 if (i != program.videoStreams.begin())
2363 eDebugNoNewLine(", ");
2364 eDebugNoNewLine("%04x", i->pid);
2366 eDebugNoNewLine(")");
2368 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2369 if (!program.audioStreams.empty())
2371 eDebugNoNewLine(" (");
2372 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2373 i(program.audioStreams.begin());
2374 i != program.audioStreams.end(); ++i)
2376 if (i != program.audioStreams.begin())
2377 eDebugNoNewLine(", ");
2378 eDebugNoNewLine("%04x", i->pid);
2380 eDebugNoNewLine(")");
2382 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2383 pcrpid = program.pcrPid;
2384 eDebug(", and the text pid is %04x", program.textPid);
2385 tpid = program.textPid;
2390 h.getDecodeDemux(m_decode_demux);
2393 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2395 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2396 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2397 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2398 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2399 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2402 m_teletext_parser = 0;
2403 m_subtitle_parser = 0;
2407 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2414 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2415 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2416 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2418 else // subservice or recording
2420 eServiceReferenceDVB ref;
2421 m_service_handler.getServiceReference(ref);
2422 eServiceReferenceDVB parent = ref.getParentServiceReference();
2427 ePtr<eDVBResourceManager> res_mgr;
2428 if (!eDVBResourceManager::getInstance(res_mgr))
2430 ePtr<iDVBChannelList> db;
2431 if (!res_mgr->getChannelList(db))
2433 ePtr<eDVBService> origService;
2434 if (!db->getService(parent, origService))
2436 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2437 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2443 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2444 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2446 m_decoder->setVideoPID(vpid, vpidtype);
2447 selectAudioStream();
2449 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2450 m_decoder->setSyncPCR(pcrpid);
2452 m_decoder->setSyncPCR(-1);
2454 m_decoder->setTextPID(tpid);
2456 m_teletext_parser->start(program.textPid);
2459 m_decoder->setTrickmode(1);
2462 m_decoder->preroll();
2466 if (vpid > 0 && vpid < 0x2000)
2470 std::string radio_pic;
2471 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2472 m_decoder->setRadioPic(radio_pic);
2475 m_decoder->setAudioChannel(achannel);
2477 /* don't worry about non-existing services, nor pvr services */
2478 if (m_dvb_service && !m_is_pvr)
2480 /* (audio pid will be set in selectAudioTrack */
2481 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2482 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2483 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2484 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2487 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2490 void eDVBServicePlay::loadCuesheet()
2492 std::string filename = m_reference.path + ".cuts";
2494 m_cue_entries.clear();
2496 FILE *f = fopen(filename.c_str(), "rb");
2500 eDebug("loading cuts..");
2503 unsigned long long where;
2506 if (!fread(&where, sizeof(where), 1, f))
2508 if (!fread(&what, sizeof(what), 1, f))
2511 #if BYTE_ORDER == LITTLE_ENDIAN
2512 where = bswap_64(where);
2519 m_cue_entries.insert(cueEntry(where, what));
2522 eDebug("%d entries", m_cue_entries.size());
2524 eDebug("cutfile not found!");
2526 m_cuesheet_changed = 0;
2527 cutlistToCuesheet();
2528 m_event((iPlayableService*)this, evCuesheetChanged);
2531 void eDVBServicePlay::saveCuesheet()
2533 std::string filename = m_reference.path + ".cuts";
2535 FILE *f = fopen(filename.c_str(), "wb");
2539 unsigned long long where;
2542 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2544 #if BYTE_ORDER == BIG_ENDIAN
2547 where = bswap_64(i->where);
2549 what = htonl(i->what);
2550 fwrite(&where, sizeof(where), 1, f);
2551 fwrite(&what, sizeof(what), 1, f);
2557 m_cuesheet_changed = 0;
2560 void eDVBServicePlay::cutlistToCuesheet()
2564 eDebug("no cue sheet");
2569 if (!m_cutlist_enabled)
2571 m_cue->commitSpans();
2572 eDebug("cutlists were disabled");
2576 pts_t in = 0, out = 0, length = 0;
2580 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2584 if (i == m_cue_entries.end())
2587 if (i->what == 0) /* in */
2591 } else if (i->what == 1) /* out */
2593 else /* mark (2) or last play position (3) */
2610 m_cue->addSourceSpan(in, out);
2614 if (i == m_cue_entries.end())
2617 m_cue->commitSpans();
2620 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2622 if (m_subtitle_widget)
2623 disableSubtitles(parent);
2626 int tuplesize = PyTuple_Size(tuple);
2629 if (!PyTuple_Check(tuple))
2635 entry = PyTuple_GET_ITEM(tuple, 0);
2637 if (!PyInt_Check(entry))
2640 type = PyInt_AsLong(entry);
2642 if (type == 1) // teletext subtitles
2644 int page, magazine, pid;
2648 if (!m_teletext_parser)
2650 eDebug("enable teletext subtitles.. no parser !!!");
2654 entry = PyTuple_GET_ITEM(tuple, 1);
2655 if (!PyInt_Check(entry))
2657 pid = PyInt_AsLong(entry);
2659 entry = PyTuple_GET_ITEM(tuple, 2);
2660 if (!PyInt_Check(entry))
2662 page = PyInt_AsLong(entry);
2664 entry = PyTuple_GET_ITEM(tuple, 3);
2665 if (!PyInt_Check(entry))
2667 magazine = PyInt_AsLong(entry);
2669 m_subtitle_widget = new eSubtitleWidget(parent);
2670 m_subtitle_widget->resize(parent->size()); /* full size */
2671 m_teletext_parser->setPageAndMagazine(page, magazine);
2673 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2677 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2678 if (!m_subtitle_parser)
2680 eDebug("enable dvb subtitles.. no parser !!!");
2686 entry = PyTuple_GET_ITEM(tuple, 1);
2687 if (!PyInt_Check(entry))
2689 pid = PyInt_AsLong(entry);
2691 entry = PyTuple_GET_ITEM(tuple, 2);
2692 if (!PyInt_Check(entry))
2694 composition_page_id = PyInt_AsLong(entry);
2696 entry = PyTuple_GET_ITEM(tuple, 3);
2697 if (!PyInt_Check(entry))
2699 ancillary_page_id = PyInt_AsLong(entry);
2701 m_subtitle_widget = new eSubtitleWidget(parent);
2702 m_subtitle_widget->resize(parent->size()); /* full size */
2703 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2705 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2711 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2712 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2713 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2717 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2719 delete m_subtitle_widget;
2720 m_subtitle_widget = 0;
2721 if (m_subtitle_parser)
2723 m_subtitle_parser->stop();
2724 m_dvb_subtitle_pages.clear();
2726 if (m_teletext_parser)
2728 m_teletext_parser->setPageAndMagazine(-1, -1);
2729 m_subtitle_pages.clear();
2732 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2736 PyObject *eDVBServicePlay::getCachedSubtitle()
2740 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2743 unsigned int data = (unsigned int)tmp;
2744 int pid = (data&0xFFFF0000)>>16;
2745 ePyObject tuple = PyTuple_New(4);
2746 eDVBServicePMTHandler::program program;
2747 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2748 if (!h.getProgramInfo(program))
2750 if (program.textPid==pid) // teletext
2751 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2753 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2754 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2755 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2756 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2764 PyObject *eDVBServicePlay::getSubtitleList()
2766 if (!m_teletext_parser)
2769 ePyObject l = PyList_New(0);
2770 std::set<int> added_ttx_pages;
2772 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2773 m_teletext_parser->m_found_subtitle_pages;
2775 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2776 eDVBServicePMTHandler::program program;
2777 if (h.getProgramInfo(program))
2778 eDebug("getting program info failed.");
2781 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2782 it != program.subtitleStreams.end(); ++it)
2784 switch(it->subtitling_type)
2786 case 0x01: // ebu teletext subtitles
2788 int page_number = it->teletext_page_number & 0xFF;
2789 int magazine_number = it->teletext_magazine_number & 7;
2790 int hash = magazine_number << 8 | page_number;
2791 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2793 ePyObject tuple = PyTuple_New(5);
2794 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2795 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2796 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2797 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2798 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2799 PyList_Append(l, tuple);
2801 added_ttx_pages.insert(hash);
2806 case 0x20 ... 0x23: // dvb subtitles
2808 ePyObject tuple = PyTuple_New(5);
2809 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2810 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2811 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2812 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2813 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2814 PyList_Insert(l, 0, tuple);
2822 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2823 it != subs.end(); ++it)
2825 int page_number = it->teletext_page_number & 0xFF;
2826 int magazine_number = it->teletext_magazine_number & 7;
2827 int hash = magazine_number << 8 | page_number;
2828 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2830 ePyObject tuple = PyTuple_New(5);
2831 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2832 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2833 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2834 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2835 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2836 PyList_Append(l, tuple);
2844 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2846 if (m_subtitle_widget)
2850 m_decoder->getPTS(0, pos);
2851 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2852 m_subtitle_pages.push_back(page);
2853 checkSubtitleTiming();
2857 void eDVBServicePlay::checkSubtitleTiming()
2859 eDebug("checkSubtitleTiming");
2860 if (!m_subtitle_widget)
2864 enum { TELETEXT, DVB } type;
2865 eDVBTeletextSubtitlePage page;
2866 eDVBSubtitlePage dvb_page;
2868 if (!m_subtitle_pages.empty())
2870 page = m_subtitle_pages.front();
2872 show_time = page.m_pts;
2874 else if (!m_dvb_subtitle_pages.empty())
2876 dvb_page = m_dvb_subtitle_pages.front();
2878 show_time = dvb_page.m_show_time;
2886 m_decoder->getPTS(0, pos);
2888 eDebug("%lld %lld", pos, show_time);
2889 int diff = show_time - pos;
2892 eDebug("[late (%d ms)]", -diff / 90);
2895 // if (diff > 900000)
2897 // eDebug("[invalid]");
2903 if (type == TELETEXT)
2905 eDebug("display teletext subtitle page %lld", show_time);
2906 m_subtitle_widget->setPage(page);
2907 m_subtitle_pages.pop_front();
2911 eDebug("display dvb subtitle Page %lld", show_time);
2912 m_subtitle_widget->setPage(dvb_page);
2913 m_dvb_subtitle_pages.pop_front();
2917 eDebug("start subtitle delay %d", diff / 90);
2918 m_subtitle_sync_timer->start(diff / 90, 1);
2924 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2926 if (m_subtitle_widget)
2930 m_decoder->getPTS(0, pos);
2931 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2932 m_dvb_subtitle_pages.push_back(p);
2933 checkSubtitleTiming();
2937 int eDVBServicePlay::getAC3Delay()
2940 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2942 return m_decoder->getAC3Delay();
2947 int eDVBServicePlay::getPCMDelay()
2950 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2952 return m_decoder->getPCMDelay();
2957 void eDVBServicePlay::setAC3Delay(int delay)
2960 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2962 m_decoder->setAC3Delay(delay);
2965 void eDVBServicePlay::setPCMDelay(int delay)
2968 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2970 m_decoder->setPCMDelay(delay);
2973 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2975 switch(event.type) {
2976 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2977 m_event((iPlayableService*)this, evVideoSizeChanged);
2979 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2980 m_event((iPlayableService*)this, evVideoFramerateChanged);
2982 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2983 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2990 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2996 PyObject *eDVBServicePlay::getStreamingData()
2998 eDVBServicePMTHandler::program program;
2999 if (m_service_handler.getProgramInfo(program))
3004 ePyObject r = program.createPythonObject();
3005 ePtr<iDVBDemux> demux;
3006 if (!m_service_handler.getDataDemux(demux))
3009 if (!demux->getCADemuxID(demux_id))
3010 PutToDict(r, "demux", demux_id);
3017 DEFINE_REF(eDVBServicePlay)
3019 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3023 case iServiceInformation::sTransponderData:
3024 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3028 return iStaticServiceInformation::getInfoObject(ref, w);
3031 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");