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)
1047 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
1049 m_is_pvr = !m_reference.path.empty();
1051 m_timeshift_enabled = m_timeshift_active = 0;
1054 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
1055 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
1056 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
1058 m_cuesheet_changed = 0;
1059 m_cutlist_enabled = 1;
1061 m_subtitle_widget = 0;
1065 m_subtitle_sync_timer = eTimer::create(eApp);
1067 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
1070 eDVBServicePlay::~eDVBServicePlay()
1072 delete m_subtitle_widget;
1075 void eDVBServicePlay::gotNewEvent()
1079 ePtr<eServiceEvent> m_event_now, m_event_next;
1080 getEvent(m_event_now, 0);
1081 getEvent(m_event_next, 1);
1084 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1086 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1088 m_event((iPlayableService*)this, evUpdatedEventInfo);
1091 void eDVBServicePlay::serviceEvent(int event)
1093 m_tune_state = event;
1097 case eDVBServicePMTHandler::eventTuned:
1099 ePtr<iDVBDemux> m_demux;
1100 if (!m_service_handler.getDataDemux(m_demux))
1102 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1103 int sid = ref.getParentServiceID().get();
1105 sid = ref.getServiceID().get();
1106 if ( ref.getParentTransportStreamID().get() &&
1107 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1108 m_event_handler.startOther(m_demux, sid);
1110 m_event_handler.start(m_demux, sid);
1112 m_event((iPlayableService*)this, evTunedIn);
1115 case eDVBServicePMTHandler::eventNoResources:
1116 case eDVBServicePMTHandler::eventNoPAT:
1117 case eDVBServicePMTHandler::eventNoPATEntry:
1118 case eDVBServicePMTHandler::eventNoPMT:
1119 case eDVBServicePMTHandler::eventTuneFailed:
1120 case eDVBServicePMTHandler::eventMisconfiguration:
1122 eDebug("DVB service failed to tune - error %d", event);
1123 m_event((iPlayableService*)this, evTuneFailed);
1126 case eDVBServicePMTHandler::eventNewProgramInfo:
1128 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1129 if (m_timeshift_enabled)
1130 updateTimeshiftPids();
1131 if (!m_timeshift_active)
1133 if (m_first_program_info && m_is_pvr)
1135 m_first_program_info = 0;
1138 m_event((iPlayableService*)this, evUpdatedInfo);
1141 case eDVBServicePMTHandler::eventEOF:
1142 m_event((iPlayableService*)this, evEOF);
1144 case eDVBServicePMTHandler::eventSOF:
1145 m_event((iPlayableService*)this, evSOF);
1150 void eDVBServicePlay::serviceEventTimeshift(int event)
1154 case eDVBServicePMTHandler::eventNewProgramInfo:
1155 if (m_timeshift_active)
1158 case eDVBServicePMTHandler::eventSOF:
1159 m_event((iPlayableService*)this, evSOF);
1161 case eDVBServicePMTHandler::eventEOF:
1162 if ((!m_is_paused) && (m_skipmode >= 0))
1168 RESULT eDVBServicePlay::start()
1171 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1172 two (one for decoding, one for data source), as we must be prepared
1173 to start recording from the data demux. */
1175 m_cue = new eCueSheet();
1177 m_event(this, evStart);
1179 m_first_program_info = 1;
1180 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1181 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1183 /* inject EIT if there is a stored one */
1186 std::string filename = service.path;
1187 filename.erase(filename.length()-2, 2);
1189 ePtr<eServiceEvent> event = new eServiceEvent;
1190 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1192 ePtr<eServiceEvent> empty;
1193 m_event_handler.inject(event, 0);
1194 m_event_handler.inject(empty, 1);
1201 m_event(this, evStart);
1206 RESULT eDVBServicePlay::stop()
1208 /* add bookmark for last play position */
1211 pts_t play_position, length;
1212 if (!getPlayPosition(play_position))
1214 /* remove last position */
1215 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1217 if (i->what == 3) /* current play position */
1219 m_cue_entries.erase(i);
1220 i = m_cue_entries.begin();
1226 if (getLength(length))
1231 int perc = play_position * 100LL / length;
1233 /* only store last play position when between 1% and 99% */
1234 if ((1 < perc) && (perc < 99))
1235 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1237 m_cuesheet_changed = 1;
1241 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1243 m_service_handler_timeshift.free();
1244 m_service_handler.free();
1246 if (m_is_pvr && m_cuesheet_changed)
1249 /* save cuesheet only when main file is accessible. */
1250 if (!::stat(m_reference.path.c_str(), &s))
1253 m_event((iPlayableService*)this, evStopped);
1257 RESULT eDVBServicePlay::setTarget(int target)
1259 m_is_primary = !target;
1263 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1265 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1269 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1271 /* note: we check for timeshift to be enabled,
1272 not neccessary active. if you pause when timeshift
1273 is not active, you should activate it when unpausing */
1274 if ((!m_is_pvr) && (!m_timeshift_enabled))
1284 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1287 return m_decoder->setSlowMotion(ratio);
1292 RESULT eDVBServicePlay::setFastForward(int ratio)
1294 int skipmode, ffratio;
1300 } else if (ratio > 0)
1308 } else // if (ratio < 0)
1314 if (m_skipmode != skipmode)
1316 eDebug("setting cue skipmode to %d", skipmode);
1318 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1321 m_skipmode = skipmode;
1326 return m_decoder->setFastForward(ffratio);
1329 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1331 if (m_is_pvr || m_timeshift_enabled)
1341 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1342 RESULT eDVBServicePlay::getLength(pts_t &len)
1344 ePtr<iDVBPVRChannel> pvr_channel;
1346 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1349 return pvr_channel->getLength(len);
1352 RESULT eDVBServicePlay::pause()
1354 if (!m_is_paused && m_decoder)
1357 return m_decoder->freeze(0);
1362 RESULT eDVBServicePlay::unpause()
1364 if (m_is_paused && m_decoder)
1367 return m_decoder->unfreeze();
1372 RESULT eDVBServicePlay::seekTo(pts_t to)
1374 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1376 if (!m_decode_demux)
1379 ePtr<iDVBPVRChannel> pvr_channel;
1381 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1387 m_cue->seekTo(0, to);
1388 m_dvb_subtitle_pages.clear();
1389 m_subtitle_pages.clear();
1394 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1396 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1398 if (!m_decode_demux)
1401 ePtr<iDVBPVRChannel> pvr_channel;
1403 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1408 /* HACK until we have skip-AP api */
1409 if ((to > 0) && (to < 100))
1417 m_cue->seekTo(mode, to);
1418 m_dvb_subtitle_pages.clear();
1419 m_subtitle_pages.clear();
1423 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1425 ePtr<iDVBPVRChannel> pvr_channel;
1427 if (!m_decode_demux)
1430 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1435 /* if there is a decoder, use audio or video PTS */
1438 r = m_decoder->getPTS(0, pos);
1444 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1447 RESULT eDVBServicePlay::setTrickmode(int trick)
1450 m_decoder->setTrickmode(trick);
1454 RESULT eDVBServicePlay::isCurrentlySeekable()
1456 return m_is_pvr || m_timeshift_active;
1459 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1465 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1471 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1477 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1483 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1489 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1492 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1493 (m_timeshift_enabled || !m_is_pvr))
1495 if (!m_timeshift_enabled)
1497 /* query config path */
1499 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1500 eDebug("could not query ts path from config");
1504 /* we need enough diskspace */
1506 if (statfs(tspath.c_str(), &fs) < 0)
1508 eDebug("statfs failed!");
1512 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1514 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1524 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1535 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1541 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1547 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1553 RESULT eDVBServicePlay::getName(std::string &name)
1557 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1558 return i->getName(m_reference, name);
1562 m_dvb_service->getName(m_reference, name);
1566 else if (!m_reference.name.empty())
1567 eStaticServiceDVBInformation().getName(m_reference, name);
1569 name = "DVB service";
1573 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1575 return m_event_handler.getEvent(evt, nownext);
1578 static int readMpegProc(char *str, int decoder)
1582 sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
1583 FILE *f = fopen(tmp, "r");
1586 fscanf(f, "%x", &val);
1592 int eDVBServicePlay::getInfo(int w)
1594 eDVBServicePMTHandler::program program;
1597 return resIsPyObject;
1599 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1601 int no_program_info = 0;
1603 if (h.getProgramInfo(program))
1604 no_program_info = 1;
1608 #if HAVE_DVB_API_VERSION >= 3
1610 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1611 return m_videoEventData.height;
1613 return readMpegProc("yres", !m_is_primary);
1615 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1616 return m_videoEventData.width;
1618 return readMpegProc("xres", !m_is_primary);
1620 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventFrameRateChanged)
1621 return m_videoEventData.framerate;
1623 return readMpegProc("framerate", !m_is_primary);
1625 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventProgressiveChanged)
1626 return m_videoEventData.progressive;
1627 return readMpegProc("progressive", !m_is_primary);
1629 #warning "FIXMEE implement sFrameRate, sProgressive, sVideoHeight, sVideoWidth for old DVB API"
1634 #if HAVE_DVB_API_VERSION >= 3
1635 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1636 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1637 else if ((val=readMpegProc("aspect", !m_is_primary)) != -1)
1641 #warning "FIXMEE implement sAspect for old DVB API"
1643 if (no_program_info)
1645 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1647 ePtr<eServiceEvent> evt;
1648 if (!m_event_handler.getEvent(evt, 0))
1650 ePtr<eComponentData> data;
1651 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1653 if ( data->getStreamContent() == 1 )
1655 switch(data->getComponentType())
1658 case 1: // 4:3 SD PAL
1660 case 3: // 16:9 SD PAL
1661 case 4: // > 16:9 PAL
1662 case 5: // 4:3 SD NTSC
1664 case 7: // 16:9 SD NTSC
1665 case 8: // > 16:9 NTSC
1668 case 9: // 4:3 HD PAL
1670 case 0xB: // 16:9 HD PAL
1671 case 0xC: // > 16:9 HD PAL
1672 case 0xD: // 4:3 HD NTSC
1674 case 0xF: // 16:9 HD NTSC
1675 case 0x10: // > 16:9 HD PAL
1676 return data->getComponentType();
1684 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1685 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1686 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1687 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1688 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1689 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1690 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1691 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1692 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1693 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1694 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1695 case sProvider: if (!m_dvb_service) return -1; return -2;
1696 case sServiceref: return resIsString;
1697 case sDVBState: return m_tune_state;
1703 std::string eDVBServicePlay::getInfoString(int w)
1708 if (!m_dvb_service) return "";
1709 return m_dvb_service->m_provider_name;
1711 return m_reference.toString();
1715 return iServiceInformation::getInfoString(w);
1718 PyObject *eDVBServicePlay::getInfoObject(int w)
1723 return m_service_handler.getCaIds();
1724 case sTransponderData:
1725 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1729 return iServiceInformation::getInfoObject(w);
1732 int eDVBServicePlay::getNumberOfTracks()
1734 eDVBServicePMTHandler::program program;
1735 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1736 if (h.getProgramInfo(program))
1738 return program.audioStreams.size();
1741 int eDVBServicePlay::getCurrentTrack()
1743 eDVBServicePMTHandler::program program;
1744 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1745 if (h.getProgramInfo(program))
1748 int max = program.audioStreams.size();
1751 for (i = 0; i < max; ++i)
1752 if (program.audioStreams[i].pid == m_current_audio_pid)
1758 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1760 int ret = selectAudioStream(i);
1762 if (m_decoder->start())
1768 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1770 eDVBServicePMTHandler::program program;
1771 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1773 if (h.getProgramInfo(program))
1776 if (i >= program.audioStreams.size())
1779 info.m_pid = program.audioStreams[i].pid;
1781 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1782 info.m_description = "MPEG";
1783 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1784 info.m_description = "AC3";
1785 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1786 info.m_description = "AAC";
1787 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1788 info.m_description = "DTS";
1790 info.m_description = "???";
1792 if (program.audioStreams[i].component_tag != -1)
1794 ePtr<eServiceEvent> evt;
1795 if (!m_event_handler.getEvent(evt, 0))
1797 ePtr<eComponentData> data;
1798 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1799 info.m_language = data->getText();
1803 if (info.m_language.empty())
1804 info.m_language = program.audioStreams[i].language_code;
1809 int eDVBServicePlay::selectAudioStream(int i)
1811 eDVBServicePMTHandler::program program;
1812 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1814 if (h.getProgramInfo(program))
1817 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1825 stream = program.defaultAudioStream;
1827 int apid = -1, apidtype = -1;
1829 if (((unsigned int)stream) < program.audioStreams.size())
1831 apid = program.audioStreams[stream].pid;
1832 apidtype = program.audioStreams[stream].type;
1835 m_current_audio_pid = apid;
1837 if (m_decoder->setAudioPID(apid, apidtype))
1839 eDebug("set audio pid failed");
1843 /* 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 */
1844 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1847 ePtr<iDVBDemux> data_demux;
1848 if (!h.getDataDemux(data_demux))
1850 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1851 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1855 /* if we decided that we need one, update the pid */
1857 m_rds_decoder->start(apid);
1859 /* store new pid as default only when:
1860 a.) we have an entry in the service db for the current service,
1861 b.) we are not playing back something,
1862 c.) we are not selecting the default entry. (we wouldn't change
1863 anything in the best case, or destroy the default setting in
1864 case the real default is not yet available.)
1866 if (m_dvb_service && !m_is_pvr && ((i != -1)
1867 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1869 if (apidtype == eDVBAudio::aMPEG)
1871 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1872 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1876 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1877 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1881 h.resetCachedProgram();
1886 int eDVBServicePlay::getCurrentChannel()
1888 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1891 RESULT eDVBServicePlay::selectChannel(int i)
1893 if (i < LEFT || i > RIGHT || i == STEREO)
1896 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1898 m_decoder->setAudioChannel(i);
1902 std::string eDVBServicePlay::getText(int x)
1908 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1910 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1915 void eDVBServicePlay::rdsDecoderEvent(int what)
1919 case eDVBRdsDecoder::RadioTextChanged:
1920 m_event((iPlayableService*)this, evUpdatedRadioText);
1922 case eDVBRdsDecoder::RtpTextChanged:
1923 m_event((iPlayableService*)this, evUpdatedRtpText);
1925 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1926 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1928 case eDVBRdsDecoder::RecvRassSlidePic:
1929 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1934 void eDVBServicePlay::showRassSlidePicture()
1940 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1941 if (rass_slide_pic.length())
1942 m_decoder->showSinglePic(rass_slide_pic.c_str());
1944 eDebug("empty filename for rass slide picture received!!");
1947 eDebug("no MPEG Decoder to show iframes avail");
1950 eDebug("showRassSlidePicture called.. but not decoder");
1953 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1959 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1960 if (rass_interactive_pic.length())
1961 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1963 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1966 eDebug("no MPEG Decoder to show iframes avail");
1969 eDebug("showRassInteractivePic called.. but not decoder");
1972 ePyObject eDVBServicePlay::getRassInteractiveMask()
1975 return m_rds_decoder->getRassPictureMask();
1979 int eDVBServiceBase::getFrontendInfo(int w)
1981 eUsePtr<iDVBChannel> channel;
1982 if(m_service_handler.getChannel(channel))
1984 ePtr<iDVBFrontend> fe;
1985 if(channel->getFrontend(fe))
1987 return fe->readFrontendData(w);
1990 PyObject *eDVBServiceBase::getFrontendData()
1992 ePyObject ret = PyDict_New();
1995 eUsePtr<iDVBChannel> channel;
1996 if(!m_service_handler.getChannel(channel))
1998 ePtr<iDVBFrontend> fe;
1999 if(!channel->getFrontend(fe))
2000 fe->getFrontendData(ret);
2008 PyObject *eDVBServiceBase::getFrontendStatus()
2010 ePyObject ret = PyDict_New();
2013 eUsePtr<iDVBChannel> channel;
2014 if(!m_service_handler.getChannel(channel))
2016 ePtr<iDVBFrontend> fe;
2017 if(!channel->getFrontend(fe))
2018 fe->getFrontendStatus(ret);
2026 PyObject *eDVBServiceBase::getTransponderData(bool original)
2028 ePyObject ret = PyDict_New();
2031 eUsePtr<iDVBChannel> channel;
2032 if(!m_service_handler.getChannel(channel))
2034 ePtr<iDVBFrontend> fe;
2035 if(!channel->getFrontend(fe))
2037 fe->getTransponderData(ret, original);
2038 ePtr<iDVBFrontendParameters> feparm;
2039 channel->getCurrentFrontendParameters(feparm);
2042 eDVBFrontendParametersSatellite osat;
2043 if (!feparm->getDVBS(osat))
2045 PutToDict(ret, "orbital_position", osat.orbital_position);
2046 const char *tmp = "UNKNOWN";
2047 switch(osat.polarisation)
2049 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2050 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2051 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2052 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2055 PutToDict(ret, "polarization", tmp);
2066 PyObject *eDVBServiceBase::getAll(bool original)
2068 ePyObject ret = getTransponderData(original);
2071 eUsePtr<iDVBChannel> channel;
2072 if(!m_service_handler.getChannel(channel))
2074 ePtr<iDVBFrontend> fe;
2075 if(!channel->getFrontend(fe))
2077 fe->getFrontendData(ret);
2078 fe->getFrontendStatus(ret);
2085 int eDVBServicePlay::getNumberOfSubservices()
2087 ePtr<eServiceEvent> evt;
2088 if (!m_event_handler.getEvent(evt, 0))
2089 return evt->getNumOfLinkageServices();
2093 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2095 ePtr<eServiceEvent> evt;
2096 if (!m_event_handler.getEvent(evt, 0))
2098 if (!evt->getLinkageService(sub, m_reference, n))
2101 sub.type=eServiceReference::idInvalid;
2105 RESULT eDVBServicePlay::startTimeshift()
2107 ePtr<iDVBDemux> demux;
2109 eDebug("Start timeshift!");
2111 if (m_timeshift_enabled)
2114 /* start recording with the data demux. */
2115 if (m_service_handler.getDataDemux(demux))
2118 demux->createTSRecorder(m_record);
2123 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2124 eDebug("could not query ts path");
2127 tspath.append("/timeshift.XXXXXX");
2129 templ = new char[tspath.length() + 1];
2130 strcpy(templ, tspath.c_str());
2132 m_timeshift_fd = mkstemp(templ);
2133 m_timeshift_file = std::string(templ);
2135 eDebug("recording to %s", templ);
2139 if (m_timeshift_fd < 0)
2145 m_record->setTargetFD(m_timeshift_fd);
2147 m_timeshift_enabled = 1;
2149 updateTimeshiftPids();
2155 RESULT eDVBServicePlay::stopTimeshift()
2157 if (!m_timeshift_enabled)
2162 m_timeshift_enabled = 0;
2167 close(m_timeshift_fd);
2168 eDebug("remove timeshift file");
2169 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2174 int eDVBServicePlay::isTimeshiftActive()
2176 return m_timeshift_enabled && m_timeshift_active;
2179 RESULT eDVBServicePlay::activateTimeshift()
2181 if (!m_timeshift_enabled)
2184 if (!m_timeshift_active)
2186 switchToTimeshift();
2193 PyObject *eDVBServicePlay::getCutList()
2195 ePyObject list = PyList_New(0);
2197 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2199 ePyObject tuple = PyTuple_New(2);
2200 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2201 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2202 PyList_Append(list, tuple);
2209 void eDVBServicePlay::setCutList(ePyObject list)
2211 if (!PyList_Check(list))
2213 int size = PyList_Size(list);
2216 m_cue_entries.clear();
2218 for (i=0; i<size; ++i)
2220 ePyObject tuple = PyList_GET_ITEM(list, i);
2221 if (!PyTuple_Check(tuple))
2223 eDebug("non-tuple in cutlist");
2226 if (PyTuple_Size(tuple) != 2)
2228 eDebug("cutlist entries need to be a 2-tuple");
2231 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2232 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2234 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2237 pts_t pts = PyLong_AsLongLong(ppts);
2238 int type = PyInt_AsLong(ptype);
2239 m_cue_entries.insert(cueEntry(pts, type));
2240 eDebug("adding %08llx, %d", pts, type);
2242 m_cuesheet_changed = 1;
2244 cutlistToCuesheet();
2245 m_event((iPlayableService*)this, evCuesheetChanged);
2248 void eDVBServicePlay::setCutListEnable(int enable)
2250 m_cutlist_enabled = enable;
2251 cutlistToCuesheet();
2254 void eDVBServicePlay::updateTimeshiftPids()
2259 eDVBServicePMTHandler::program program;
2260 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2262 if (h.getProgramInfo(program))
2266 std::set<int> pids_to_record;
2267 pids_to_record.insert(0); // PAT
2268 if (program.pmtPid != -1)
2269 pids_to_record.insert(program.pmtPid); // PMT
2271 if (program.textPid != -1)
2272 pids_to_record.insert(program.textPid); // Videotext
2274 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2275 i(program.videoStreams.begin());
2276 i != program.videoStreams.end(); ++i)
2277 pids_to_record.insert(i->pid);
2279 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2280 i(program.audioStreams.begin());
2281 i != program.audioStreams.end(); ++i)
2282 pids_to_record.insert(i->pid);
2284 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2285 i(program.subtitleStreams.begin());
2286 i != program.subtitleStreams.end(); ++i)
2287 pids_to_record.insert(i->pid);
2289 std::set<int> new_pids, obsolete_pids;
2291 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2292 m_pids_active.begin(), m_pids_active.end(),
2293 std::inserter(new_pids, new_pids.begin()));
2295 std::set_difference(
2296 m_pids_active.begin(), m_pids_active.end(),
2297 pids_to_record.begin(), pids_to_record.end(),
2298 std::inserter(new_pids, new_pids.begin())
2301 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2302 m_record->addPID(*i);
2304 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2305 m_record->removePID(*i);
2309 void eDVBServicePlay::switchToLive()
2311 if (!m_timeshift_active)
2317 m_teletext_parser = 0;
2319 m_subtitle_parser = 0;
2320 m_new_dvb_subtitle_page_connection = 0;
2321 m_new_subtitle_page_connection = 0;
2322 m_rds_decoder_event_connection = 0;
2323 m_video_event_connection = 0;
2325 /* free the timeshift service handler, we need the resources */
2326 m_service_handler_timeshift.free();
2327 m_timeshift_active = 0;
2329 m_event((iPlayableService*)this, evSeekableStatusChanged);
2334 void eDVBServicePlay::switchToTimeshift()
2336 if (m_timeshift_active)
2341 m_teletext_parser = 0;
2343 m_subtitle_parser = 0;
2344 m_new_subtitle_page_connection = 0;
2345 m_new_dvb_subtitle_page_connection = 0;
2346 m_rds_decoder_event_connection = 0;
2347 m_video_event_connection = 0;
2349 m_timeshift_active = 1;
2351 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2352 r.path = m_timeshift_file;
2354 m_cue = new eCueSheet();
2355 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2357 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2359 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2361 m_event((iPlayableService*)this, evSeekableStatusChanged);
2364 void eDVBServicePlay::updateDecoder()
2366 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2368 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2370 eDVBServicePMTHandler::program program;
2371 if (h.getProgramInfo(program))
2372 eDebug("getting program info failed.");
2375 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2376 if (!program.videoStreams.empty())
2378 eDebugNoNewLine(" (");
2379 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2380 i(program.videoStreams.begin());
2381 i != program.videoStreams.end(); ++i)
2388 if (i != program.videoStreams.begin())
2389 eDebugNoNewLine(", ");
2390 eDebugNoNewLine("%04x", i->pid);
2392 eDebugNoNewLine(")");
2394 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2395 if (!program.audioStreams.empty())
2397 eDebugNoNewLine(" (");
2398 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2399 i(program.audioStreams.begin());
2400 i != program.audioStreams.end(); ++i)
2402 if (i != program.audioStreams.begin())
2403 eDebugNoNewLine(", ");
2404 eDebugNoNewLine("%04x", i->pid);
2406 eDebugNoNewLine(")");
2408 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2409 pcrpid = program.pcrPid;
2410 eDebug(", and the text pid is %04x", program.textPid);
2411 tpid = program.textPid;
2416 h.getDecodeDemux(m_decode_demux);
2419 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2421 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2422 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2423 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2424 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2425 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2428 m_teletext_parser = 0;
2429 m_subtitle_parser = 0;
2433 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2440 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2441 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2442 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2444 else // subservice or recording
2446 eServiceReferenceDVB ref;
2447 m_service_handler.getServiceReference(ref);
2448 eServiceReferenceDVB parent = ref.getParentServiceReference();
2453 ePtr<eDVBResourceManager> res_mgr;
2454 if (!eDVBResourceManager::getInstance(res_mgr))
2456 ePtr<iDVBChannelList> db;
2457 if (!res_mgr->getChannelList(db))
2459 ePtr<eDVBService> origService;
2460 if (!db->getService(parent, origService))
2462 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2463 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2469 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2470 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2472 m_decoder->setVideoPID(vpid, vpidtype);
2473 selectAudioStream();
2475 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2476 m_decoder->setSyncPCR(pcrpid);
2478 m_decoder->setSyncPCR(-1);
2480 m_decoder->setTextPID(tpid);
2482 m_teletext_parser->start(program.textPid);
2485 m_decoder->setTrickmode(1);
2488 m_decoder->preroll();
2492 if (vpid > 0 && vpid < 0x2000)
2496 std::string radio_pic;
2497 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2498 m_decoder->setRadioPic(radio_pic);
2501 m_decoder->setAudioChannel(achannel);
2503 /* don't worry about non-existing services, nor pvr services */
2504 if (m_dvb_service && !m_is_pvr)
2506 /* (audio pid will be set in selectAudioTrack */
2507 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2508 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2509 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2510 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2513 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2516 void eDVBServicePlay::loadCuesheet()
2518 std::string filename = m_reference.path + ".cuts";
2520 m_cue_entries.clear();
2522 FILE *f = fopen(filename.c_str(), "rb");
2526 eDebug("loading cuts..");
2529 unsigned long long where;
2532 if (!fread(&where, sizeof(where), 1, f))
2534 if (!fread(&what, sizeof(what), 1, f))
2537 #if BYTE_ORDER == LITTLE_ENDIAN
2538 where = bswap_64(where);
2545 m_cue_entries.insert(cueEntry(where, what));
2548 eDebug("%d entries", m_cue_entries.size());
2550 eDebug("cutfile not found!");
2552 m_cuesheet_changed = 0;
2553 cutlistToCuesheet();
2554 m_event((iPlayableService*)this, evCuesheetChanged);
2557 void eDVBServicePlay::saveCuesheet()
2559 std::string filename = m_reference.path + ".cuts";
2561 FILE *f = fopen(filename.c_str(), "wb");
2565 unsigned long long where;
2568 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2570 #if BYTE_ORDER == BIG_ENDIAN
2573 where = bswap_64(i->where);
2575 what = htonl(i->what);
2576 fwrite(&where, sizeof(where), 1, f);
2577 fwrite(&what, sizeof(what), 1, f);
2583 m_cuesheet_changed = 0;
2586 void eDVBServicePlay::cutlistToCuesheet()
2590 eDebug("no cue sheet");
2595 if (!m_cutlist_enabled)
2597 m_cue->commitSpans();
2598 eDebug("cutlists were disabled");
2602 pts_t in = 0, out = 0, length = 0;
2606 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2610 if (i == m_cue_entries.end())
2613 if (i->what == 0) /* in */
2617 } else if (i->what == 1) /* out */
2619 else /* mark (2) or last play position (3) */
2636 m_cue->addSourceSpan(in, out);
2640 if (i == m_cue_entries.end())
2643 m_cue->commitSpans();
2646 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2648 if (m_subtitle_widget)
2649 disableSubtitles(parent);
2652 int tuplesize = PyTuple_Size(tuple);
2655 if (!PyTuple_Check(tuple))
2661 entry = PyTuple_GET_ITEM(tuple, 0);
2663 if (!PyInt_Check(entry))
2666 type = PyInt_AsLong(entry);
2668 if (type == 1) // teletext subtitles
2670 int page, magazine, pid;
2674 if (!m_teletext_parser)
2676 eDebug("enable teletext subtitles.. no parser !!!");
2680 entry = PyTuple_GET_ITEM(tuple, 1);
2681 if (!PyInt_Check(entry))
2683 pid = PyInt_AsLong(entry);
2685 entry = PyTuple_GET_ITEM(tuple, 2);
2686 if (!PyInt_Check(entry))
2688 page = PyInt_AsLong(entry);
2690 entry = PyTuple_GET_ITEM(tuple, 3);
2691 if (!PyInt_Check(entry))
2693 magazine = PyInt_AsLong(entry);
2695 m_subtitle_widget = new eSubtitleWidget(parent);
2696 m_subtitle_widget->resize(parent->size()); /* full size */
2697 m_teletext_parser->setPageAndMagazine(page, magazine);
2699 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2703 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2704 if (!m_subtitle_parser)
2706 eDebug("enable dvb subtitles.. no parser !!!");
2712 entry = PyTuple_GET_ITEM(tuple, 1);
2713 if (!PyInt_Check(entry))
2715 pid = PyInt_AsLong(entry);
2717 entry = PyTuple_GET_ITEM(tuple, 2);
2718 if (!PyInt_Check(entry))
2720 composition_page_id = PyInt_AsLong(entry);
2722 entry = PyTuple_GET_ITEM(tuple, 3);
2723 if (!PyInt_Check(entry))
2725 ancillary_page_id = PyInt_AsLong(entry);
2727 m_subtitle_widget = new eSubtitleWidget(parent);
2728 m_subtitle_widget->resize(parent->size()); /* full size */
2729 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2731 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2737 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2738 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2739 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2743 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2745 delete m_subtitle_widget;
2746 m_subtitle_widget = 0;
2747 if (m_subtitle_parser)
2749 m_subtitle_parser->stop();
2750 m_dvb_subtitle_pages.clear();
2752 if (m_teletext_parser)
2754 m_teletext_parser->setPageAndMagazine(-1, -1);
2755 m_subtitle_pages.clear();
2758 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2762 PyObject *eDVBServicePlay::getCachedSubtitle()
2766 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2769 unsigned int data = (unsigned int)tmp;
2770 int pid = (data&0xFFFF0000)>>16;
2771 ePyObject tuple = PyTuple_New(4);
2772 eDVBServicePMTHandler::program program;
2773 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2774 if (!h.getProgramInfo(program))
2776 if (program.textPid==pid) // teletext
2777 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2779 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2780 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2781 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2782 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2790 PyObject *eDVBServicePlay::getSubtitleList()
2792 if (!m_teletext_parser)
2795 ePyObject l = PyList_New(0);
2796 std::set<int> added_ttx_pages;
2798 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2799 m_teletext_parser->m_found_subtitle_pages;
2801 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2802 eDVBServicePMTHandler::program program;
2803 if (h.getProgramInfo(program))
2804 eDebug("getting program info failed.");
2807 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2808 it != program.subtitleStreams.end(); ++it)
2810 switch(it->subtitling_type)
2812 case 0x01: // ebu teletext subtitles
2814 int page_number = it->teletext_page_number & 0xFF;
2815 int magazine_number = it->teletext_magazine_number & 7;
2816 int hash = magazine_number << 8 | page_number;
2817 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2819 ePyObject tuple = PyTuple_New(5);
2820 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2821 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2822 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2823 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2824 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2825 PyList_Append(l, tuple);
2827 added_ttx_pages.insert(hash);
2832 case 0x20 ... 0x23: // dvb subtitles
2834 ePyObject tuple = PyTuple_New(5);
2835 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2836 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2837 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2838 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2839 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2840 PyList_Insert(l, 0, tuple);
2848 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2849 it != subs.end(); ++it)
2851 int page_number = it->teletext_page_number & 0xFF;
2852 int magazine_number = it->teletext_magazine_number & 7;
2853 int hash = magazine_number << 8 | page_number;
2854 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2856 ePyObject tuple = PyTuple_New(5);
2857 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2858 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2859 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2860 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2861 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2862 PyList_Append(l, tuple);
2870 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2872 if (m_subtitle_widget)
2876 m_decoder->getPTS(0, pos);
2877 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2878 m_subtitle_pages.push_back(page);
2879 checkSubtitleTiming();
2883 void eDVBServicePlay::checkSubtitleTiming()
2885 eDebug("checkSubtitleTiming");
2886 if (!m_subtitle_widget)
2890 enum { TELETEXT, DVB } type;
2891 eDVBTeletextSubtitlePage page;
2892 eDVBSubtitlePage dvb_page;
2894 if (!m_subtitle_pages.empty())
2896 page = m_subtitle_pages.front();
2898 show_time = page.m_pts;
2900 else if (!m_dvb_subtitle_pages.empty())
2902 dvb_page = m_dvb_subtitle_pages.front();
2904 show_time = dvb_page.m_show_time;
2912 m_decoder->getPTS(0, pos);
2914 eDebug("%lld %lld", pos, show_time);
2915 int diff = show_time - pos;
2918 eDebug("[late (%d ms)]", -diff / 90);
2921 // if (diff > 900000)
2923 // eDebug("[invalid]");
2929 if (type == TELETEXT)
2931 eDebug("display teletext subtitle page %lld", show_time);
2932 m_subtitle_widget->setPage(page);
2933 m_subtitle_pages.pop_front();
2937 eDebug("display dvb subtitle Page %lld", show_time);
2938 m_subtitle_widget->setPage(dvb_page);
2939 m_dvb_subtitle_pages.pop_front();
2943 eDebug("start subtitle delay %d", diff / 90);
2944 m_subtitle_sync_timer->start(diff / 90, 1);
2950 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2952 if (m_subtitle_widget)
2956 m_decoder->getPTS(0, pos);
2957 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2958 m_dvb_subtitle_pages.push_back(p);
2959 checkSubtitleTiming();
2963 int eDVBServicePlay::getAC3Delay()
2966 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2968 return m_decoder->getAC3Delay();
2973 int eDVBServicePlay::getPCMDelay()
2976 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2978 return m_decoder->getPCMDelay();
2983 void eDVBServicePlay::setAC3Delay(int delay)
2986 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2988 m_decoder->setAC3Delay(delay);
2991 void eDVBServicePlay::setPCMDelay(int delay)
2994 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2996 m_decoder->setPCMDelay(delay);
2999 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3001 memcpy(&m_videoEventData, &event, sizeof(event));
3002 switch(event.type) {
3003 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3004 m_event((iPlayableService*)this, evVideoSizeChanged);
3006 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3007 m_event((iPlayableService*)this, evVideoFramerateChanged);
3009 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3010 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3017 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3023 PyObject *eDVBServicePlay::getStreamingData()
3025 eDVBServicePMTHandler::program program;
3026 if (m_service_handler.getProgramInfo(program))
3031 ePyObject r = program.createPythonObject();
3032 ePtr<iDVBDemux> demux;
3033 if (!m_service_handler.getDataDemux(demux))
3036 if (!demux->getCADemuxID(demux_id))
3037 PutToDict(r, "demux", demux_id);
3044 DEFINE_REF(eDVBServicePlay)
3046 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3050 case iServiceInformation::sTransponderData:
3051 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3055 return iStaticServiceInformation::getInfoObject(ref, w);
3058 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");