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();
1655 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1656 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1657 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1658 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1659 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1660 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1661 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1662 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1663 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1664 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1665 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1666 case sProvider: if (!m_dvb_service) return -1; return -2;
1667 case sServiceref: return resIsString;
1668 case sDVBState: return m_tune_state;
1675 std::string eDVBServicePlay::getInfoString(int w)
1680 if (!m_dvb_service) return "";
1681 return m_dvb_service->m_provider_name;
1683 return m_reference.toString();
1687 return iServiceInformation::getInfoString(w);
1690 PyObject *eDVBServicePlay::getInfoObject(int w)
1695 return m_service_handler.getCaIds();
1696 case sTransponderData:
1697 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1701 return iServiceInformation::getInfoObject(w);
1704 int eDVBServicePlay::getNumberOfTracks()
1706 eDVBServicePMTHandler::program program;
1707 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1708 if (h.getProgramInfo(program))
1710 return program.audioStreams.size();
1713 int eDVBServicePlay::getCurrentTrack()
1715 eDVBServicePMTHandler::program program;
1716 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1717 if (h.getProgramInfo(program))
1720 int max = program.audioStreams.size();
1723 for (i = 0; i < max; ++i)
1724 if (program.audioStreams[i].pid == m_current_audio_pid)
1730 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1732 int ret = selectAudioStream(i);
1734 if (m_decoder->start())
1740 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1742 eDVBServicePMTHandler::program program;
1743 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1745 if (h.getProgramInfo(program))
1748 if (i >= program.audioStreams.size())
1751 info.m_pid = program.audioStreams[i].pid;
1753 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1754 info.m_description = "MPEG";
1755 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1756 info.m_description = "AC3";
1757 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1758 info.m_description = "AAC";
1759 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1760 info.m_description = "DTS";
1762 info.m_description = "???";
1764 if (program.audioStreams[i].component_tag != -1)
1766 ePtr<eServiceEvent> evt;
1767 if (!m_event_handler.getEvent(evt, 0))
1769 ePtr<eComponentData> data;
1770 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1771 info.m_language = data->getText();
1775 if (info.m_language.empty())
1776 info.m_language = program.audioStreams[i].language_code;
1781 int eDVBServicePlay::selectAudioStream(int i)
1783 eDVBServicePMTHandler::program program;
1784 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1786 if (h.getProgramInfo(program))
1789 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1797 stream = program.defaultAudioStream;
1799 int apid = -1, apidtype = -1;
1801 if (((unsigned int)stream) < program.audioStreams.size())
1803 apid = program.audioStreams[stream].pid;
1804 apidtype = program.audioStreams[stream].type;
1807 m_current_audio_pid = apid;
1809 if (m_decoder->setAudioPID(apid, apidtype))
1811 eDebug("set audio pid failed");
1815 /* 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 */
1816 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1819 ePtr<iDVBDemux> data_demux;
1820 if (!h.getDataDemux(data_demux))
1822 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1823 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1827 /* if we decided that we need one, update the pid */
1829 m_rds_decoder->start(apid);
1831 /* store new pid as default only when:
1832 a.) we have an entry in the service db for the current service,
1833 b.) we are not playing back something,
1834 c.) we are not selecting the default entry. (we wouldn't change
1835 anything in the best case, or destroy the default setting in
1836 case the real default is not yet available.)
1838 if (m_dvb_service && !m_is_pvr && ((i != -1)
1839 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1841 if (apidtype == eDVBAudio::aMPEG)
1843 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1844 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1848 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1849 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1853 h.resetCachedProgram();
1858 int eDVBServicePlay::getCurrentChannel()
1860 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1863 RESULT eDVBServicePlay::selectChannel(int i)
1865 if (i < LEFT || i > RIGHT || i == STEREO)
1868 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1870 m_decoder->setAudioChannel(i);
1874 std::string eDVBServicePlay::getText(int x)
1880 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1882 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1887 void eDVBServicePlay::rdsDecoderEvent(int what)
1891 case eDVBRdsDecoder::RadioTextChanged:
1892 m_event((iPlayableService*)this, evUpdatedRadioText);
1894 case eDVBRdsDecoder::RtpTextChanged:
1895 m_event((iPlayableService*)this, evUpdatedRtpText);
1897 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1898 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1900 case eDVBRdsDecoder::RecvRassSlidePic:
1901 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1906 void eDVBServicePlay::showRassSlidePicture()
1912 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1913 if (rass_slide_pic.length())
1914 m_decoder->showSinglePic(rass_slide_pic.c_str());
1916 eDebug("empty filename for rass slide picture received!!");
1919 eDebug("no MPEG Decoder to show iframes avail");
1922 eDebug("showRassSlidePicture called.. but not decoder");
1925 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1931 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1932 if (rass_interactive_pic.length())
1933 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1935 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1938 eDebug("no MPEG Decoder to show iframes avail");
1941 eDebug("showRassInteractivePic called.. but not decoder");
1944 ePyObject eDVBServicePlay::getRassInteractiveMask()
1947 return m_rds_decoder->getRassPictureMask();
1951 int eDVBServiceBase::getFrontendInfo(int w)
1953 eUsePtr<iDVBChannel> channel;
1954 if(m_service_handler.getChannel(channel))
1956 ePtr<iDVBFrontend> fe;
1957 if(channel->getFrontend(fe))
1959 return fe->readFrontendData(w);
1962 PyObject *eDVBServiceBase::getFrontendData()
1964 ePyObject ret = PyDict_New();
1967 eUsePtr<iDVBChannel> channel;
1968 if(!m_service_handler.getChannel(channel))
1970 ePtr<iDVBFrontend> fe;
1971 if(!channel->getFrontend(fe))
1972 fe->getFrontendData(ret);
1980 PyObject *eDVBServiceBase::getFrontendStatus()
1982 ePyObject ret = PyDict_New();
1985 eUsePtr<iDVBChannel> channel;
1986 if(!m_service_handler.getChannel(channel))
1988 ePtr<iDVBFrontend> fe;
1989 if(!channel->getFrontend(fe))
1990 fe->getFrontendStatus(ret);
1998 PyObject *eDVBServiceBase::getTransponderData(bool original)
2000 ePyObject ret = PyDict_New();
2003 eUsePtr<iDVBChannel> channel;
2004 if(!m_service_handler.getChannel(channel))
2006 ePtr<iDVBFrontend> fe;
2007 if(!channel->getFrontend(fe))
2009 fe->getTransponderData(ret, original);
2010 ePtr<iDVBFrontendParameters> feparm;
2011 channel->getCurrentFrontendParameters(feparm);
2014 eDVBFrontendParametersSatellite osat;
2015 if (!feparm->getDVBS(osat))
2017 PutToDict(ret, "orbital_position", osat.orbital_position);
2018 const char *tmp = "UNKNOWN";
2019 switch(osat.polarisation)
2021 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2022 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2023 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2024 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2027 PutToDict(ret, "polarization", tmp);
2038 PyObject *eDVBServiceBase::getAll(bool original)
2040 ePyObject ret = getTransponderData(original);
2043 eUsePtr<iDVBChannel> channel;
2044 if(!m_service_handler.getChannel(channel))
2046 ePtr<iDVBFrontend> fe;
2047 if(!channel->getFrontend(fe))
2049 fe->getFrontendData(ret);
2050 fe->getFrontendStatus(ret);
2057 int eDVBServicePlay::getNumberOfSubservices()
2059 ePtr<eServiceEvent> evt;
2060 if (!m_event_handler.getEvent(evt, 0))
2061 return evt->getNumOfLinkageServices();
2065 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2067 ePtr<eServiceEvent> evt;
2068 if (!m_event_handler.getEvent(evt, 0))
2070 if (!evt->getLinkageService(sub, m_reference, n))
2073 sub.type=eServiceReference::idInvalid;
2077 RESULT eDVBServicePlay::startTimeshift()
2079 ePtr<iDVBDemux> demux;
2081 eDebug("Start timeshift!");
2083 if (m_timeshift_enabled)
2086 /* start recording with the data demux. */
2087 if (m_service_handler.getDataDemux(demux))
2090 demux->createTSRecorder(m_record);
2095 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2096 eDebug("could not query ts path");
2099 tspath.append("/timeshift.XXXXXX");
2101 templ = new char[tspath.length() + 1];
2102 strcpy(templ, tspath.c_str());
2104 m_timeshift_fd = mkstemp(templ);
2105 m_timeshift_file = std::string(templ);
2107 eDebug("recording to %s", templ);
2111 if (m_timeshift_fd < 0)
2117 m_record->setTargetFD(m_timeshift_fd);
2119 m_timeshift_enabled = 1;
2121 updateTimeshiftPids();
2127 RESULT eDVBServicePlay::stopTimeshift()
2129 if (!m_timeshift_enabled)
2134 m_timeshift_enabled = 0;
2139 close(m_timeshift_fd);
2140 eDebug("remove timeshift file");
2141 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2146 int eDVBServicePlay::isTimeshiftActive()
2148 return m_timeshift_enabled && m_timeshift_active;
2151 RESULT eDVBServicePlay::activateTimeshift()
2153 if (!m_timeshift_enabled)
2156 if (!m_timeshift_active)
2158 switchToTimeshift();
2165 PyObject *eDVBServicePlay::getCutList()
2167 ePyObject list = PyList_New(0);
2169 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2171 ePyObject tuple = PyTuple_New(2);
2172 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2173 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2174 PyList_Append(list, tuple);
2181 void eDVBServicePlay::setCutList(ePyObject list)
2183 if (!PyList_Check(list))
2185 int size = PyList_Size(list);
2188 m_cue_entries.clear();
2190 for (i=0; i<size; ++i)
2192 ePyObject tuple = PyList_GET_ITEM(list, i);
2193 if (!PyTuple_Check(tuple))
2195 eDebug("non-tuple in cutlist");
2198 if (PyTuple_Size(tuple) != 2)
2200 eDebug("cutlist entries need to be a 2-tuple");
2203 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2204 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2206 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2209 pts_t pts = PyLong_AsLongLong(ppts);
2210 int type = PyInt_AsLong(ptype);
2211 m_cue_entries.insert(cueEntry(pts, type));
2212 eDebug("adding %08llx, %d", pts, type);
2214 m_cuesheet_changed = 1;
2216 cutlistToCuesheet();
2217 m_event((iPlayableService*)this, evCuesheetChanged);
2220 void eDVBServicePlay::setCutListEnable(int enable)
2222 m_cutlist_enabled = enable;
2223 cutlistToCuesheet();
2226 void eDVBServicePlay::updateTimeshiftPids()
2231 eDVBServicePMTHandler::program program;
2232 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2234 if (h.getProgramInfo(program))
2238 std::set<int> pids_to_record;
2239 pids_to_record.insert(0); // PAT
2240 if (program.pmtPid != -1)
2241 pids_to_record.insert(program.pmtPid); // PMT
2243 if (program.textPid != -1)
2244 pids_to_record.insert(program.textPid); // Videotext
2246 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2247 i(program.videoStreams.begin());
2248 i != program.videoStreams.end(); ++i)
2249 pids_to_record.insert(i->pid);
2251 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2252 i(program.audioStreams.begin());
2253 i != program.audioStreams.end(); ++i)
2254 pids_to_record.insert(i->pid);
2256 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2257 i(program.subtitleStreams.begin());
2258 i != program.subtitleStreams.end(); ++i)
2259 pids_to_record.insert(i->pid);
2261 std::set<int> new_pids, obsolete_pids;
2263 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2264 m_pids_active.begin(), m_pids_active.end(),
2265 std::inserter(new_pids, new_pids.begin()));
2267 std::set_difference(
2268 m_pids_active.begin(), m_pids_active.end(),
2269 pids_to_record.begin(), pids_to_record.end(),
2270 std::inserter(new_pids, new_pids.begin())
2273 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2274 m_record->addPID(*i);
2276 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2277 m_record->removePID(*i);
2281 void eDVBServicePlay::switchToLive()
2283 if (!m_timeshift_active)
2289 m_teletext_parser = 0;
2291 m_subtitle_parser = 0;
2292 m_new_dvb_subtitle_page_connection = 0;
2293 m_new_subtitle_page_connection = 0;
2294 m_rds_decoder_event_connection = 0;
2295 m_video_event_connection = 0;
2297 /* free the timeshift service handler, we need the resources */
2298 m_service_handler_timeshift.free();
2299 m_timeshift_active = 0;
2301 m_event((iPlayableService*)this, evSeekableStatusChanged);
2306 void eDVBServicePlay::switchToTimeshift()
2308 if (m_timeshift_active)
2313 m_teletext_parser = 0;
2315 m_subtitle_parser = 0;
2316 m_new_subtitle_page_connection = 0;
2317 m_new_dvb_subtitle_page_connection = 0;
2318 m_rds_decoder_event_connection = 0;
2319 m_video_event_connection = 0;
2321 m_timeshift_active = 1;
2323 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2324 r.path = m_timeshift_file;
2326 m_cue = new eCueSheet();
2327 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2329 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2331 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2333 m_event((iPlayableService*)this, evSeekableStatusChanged);
2336 void eDVBServicePlay::updateDecoder()
2338 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2340 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2342 eDVBServicePMTHandler::program program;
2343 if (h.getProgramInfo(program))
2344 eDebug("getting program info failed.");
2347 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2348 if (!program.videoStreams.empty())
2350 eDebugNoNewLine(" (");
2351 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2352 i(program.videoStreams.begin());
2353 i != program.videoStreams.end(); ++i)
2360 if (i != program.videoStreams.begin())
2361 eDebugNoNewLine(", ");
2362 eDebugNoNewLine("%04x", i->pid);
2364 eDebugNoNewLine(")");
2366 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2367 if (!program.audioStreams.empty())
2369 eDebugNoNewLine(" (");
2370 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2371 i(program.audioStreams.begin());
2372 i != program.audioStreams.end(); ++i)
2374 if (i != program.audioStreams.begin())
2375 eDebugNoNewLine(", ");
2376 eDebugNoNewLine("%04x", i->pid);
2378 eDebugNoNewLine(")");
2380 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2381 pcrpid = program.pcrPid;
2382 eDebug(", and the text pid is %04x", program.textPid);
2383 tpid = program.textPid;
2388 h.getDecodeDemux(m_decode_demux);
2391 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2393 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2394 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2395 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2396 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2397 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2400 m_teletext_parser = 0;
2401 m_subtitle_parser = 0;
2405 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2412 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2413 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2414 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2416 else // subservice or recording
2418 eServiceReferenceDVB ref;
2419 m_service_handler.getServiceReference(ref);
2420 eServiceReferenceDVB parent = ref.getParentServiceReference();
2425 ePtr<eDVBResourceManager> res_mgr;
2426 if (!eDVBResourceManager::getInstance(res_mgr))
2428 ePtr<iDVBChannelList> db;
2429 if (!res_mgr->getChannelList(db))
2431 ePtr<eDVBService> origService;
2432 if (!db->getService(parent, origService))
2434 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2435 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2441 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2442 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2444 m_decoder->setVideoPID(vpid, vpidtype);
2445 selectAudioStream();
2447 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2448 m_decoder->setSyncPCR(pcrpid);
2450 m_decoder->setSyncPCR(-1);
2452 m_decoder->setTextPID(tpid);
2454 m_teletext_parser->start(program.textPid);
2457 m_decoder->setTrickmode(1);
2460 m_decoder->preroll();
2464 if (vpid > 0 && vpid < 0x2000)
2468 std::string radio_pic;
2469 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2470 m_decoder->setRadioPic(radio_pic);
2473 m_decoder->setAudioChannel(achannel);
2475 /* don't worry about non-existing services, nor pvr services */
2476 if (m_dvb_service && !m_is_pvr)
2478 /* (audio pid will be set in selectAudioTrack */
2479 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2480 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2481 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2482 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2485 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2488 void eDVBServicePlay::loadCuesheet()
2490 std::string filename = m_reference.path + ".cuts";
2492 m_cue_entries.clear();
2494 FILE *f = fopen(filename.c_str(), "rb");
2498 eDebug("loading cuts..");
2501 unsigned long long where;
2504 if (!fread(&where, sizeof(where), 1, f))
2506 if (!fread(&what, sizeof(what), 1, f))
2509 #if BYTE_ORDER == LITTLE_ENDIAN
2510 where = bswap_64(where);
2517 m_cue_entries.insert(cueEntry(where, what));
2520 eDebug("%d entries", m_cue_entries.size());
2522 eDebug("cutfile not found!");
2524 m_cuesheet_changed = 0;
2525 cutlistToCuesheet();
2526 m_event((iPlayableService*)this, evCuesheetChanged);
2529 void eDVBServicePlay::saveCuesheet()
2531 std::string filename = m_reference.path + ".cuts";
2533 FILE *f = fopen(filename.c_str(), "wb");
2537 unsigned long long where;
2540 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2542 #if BYTE_ORDER == BIG_ENDIAN
2545 where = bswap_64(i->where);
2547 what = htonl(i->what);
2548 fwrite(&where, sizeof(where), 1, f);
2549 fwrite(&what, sizeof(what), 1, f);
2555 m_cuesheet_changed = 0;
2558 void eDVBServicePlay::cutlistToCuesheet()
2562 eDebug("no cue sheet");
2567 if (!m_cutlist_enabled)
2569 m_cue->commitSpans();
2570 eDebug("cutlists were disabled");
2574 pts_t in = 0, out = 0, length = 0;
2578 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2582 if (i == m_cue_entries.end())
2585 if (i->what == 0) /* in */
2589 } else if (i->what == 1) /* out */
2591 else /* mark (2) or last play position (3) */
2608 m_cue->addSourceSpan(in, out);
2612 if (i == m_cue_entries.end())
2615 m_cue->commitSpans();
2618 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2620 if (m_subtitle_widget)
2621 disableSubtitles(parent);
2624 int tuplesize = PyTuple_Size(tuple);
2627 if (!PyTuple_Check(tuple))
2633 entry = PyTuple_GET_ITEM(tuple, 0);
2635 if (!PyInt_Check(entry))
2638 type = PyInt_AsLong(entry);
2640 if (type == 1) // teletext subtitles
2642 int page, magazine, pid;
2646 if (!m_teletext_parser)
2648 eDebug("enable teletext subtitles.. no parser !!!");
2652 entry = PyTuple_GET_ITEM(tuple, 1);
2653 if (!PyInt_Check(entry))
2655 pid = PyInt_AsLong(entry);
2657 entry = PyTuple_GET_ITEM(tuple, 2);
2658 if (!PyInt_Check(entry))
2660 page = PyInt_AsLong(entry);
2662 entry = PyTuple_GET_ITEM(tuple, 3);
2663 if (!PyInt_Check(entry))
2665 magazine = PyInt_AsLong(entry);
2667 m_subtitle_widget = new eSubtitleWidget(parent);
2668 m_subtitle_widget->resize(parent->size()); /* full size */
2669 m_teletext_parser->setPageAndMagazine(page, magazine);
2671 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2675 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2676 if (!m_subtitle_parser)
2678 eDebug("enable dvb subtitles.. no parser !!!");
2684 entry = PyTuple_GET_ITEM(tuple, 1);
2685 if (!PyInt_Check(entry))
2687 pid = PyInt_AsLong(entry);
2689 entry = PyTuple_GET_ITEM(tuple, 2);
2690 if (!PyInt_Check(entry))
2692 composition_page_id = PyInt_AsLong(entry);
2694 entry = PyTuple_GET_ITEM(tuple, 3);
2695 if (!PyInt_Check(entry))
2697 ancillary_page_id = PyInt_AsLong(entry);
2699 m_subtitle_widget = new eSubtitleWidget(parent);
2700 m_subtitle_widget->resize(parent->size()); /* full size */
2701 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2703 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2709 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2710 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2711 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2715 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2717 delete m_subtitle_widget;
2718 m_subtitle_widget = 0;
2719 if (m_subtitle_parser)
2721 m_subtitle_parser->stop();
2722 m_dvb_subtitle_pages.clear();
2724 if (m_teletext_parser)
2726 m_teletext_parser->setPageAndMagazine(-1, -1);
2727 m_subtitle_pages.clear();
2730 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2734 PyObject *eDVBServicePlay::getCachedSubtitle()
2738 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2741 unsigned int data = (unsigned int)tmp;
2742 int pid = (data&0xFFFF0000)>>16;
2743 ePyObject tuple = PyTuple_New(4);
2744 eDVBServicePMTHandler::program program;
2745 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2746 if (!h.getProgramInfo(program))
2748 if (program.textPid==pid) // teletext
2749 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2751 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2752 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2753 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2754 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2762 PyObject *eDVBServicePlay::getSubtitleList()
2764 if (!m_teletext_parser)
2767 ePyObject l = PyList_New(0);
2768 std::set<int> added_ttx_pages;
2770 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2771 m_teletext_parser->m_found_subtitle_pages;
2773 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2774 eDVBServicePMTHandler::program program;
2775 if (h.getProgramInfo(program))
2776 eDebug("getting program info failed.");
2779 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2780 it != program.subtitleStreams.end(); ++it)
2782 switch(it->subtitling_type)
2784 case 0x01: // ebu teletext subtitles
2786 int page_number = it->teletext_page_number & 0xFF;
2787 int magazine_number = it->teletext_magazine_number & 7;
2788 int hash = magazine_number << 8 | page_number;
2789 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2791 ePyObject tuple = PyTuple_New(5);
2792 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2793 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2794 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2795 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2796 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2797 PyList_Append(l, tuple);
2799 added_ttx_pages.insert(hash);
2804 case 0x20 ... 0x23: // dvb subtitles
2806 ePyObject tuple = PyTuple_New(5);
2807 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2808 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2809 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2810 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2811 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2812 PyList_Insert(l, 0, tuple);
2820 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2821 it != subs.end(); ++it)
2823 int page_number = it->teletext_page_number & 0xFF;
2824 int magazine_number = it->teletext_magazine_number & 7;
2825 int hash = magazine_number << 8 | page_number;
2826 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2828 ePyObject tuple = PyTuple_New(5);
2829 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2830 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2831 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2832 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2833 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2834 PyList_Append(l, tuple);
2842 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2844 if (m_subtitle_widget)
2848 m_decoder->getPTS(0, pos);
2849 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2850 m_subtitle_pages.push_back(page);
2851 checkSubtitleTiming();
2855 void eDVBServicePlay::checkSubtitleTiming()
2857 eDebug("checkSubtitleTiming");
2858 if (!m_subtitle_widget)
2862 enum { TELETEXT, DVB } type;
2863 eDVBTeletextSubtitlePage page;
2864 eDVBSubtitlePage dvb_page;
2866 if (!m_subtitle_pages.empty())
2868 page = m_subtitle_pages.front();
2870 show_time = page.m_pts;
2872 else if (!m_dvb_subtitle_pages.empty())
2874 dvb_page = m_dvb_subtitle_pages.front();
2876 show_time = dvb_page.m_show_time;
2884 m_decoder->getPTS(0, pos);
2886 eDebug("%lld %lld", pos, show_time);
2887 int diff = show_time - pos;
2890 eDebug("[late (%d ms)]", -diff / 90);
2893 // if (diff > 900000)
2895 // eDebug("[invalid]");
2901 if (type == TELETEXT)
2903 eDebug("display teletext subtitle page %lld", show_time);
2904 m_subtitle_widget->setPage(page);
2905 m_subtitle_pages.pop_front();
2909 eDebug("display dvb subtitle Page %lld", show_time);
2910 m_subtitle_widget->setPage(dvb_page);
2911 m_dvb_subtitle_pages.pop_front();
2915 eDebug("start subtitle delay %d", diff / 90);
2916 m_subtitle_sync_timer->start(diff / 90, 1);
2922 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2924 if (m_subtitle_widget)
2928 m_decoder->getPTS(0, pos);
2929 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2930 m_dvb_subtitle_pages.push_back(p);
2931 checkSubtitleTiming();
2935 int eDVBServicePlay::getAC3Delay()
2938 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2940 return m_decoder->getAC3Delay();
2945 int eDVBServicePlay::getPCMDelay()
2948 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2950 return m_decoder->getPCMDelay();
2955 void eDVBServicePlay::setAC3Delay(int delay)
2958 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2960 m_decoder->setAC3Delay(delay);
2963 void eDVBServicePlay::setPCMDelay(int delay)
2966 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2968 m_decoder->setPCMDelay(delay);
2971 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2973 switch(event.type) {
2974 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2975 m_event((iPlayableService*)this, evVideoSizeChanged);
2977 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2978 m_event((iPlayableService*)this, evVideoFramerateChanged);
2980 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2981 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2988 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2994 PyObject *eDVBServicePlay::getStreamingData()
2996 eDVBServicePMTHandler::program program;
2997 if (m_service_handler.getProgramInfo(program))
3002 ePyObject r = program.createPythonObject();
3003 ePtr<iDVBDemux> demux;
3004 if (!m_service_handler.getDataDemux(demux))
3007 if (!demux->getCADemuxID(demux_id))
3008 PutToDict(r, "demux", demux_id);
3015 DEFINE_REF(eDVBServicePlay)
3017 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3021 case iServiceInformation::sTransponderData:
3022 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3026 return iStaticServiceInformation::getInfoObject(ref, w);
3029 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");