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);
540 stat(ref.path.c_str(), &s);
542 if (tstools.openFile(ref.path.c_str()))
545 /* check if cached data is still valid */
546 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
547 return m_parser.m_length / 90000;
549 /* otherwise, re-calc length and update meta file */
551 if (tstools.calcLen(len))
554 m_parser.m_length = len;
555 m_parser.m_filesize = s.st_size;
556 m_parser.updateMeta(ref.path);
557 return m_parser.m_length / 90000;
560 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
564 case iServiceInformation::sDescription:
565 return iServiceInformation::resIsString;
566 case iServiceInformation::sServiceref:
567 return iServiceInformation::resIsString;
568 case iServiceInformation::sTimeCreate:
569 if (m_parser.m_time_create)
570 return m_parser.m_time_create;
572 return iServiceInformation::resNA;
574 return iServiceInformation::resNA;
578 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
582 case iServiceInformation::sDescription:
583 return m_parser.m_description;
584 case iServiceInformation::sServiceref:
585 return m_parser.m_ref.toString();
586 case iServiceInformation::sTags:
587 return m_parser.m_tags;
593 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
595 if (!ref.path.empty())
597 ePtr<eServiceEvent> event = new eServiceEvent;
598 std::string filename = ref.path;
599 filename.erase(filename.length()-2, 2);
601 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
611 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
613 DECLARE_REF(eDVBPVRServiceOfflineOperations);
614 eServiceReferenceDVB m_ref;
616 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
618 RESULT deleteFromDisk(int simulate);
619 RESULT getListOfFilenames(std::list<std::string> &);
622 DEFINE_REF(eDVBPVRServiceOfflineOperations);
624 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
628 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
634 std::list<std::string> res;
635 if (getListOfFilenames(res))
638 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
640 eDebug("FATAL !! can't get background file eraser");
642 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
644 eDebug("Removing %s...", i->c_str());
646 eraser->erase(i->c_str());
648 ::unlink(i->c_str());
655 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
658 res.push_back(m_ref.path);
660 // handling for old splitted recordings (enigma 1)
665 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
667 if (stat(buf, &s) < 0)
672 res.push_back(m_ref.path + ".meta");
673 res.push_back(m_ref.path + ".ap");
674 res.push_back(m_ref.path + ".cuts");
675 std::string tmp = m_ref.path;
676 tmp.erase(m_ref.path.length()-3);
677 res.push_back(tmp + ".eit");
681 DEFINE_REF(eServiceFactoryDVB)
683 eServiceFactoryDVB::eServiceFactoryDVB()
685 ePtr<eServiceCenter> sc;
687 eServiceCenter::getPrivInstance(sc);
690 std::list<std::string> extensions;
691 extensions.push_back("ts");
692 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
695 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
696 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
699 eServiceFactoryDVB::~eServiceFactoryDVB()
701 ePtr<eServiceCenter> sc;
703 eServiceCenter::getPrivInstance(sc);
705 sc->removeServiceFactory(eServiceFactoryDVB::id);
708 DEFINE_REF(eDVBServiceList);
710 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
714 eDVBServiceList::~eDVBServiceList()
718 RESULT eDVBServiceList::startQuery()
720 ePtr<iDVBChannelList> db;
721 ePtr<eDVBResourceManager> res;
724 if ((err = eDVBResourceManager::getInstance(res)) != 0)
726 eDebug("no resource manager");
729 if ((err = res->getChannelList(db)) != 0)
731 eDebug("no channel list");
735 ePtr<eDVBChannelQuery> q;
737 if (!m_parent.path.empty())
739 eDVBChannelQuery::compile(q, m_parent.path);
742 eDebug("compile query failed");
747 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
749 eDebug("startQuery failed");
756 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
758 eServiceReferenceDVB ref;
763 while (!m_query->getNextResult(ref))
767 list.sort(iListableServiceCompare(this));
772 // The first argument of this function is a format string to specify the order and
773 // the content of the returned list
774 // useable format options are
775 // R = Service Reference (as swig object .. this is very slow)
776 // S = Service Reference (as python string object .. same as ref.toString())
777 // C = Service Reference (as python string object .. same as ref.toCompareString())
778 // N = Service Name (as python string object)
779 // n = Short Service Name (short name brakets used) (as python string object)
780 // when exactly one return value per service is selected in the format string,
781 // then each value is directly a list entry
782 // when more than one value is returned per service, then the list is a list of
784 // unknown format string chars are returned as python None values !
785 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
788 std::list<eServiceReference> tmplist;
791 if (!format || !(retcount=strlen(format)))
792 format = "R"; // just return service reference swig object ...
794 if (!getContent(tmplist, sorted))
796 int services=tmplist.size();
797 ePtr<iStaticServiceInformation> sptr;
798 eServiceCenterPtr service_center;
800 if (strchr(format, 'N') || strchr(format, 'n'))
801 eServiceCenter::getPrivInstance(service_center);
803 ret = PyList_New(services);
804 std::list<eServiceReference>::iterator it(tmplist.begin());
806 for (int cnt=0; cnt < services; ++cnt)
808 eServiceReference &ref=*it++;
809 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
810 for (int i=0; i < retcount; ++i)
815 case 'R': // service reference (swig)object
816 tmp = NEW_eServiceReference(ref);
818 case 'C': // service reference compare string
819 tmp = PyString_FromString(ref.toCompareString().c_str());
821 case 'S': // service reference string
822 tmp = PyString_FromString(ref.toString().c_str());
824 case 'N': // service name
827 service_center->info(ref, sptr);
831 sptr->getName(ref, name);
833 // filter short name brakets
835 while((pos = name.find("\xc2\x86")) != std::string::npos)
837 while((pos = name.find("\xc2\x87")) != std::string::npos)
841 tmp = PyString_FromString(name.c_str());
845 tmp = PyString_FromString("<n/a>");
847 case 'n': // short service name
850 service_center->info(ref, sptr);
854 sptr->getName(ref, name);
855 name = buildShortName(name);
857 tmp = PyString_FromString(name.c_str());
861 tmp = PyString_FromString("<n/a>");
874 PyTuple_SET_ITEM(tuple, i, tmp);
876 PyList_SET_ITEM(ret, cnt, tmp);
880 PyList_SET_ITEM(ret, cnt, tuple);
883 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
886 RESULT eDVBServiceList::getNext(eServiceReference &ref)
891 return m_query->getNextResult((eServiceReferenceDVB&)ref);
894 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
896 if (m_parent.flags & eServiceReference::canDescent) // bouquet
898 ePtr<iDVBChannelList> db;
899 ePtr<eDVBResourceManager> resm;
901 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
904 if (db->getBouquet(m_parent, m_bouquet) != 0)
915 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
919 return m_bouquet->addService(ref, before);
922 RESULT eDVBServiceList::removeService(eServiceReference &ref)
926 return m_bouquet->removeService(ref);
929 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
933 return m_bouquet->moveService(ref, pos);
936 RESULT eDVBServiceList::flushChanges()
940 return m_bouquet->flushChanges();
943 RESULT eDVBServiceList::setListName(const std::string &name)
947 return m_bouquet->setListName(name);
950 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
952 ePtr<eDVBService> service;
953 int r = lookupService(service, ref);
956 // check resources...
957 ptr = new eDVBServicePlay(ref, service);
961 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
963 if (ref.path.empty())
965 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
974 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
976 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
977 if (list->startQuery())
987 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
989 /* is a listable service? */
990 if (ref.flags & eServiceReference::canDescent) // bouquet
992 if ( !ref.name.empty() ) // satellites or providers list
993 ptr = m_StaticServiceDVBInfo;
994 else // a dvb bouquet
995 ptr = m_StaticServiceDVBBouquetInfo;
997 else if (!ref.path.empty()) /* do we have a PVR service? */
998 ptr = new eStaticServiceDVBPVRInformation(ref);
999 else // normal dvb service
1001 ePtr<eDVBService> service;
1002 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
1003 ptr = m_StaticServiceDVBInfo;
1005 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
1011 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
1013 if (ref.path.empty())
1019 ptr = new eDVBPVRServiceOfflineOperations(ref);
1024 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
1026 // TODO: handle the listing itself
1027 // if (ref.... == -1) .. return "... bouquets ...";
1028 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
1030 ePtr<iDVBChannelList> db;
1031 ePtr<eDVBResourceManager> res;
1034 if ((err = eDVBResourceManager::getInstance(res)) != 0)
1036 eDebug("no resource manager");
1039 if ((err = res->getChannelList(db)) != 0)
1041 eDebug("no channel list");
1045 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
1046 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
1048 eDebug("getService failed!");
1055 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
1056 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
1059 m_is_pvr = !m_reference.path.empty();
1061 m_timeshift_enabled = m_timeshift_active = 0;
1064 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
1065 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
1066 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
1068 m_cuesheet_changed = 0;
1069 m_cutlist_enabled = 1;
1071 m_subtitle_widget = 0;
1075 m_subtitle_sync_timer = eTimer::create(eApp);
1077 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
1080 eDVBServicePlay::~eDVBServicePlay()
1082 delete m_subtitle_widget;
1085 void eDVBServicePlay::gotNewEvent()
1089 ePtr<eServiceEvent> m_event_now, m_event_next;
1090 getEvent(m_event_now, 0);
1091 getEvent(m_event_next, 1);
1094 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1096 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1098 m_event((iPlayableService*)this, evUpdatedEventInfo);
1101 void eDVBServicePlay::serviceEvent(int event)
1103 m_tune_state = event;
1107 case eDVBServicePMTHandler::eventTuned:
1109 ePtr<iDVBDemux> m_demux;
1110 if (!m_service_handler.getDataDemux(m_demux))
1112 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1113 int sid = ref.getParentServiceID().get();
1115 sid = ref.getServiceID().get();
1116 if ( ref.getParentTransportStreamID().get() &&
1117 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1118 m_event_handler.startOther(m_demux, sid);
1120 m_event_handler.start(m_demux, sid);
1122 m_event((iPlayableService*)this, evTunedIn);
1125 case eDVBServicePMTHandler::eventNoResources:
1126 case eDVBServicePMTHandler::eventNoPAT:
1127 case eDVBServicePMTHandler::eventNoPATEntry:
1128 case eDVBServicePMTHandler::eventNoPMT:
1129 case eDVBServicePMTHandler::eventTuneFailed:
1130 case eDVBServicePMTHandler::eventMisconfiguration:
1132 eDebug("DVB service failed to tune - error %d", event);
1133 m_event((iPlayableService*)this, evTuneFailed);
1136 case eDVBServicePMTHandler::eventNewProgramInfo:
1138 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1139 if (m_timeshift_enabled)
1140 updateTimeshiftPids();
1141 if (!m_timeshift_active)
1143 if (m_first_program_info && m_is_pvr)
1145 m_first_program_info = 0;
1148 m_event((iPlayableService*)this, evUpdatedInfo);
1151 case eDVBServicePMTHandler::eventEOF:
1152 m_event((iPlayableService*)this, evEOF);
1154 case eDVBServicePMTHandler::eventSOF:
1155 m_event((iPlayableService*)this, evSOF);
1160 void eDVBServicePlay::serviceEventTimeshift(int event)
1164 case eDVBServicePMTHandler::eventNewProgramInfo:
1165 if (m_timeshift_active)
1168 case eDVBServicePMTHandler::eventSOF:
1169 m_event((iPlayableService*)this, evSOF);
1171 case eDVBServicePMTHandler::eventEOF:
1172 if ((!m_is_paused) && (m_skipmode >= 0))
1178 RESULT eDVBServicePlay::start()
1181 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1182 two (one for decoding, one for data source), as we must be prepared
1183 to start recording from the data demux. */
1185 m_cue = new eCueSheet();
1187 m_event(this, evStart);
1189 m_first_program_info = 1;
1190 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1191 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1193 /* inject EIT if there is a stored one */
1196 std::string filename = service.path;
1197 filename.erase(filename.length()-2, 2);
1199 ePtr<eServiceEvent> event = new eServiceEvent;
1200 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1202 ePtr<eServiceEvent> empty;
1203 m_event_handler.inject(event, 0);
1204 m_event_handler.inject(empty, 1);
1211 m_event(this, evStart);
1216 RESULT eDVBServicePlay::stop()
1218 /* add bookmark for last play position */
1221 pts_t play_position, length;
1222 if (!getPlayPosition(play_position))
1224 /* remove last position */
1225 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1227 if (i->what == 3) /* current play position */
1229 m_cue_entries.erase(i);
1230 i = m_cue_entries.begin();
1236 if (getLength(length))
1241 int perc = play_position * 100LL / length;
1243 /* only store last play position when between 1% and 99% */
1244 if ((1 < perc) && (perc < 99))
1245 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1247 m_cuesheet_changed = 1;
1251 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1253 m_service_handler_timeshift.free();
1254 m_service_handler.free();
1256 if (m_is_pvr && m_cuesheet_changed)
1259 /* save cuesheet only when main file is accessible. */
1260 if (!::stat(m_reference.path.c_str(), &s))
1263 m_event((iPlayableService*)this, evStopped);
1267 RESULT eDVBServicePlay::setTarget(int target)
1269 m_is_primary = !target;
1273 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1275 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1279 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1281 /* note: we check for timeshift to be enabled,
1282 not neccessary active. if you pause when timeshift
1283 is not active, you should activate it when unpausing */
1284 if ((!m_is_pvr) && (!m_timeshift_enabled))
1294 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1297 return m_decoder->setSlowMotion(ratio);
1302 RESULT eDVBServicePlay::setFastForward(int ratio)
1304 int skipmode, ffratio;
1310 } else if (ratio > 0)
1318 } else // if (ratio < 0)
1324 if (m_skipmode != skipmode)
1326 eDebug("setting cue skipmode to %d", skipmode);
1328 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1331 m_skipmode = skipmode;
1336 return m_decoder->setFastForward(ffratio);
1339 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1341 if (m_is_pvr || m_timeshift_enabled)
1351 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1352 RESULT eDVBServicePlay::getLength(pts_t &len)
1354 ePtr<iDVBPVRChannel> pvr_channel;
1356 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1359 return pvr_channel->getLength(len);
1362 RESULT eDVBServicePlay::pause()
1364 if (!m_is_paused && m_decoder)
1367 return m_decoder->freeze(0);
1372 RESULT eDVBServicePlay::unpause()
1374 if (m_is_paused && m_decoder)
1377 return m_decoder->unfreeze();
1382 RESULT eDVBServicePlay::seekTo(pts_t to)
1384 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1386 if (!m_decode_demux)
1389 ePtr<iDVBPVRChannel> pvr_channel;
1391 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1397 m_cue->seekTo(0, to);
1398 m_dvb_subtitle_pages.clear();
1399 m_subtitle_pages.clear();
1404 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1406 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1408 if (!m_decode_demux)
1411 ePtr<iDVBPVRChannel> pvr_channel;
1413 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1418 /* HACK until we have skip-AP api */
1419 if ((to > 0) && (to < 100))
1427 m_cue->seekTo(mode, to);
1428 m_dvb_subtitle_pages.clear();
1429 m_subtitle_pages.clear();
1433 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1435 ePtr<iDVBPVRChannel> pvr_channel;
1437 if (!m_decode_demux)
1440 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1445 /* if there is a decoder, use audio or video PTS */
1448 r = m_decoder->getPTS(0, pos);
1454 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1457 RESULT eDVBServicePlay::setTrickmode(int trick)
1460 m_decoder->setTrickmode(trick);
1464 RESULT eDVBServicePlay::isCurrentlySeekable()
1466 return m_is_pvr || m_timeshift_active;
1469 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1475 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1481 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1487 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1493 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1499 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1502 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1503 (m_timeshift_enabled || !m_is_pvr))
1505 if (!m_timeshift_enabled)
1507 /* query config path */
1509 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1510 eDebug("could not query ts path from config");
1514 /* we need enough diskspace */
1516 if (statfs(tspath.c_str(), &fs) < 0)
1518 eDebug("statfs failed!");
1522 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1524 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1534 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1545 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1551 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1557 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1563 RESULT eDVBServicePlay::getName(std::string &name)
1567 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1568 return i->getName(m_reference, name);
1572 m_dvb_service->getName(m_reference, name);
1576 else if (!m_reference.name.empty())
1577 eStaticServiceDVBInformation().getName(m_reference, name);
1579 name = "DVB service";
1583 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1585 return m_event_handler.getEvent(evt, nownext);
1588 int eDVBServicePlay::getInfo(int w)
1590 eDVBServicePMTHandler::program program;
1593 return resIsPyObject;
1595 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1597 int no_program_info = 0;
1599 if (h.getProgramInfo(program))
1600 no_program_info = 1;
1606 return m_decoder->getVideoHeight();
1610 return m_decoder->getVideoWidth();
1614 return m_decoder->getVideoFrameRate();
1618 return m_decoder->getVideoProgressive();
1624 aspect = m_decoder->getVideoAspect();
1625 if (no_program_info)
1627 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1629 ePtr<eServiceEvent> evt;
1630 if (!m_event_handler.getEvent(evt, 0))
1632 ePtr<eComponentData> data;
1633 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1635 if ( data->getStreamContent() == 1 )
1637 switch(data->getComponentType())
1640 case 1: // 4:3 SD PAL
1642 case 3: // 16:9 SD PAL
1643 case 4: // > 16:9 PAL
1644 case 5: // 4:3 SD NTSC
1646 case 7: // 16:9 SD NTSC
1647 case 8: // > 16:9 NTSC
1650 case 9: // 4:3 HD PAL
1652 case 0xB: // 16:9 HD PAL
1653 case 0xC: // > 16:9 HD PAL
1654 case 0xD: // 4:3 HD NTSC
1656 case 0xF: // 16:9 HD NTSC
1657 case 0x10: // > 16:9 HD PAL
1658 return data->getComponentType();
1668 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1669 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1670 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1671 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1672 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1673 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1674 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1675 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1676 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1677 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1678 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1679 case sProvider: if (!m_dvb_service) return -1; return -2;
1680 case sServiceref: return resIsString;
1681 case sDVBState: return m_tune_state;
1688 std::string eDVBServicePlay::getInfoString(int w)
1693 if (!m_dvb_service) return "";
1694 return m_dvb_service->m_provider_name;
1696 return m_reference.toString();
1700 return iServiceInformation::getInfoString(w);
1703 PyObject *eDVBServicePlay::getInfoObject(int w)
1708 return m_service_handler.getCaIds();
1709 case sTransponderData:
1710 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1714 return iServiceInformation::getInfoObject(w);
1717 int eDVBServicePlay::getNumberOfTracks()
1719 eDVBServicePMTHandler::program program;
1720 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1721 if (h.getProgramInfo(program))
1723 return program.audioStreams.size();
1726 int eDVBServicePlay::getCurrentTrack()
1728 eDVBServicePMTHandler::program program;
1729 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1730 if (h.getProgramInfo(program))
1733 int max = program.audioStreams.size();
1736 for (i = 0; i < max; ++i)
1737 if (program.audioStreams[i].pid == m_current_audio_pid)
1743 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1745 int ret = selectAudioStream(i);
1747 if (m_decoder->start())
1753 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1755 eDVBServicePMTHandler::program program;
1756 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1758 if (h.getProgramInfo(program))
1761 if (i >= program.audioStreams.size())
1764 info.m_pid = program.audioStreams[i].pid;
1766 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1767 info.m_description = "MPEG";
1768 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1769 info.m_description = "AC3";
1770 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1771 info.m_description = "AAC";
1772 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1773 info.m_description = "DTS";
1775 info.m_description = "???";
1777 if (program.audioStreams[i].component_tag != -1)
1779 ePtr<eServiceEvent> evt;
1780 if (!m_event_handler.getEvent(evt, 0))
1782 ePtr<eComponentData> data;
1783 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1784 info.m_language = data->getText();
1788 if (info.m_language.empty())
1789 info.m_language = program.audioStreams[i].language_code;
1794 int eDVBServicePlay::selectAudioStream(int i)
1796 eDVBServicePMTHandler::program program;
1797 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1799 if (h.getProgramInfo(program))
1802 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1810 stream = program.defaultAudioStream;
1812 int apid = -1, apidtype = -1;
1814 if (((unsigned int)stream) < program.audioStreams.size())
1816 apid = program.audioStreams[stream].pid;
1817 apidtype = program.audioStreams[stream].type;
1820 m_current_audio_pid = apid;
1822 if (m_decoder->setAudioPID(apid, apidtype))
1824 eDebug("set audio pid failed");
1828 /* 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 */
1829 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1832 ePtr<iDVBDemux> data_demux;
1833 if (!h.getDataDemux(data_demux))
1835 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1836 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1840 /* if we decided that we need one, update the pid */
1842 m_rds_decoder->start(apid);
1844 /* store new pid as default only when:
1845 a.) we have an entry in the service db for the current service,
1846 b.) we are not playing back something,
1847 c.) we are not selecting the default entry. (we wouldn't change
1848 anything in the best case, or destroy the default setting in
1849 case the real default is not yet available.)
1851 if (m_dvb_service && !m_is_pvr && ((i != -1)
1852 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1854 if (apidtype == eDVBAudio::aMPEG)
1856 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1857 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1861 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1862 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1866 h.resetCachedProgram();
1871 int eDVBServicePlay::getCurrentChannel()
1873 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1876 RESULT eDVBServicePlay::selectChannel(int i)
1878 if (i < LEFT || i > RIGHT || i == STEREO)
1881 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1883 m_decoder->setAudioChannel(i);
1887 std::string eDVBServicePlay::getText(int x)
1893 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1895 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1900 void eDVBServicePlay::rdsDecoderEvent(int what)
1904 case eDVBRdsDecoder::RadioTextChanged:
1905 m_event((iPlayableService*)this, evUpdatedRadioText);
1907 case eDVBRdsDecoder::RtpTextChanged:
1908 m_event((iPlayableService*)this, evUpdatedRtpText);
1910 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1911 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1913 case eDVBRdsDecoder::RecvRassSlidePic:
1914 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1919 void eDVBServicePlay::showRassSlidePicture()
1925 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1926 if (rass_slide_pic.length())
1927 m_decoder->showSinglePic(rass_slide_pic.c_str());
1929 eDebug("empty filename for rass slide picture received!!");
1932 eDebug("no MPEG Decoder to show iframes avail");
1935 eDebug("showRassSlidePicture called.. but not decoder");
1938 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1944 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1945 if (rass_interactive_pic.length())
1946 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1948 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1951 eDebug("no MPEG Decoder to show iframes avail");
1954 eDebug("showRassInteractivePic called.. but not decoder");
1957 ePyObject eDVBServicePlay::getRassInteractiveMask()
1960 return m_rds_decoder->getRassPictureMask();
1964 int eDVBServiceBase::getFrontendInfo(int w)
1966 eUsePtr<iDVBChannel> channel;
1967 if(m_service_handler.getChannel(channel))
1969 ePtr<iDVBFrontend> fe;
1970 if(channel->getFrontend(fe))
1972 return fe->readFrontendData(w);
1975 PyObject *eDVBServiceBase::getFrontendData()
1977 ePyObject ret = PyDict_New();
1980 eUsePtr<iDVBChannel> channel;
1981 if(!m_service_handler.getChannel(channel))
1983 ePtr<iDVBFrontend> fe;
1984 if(!channel->getFrontend(fe))
1985 fe->getFrontendData(ret);
1993 PyObject *eDVBServiceBase::getFrontendStatus()
1995 ePyObject ret = PyDict_New();
1998 eUsePtr<iDVBChannel> channel;
1999 if(!m_service_handler.getChannel(channel))
2001 ePtr<iDVBFrontend> fe;
2002 if(!channel->getFrontend(fe))
2003 fe->getFrontendStatus(ret);
2011 PyObject *eDVBServiceBase::getTransponderData(bool original)
2013 ePyObject ret = PyDict_New();
2016 eUsePtr<iDVBChannel> channel;
2017 if(!m_service_handler.getChannel(channel))
2019 ePtr<iDVBFrontend> fe;
2020 if(!channel->getFrontend(fe))
2022 fe->getTransponderData(ret, original);
2023 ePtr<iDVBFrontendParameters> feparm;
2024 channel->getCurrentFrontendParameters(feparm);
2027 eDVBFrontendParametersSatellite osat;
2028 if (!feparm->getDVBS(osat))
2030 PutToDict(ret, "orbital_position", osat.orbital_position);
2031 const char *tmp = "UNKNOWN";
2032 switch(osat.polarisation)
2034 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2035 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2036 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2037 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2040 PutToDict(ret, "polarization", tmp);
2051 PyObject *eDVBServiceBase::getAll(bool original)
2053 ePyObject ret = getTransponderData(original);
2056 eUsePtr<iDVBChannel> channel;
2057 if(!m_service_handler.getChannel(channel))
2059 ePtr<iDVBFrontend> fe;
2060 if(!channel->getFrontend(fe))
2062 fe->getFrontendData(ret);
2063 fe->getFrontendStatus(ret);
2070 int eDVBServicePlay::getNumberOfSubservices()
2072 ePtr<eServiceEvent> evt;
2073 if (!m_event_handler.getEvent(evt, 0))
2074 return evt->getNumOfLinkageServices();
2078 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2080 ePtr<eServiceEvent> evt;
2081 if (!m_event_handler.getEvent(evt, 0))
2083 if (!evt->getLinkageService(sub, m_reference, n))
2086 sub.type=eServiceReference::idInvalid;
2090 RESULT eDVBServicePlay::startTimeshift()
2092 ePtr<iDVBDemux> demux;
2094 eDebug("Start timeshift!");
2096 if (m_timeshift_enabled)
2099 /* start recording with the data demux. */
2100 if (m_service_handler.getDataDemux(demux))
2103 demux->createTSRecorder(m_record);
2108 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2109 eDebug("could not query ts path");
2112 tspath.append("/timeshift.XXXXXX");
2114 templ = new char[tspath.length() + 1];
2115 strcpy(templ, tspath.c_str());
2117 m_timeshift_fd = mkstemp(templ);
2118 m_timeshift_file = std::string(templ);
2120 eDebug("recording to %s", templ);
2124 if (m_timeshift_fd < 0)
2130 m_record->setTargetFD(m_timeshift_fd);
2132 m_timeshift_enabled = 1;
2134 updateTimeshiftPids();
2140 RESULT eDVBServicePlay::stopTimeshift()
2142 if (!m_timeshift_enabled)
2147 m_timeshift_enabled = 0;
2152 close(m_timeshift_fd);
2153 eDebug("remove timeshift file");
2154 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2159 int eDVBServicePlay::isTimeshiftActive()
2161 return m_timeshift_enabled && m_timeshift_active;
2164 RESULT eDVBServicePlay::activateTimeshift()
2166 if (!m_timeshift_enabled)
2169 if (!m_timeshift_active)
2171 switchToTimeshift();
2178 PyObject *eDVBServicePlay::getCutList()
2180 ePyObject list = PyList_New(0);
2182 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2184 ePyObject tuple = PyTuple_New(2);
2185 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2186 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2187 PyList_Append(list, tuple);
2194 void eDVBServicePlay::setCutList(ePyObject list)
2196 if (!PyList_Check(list))
2198 int size = PyList_Size(list);
2201 m_cue_entries.clear();
2203 for (i=0; i<size; ++i)
2205 ePyObject tuple = PyList_GET_ITEM(list, i);
2206 if (!PyTuple_Check(tuple))
2208 eDebug("non-tuple in cutlist");
2211 if (PyTuple_Size(tuple) != 2)
2213 eDebug("cutlist entries need to be a 2-tuple");
2216 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2217 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2219 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2222 pts_t pts = PyLong_AsLongLong(ppts);
2223 int type = PyInt_AsLong(ptype);
2224 m_cue_entries.insert(cueEntry(pts, type));
2225 eDebug("adding %08llx, %d", pts, type);
2227 m_cuesheet_changed = 1;
2229 cutlistToCuesheet();
2230 m_event((iPlayableService*)this, evCuesheetChanged);
2233 void eDVBServicePlay::setCutListEnable(int enable)
2235 m_cutlist_enabled = enable;
2236 cutlistToCuesheet();
2239 void eDVBServicePlay::updateTimeshiftPids()
2244 eDVBServicePMTHandler::program program;
2245 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2247 if (h.getProgramInfo(program))
2251 std::set<int> pids_to_record;
2252 pids_to_record.insert(0); // PAT
2253 if (program.pmtPid != -1)
2254 pids_to_record.insert(program.pmtPid); // PMT
2256 if (program.textPid != -1)
2257 pids_to_record.insert(program.textPid); // Videotext
2259 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2260 i(program.videoStreams.begin());
2261 i != program.videoStreams.end(); ++i)
2262 pids_to_record.insert(i->pid);
2264 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2265 i(program.audioStreams.begin());
2266 i != program.audioStreams.end(); ++i)
2267 pids_to_record.insert(i->pid);
2269 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2270 i(program.subtitleStreams.begin());
2271 i != program.subtitleStreams.end(); ++i)
2272 pids_to_record.insert(i->pid);
2274 std::set<int> new_pids, obsolete_pids;
2276 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2277 m_pids_active.begin(), m_pids_active.end(),
2278 std::inserter(new_pids, new_pids.begin()));
2280 std::set_difference(
2281 m_pids_active.begin(), m_pids_active.end(),
2282 pids_to_record.begin(), pids_to_record.end(),
2283 std::inserter(new_pids, new_pids.begin())
2286 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2287 m_record->addPID(*i);
2289 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2290 m_record->removePID(*i);
2294 void eDVBServicePlay::switchToLive()
2296 if (!m_timeshift_active)
2302 m_teletext_parser = 0;
2304 m_subtitle_parser = 0;
2305 m_new_dvb_subtitle_page_connection = 0;
2306 m_new_subtitle_page_connection = 0;
2307 m_rds_decoder_event_connection = 0;
2308 m_video_event_connection = 0;
2310 /* free the timeshift service handler, we need the resources */
2311 m_service_handler_timeshift.free();
2312 m_timeshift_active = 0;
2314 m_event((iPlayableService*)this, evSeekableStatusChanged);
2319 void eDVBServicePlay::switchToTimeshift()
2321 if (m_timeshift_active)
2326 m_teletext_parser = 0;
2328 m_subtitle_parser = 0;
2329 m_new_subtitle_page_connection = 0;
2330 m_new_dvb_subtitle_page_connection = 0;
2331 m_rds_decoder_event_connection = 0;
2332 m_video_event_connection = 0;
2334 m_timeshift_active = 1;
2336 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2337 r.path = m_timeshift_file;
2339 m_cue = new eCueSheet();
2340 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2342 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2344 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2346 m_event((iPlayableService*)this, evSeekableStatusChanged);
2349 void eDVBServicePlay::updateDecoder()
2351 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2353 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2355 eDVBServicePMTHandler::program program;
2356 if (h.getProgramInfo(program))
2357 eDebug("getting program info failed.");
2360 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2361 if (!program.videoStreams.empty())
2363 eDebugNoNewLine(" (");
2364 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2365 i(program.videoStreams.begin());
2366 i != program.videoStreams.end(); ++i)
2373 if (i != program.videoStreams.begin())
2374 eDebugNoNewLine(", ");
2375 eDebugNoNewLine("%04x", i->pid);
2377 eDebugNoNewLine(")");
2379 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2380 if (!program.audioStreams.empty())
2382 eDebugNoNewLine(" (");
2383 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2384 i(program.audioStreams.begin());
2385 i != program.audioStreams.end(); ++i)
2387 if (i != program.audioStreams.begin())
2388 eDebugNoNewLine(", ");
2389 eDebugNoNewLine("%04x", i->pid);
2391 eDebugNoNewLine(")");
2393 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2394 pcrpid = program.pcrPid;
2395 eDebug(", and the text pid is %04x", program.textPid);
2396 tpid = program.textPid;
2401 h.getDecodeDemux(m_decode_demux);
2404 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2406 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2407 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2408 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2409 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2410 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2413 m_teletext_parser = 0;
2414 m_subtitle_parser = 0;
2418 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2425 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2426 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2427 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2429 else // subservice or recording
2431 eServiceReferenceDVB ref;
2432 m_service_handler.getServiceReference(ref);
2433 eServiceReferenceDVB parent = ref.getParentServiceReference();
2438 ePtr<eDVBResourceManager> res_mgr;
2439 if (!eDVBResourceManager::getInstance(res_mgr))
2441 ePtr<iDVBChannelList> db;
2442 if (!res_mgr->getChannelList(db))
2444 ePtr<eDVBService> origService;
2445 if (!db->getService(parent, origService))
2447 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2448 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2454 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2455 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2457 m_decoder->setVideoPID(vpid, vpidtype);
2458 selectAudioStream();
2460 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2461 m_decoder->setSyncPCR(pcrpid);
2463 m_decoder->setSyncPCR(-1);
2465 m_decoder->setTextPID(tpid);
2467 m_teletext_parser->start(program.textPid);
2470 m_decoder->setTrickmode(1);
2473 m_decoder->preroll();
2477 if (vpid > 0 && vpid < 0x2000)
2481 std::string radio_pic;
2482 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2483 m_decoder->setRadioPic(radio_pic);
2486 m_decoder->setAudioChannel(achannel);
2488 /* don't worry about non-existing services, nor pvr services */
2489 if (m_dvb_service && !m_is_pvr)
2491 /* (audio pid will be set in selectAudioTrack */
2492 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2493 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2494 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2495 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2498 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2501 void eDVBServicePlay::loadCuesheet()
2503 std::string filename = m_reference.path + ".cuts";
2505 m_cue_entries.clear();
2507 FILE *f = fopen(filename.c_str(), "rb");
2511 eDebug("loading cuts..");
2514 unsigned long long where;
2517 if (!fread(&where, sizeof(where), 1, f))
2519 if (!fread(&what, sizeof(what), 1, f))
2522 #if BYTE_ORDER == LITTLE_ENDIAN
2523 where = bswap_64(where);
2530 m_cue_entries.insert(cueEntry(where, what));
2533 eDebug("%d entries", m_cue_entries.size());
2535 eDebug("cutfile not found!");
2537 m_cuesheet_changed = 0;
2538 cutlistToCuesheet();
2539 m_event((iPlayableService*)this, evCuesheetChanged);
2542 void eDVBServicePlay::saveCuesheet()
2544 std::string filename = m_reference.path + ".cuts";
2546 FILE *f = fopen(filename.c_str(), "wb");
2550 unsigned long long where;
2553 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2555 #if BYTE_ORDER == BIG_ENDIAN
2558 where = bswap_64(i->where);
2560 what = htonl(i->what);
2561 fwrite(&where, sizeof(where), 1, f);
2562 fwrite(&what, sizeof(what), 1, f);
2568 m_cuesheet_changed = 0;
2571 void eDVBServicePlay::cutlistToCuesheet()
2575 eDebug("no cue sheet");
2580 if (!m_cutlist_enabled)
2582 m_cue->commitSpans();
2583 eDebug("cutlists were disabled");
2587 pts_t in = 0, out = 0, length = 0;
2591 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2595 if (i == m_cue_entries.end())
2598 if (i->what == 0) /* in */
2602 } else if (i->what == 1) /* out */
2604 else /* mark (2) or last play position (3) */
2621 m_cue->addSourceSpan(in, out);
2625 if (i == m_cue_entries.end())
2628 m_cue->commitSpans();
2631 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2633 if (m_subtitle_widget)
2634 disableSubtitles(parent);
2637 int tuplesize = PyTuple_Size(tuple);
2640 if (!PyTuple_Check(tuple))
2646 entry = PyTuple_GET_ITEM(tuple, 0);
2648 if (!PyInt_Check(entry))
2651 type = PyInt_AsLong(entry);
2653 if (type == 1) // teletext subtitles
2655 int page, magazine, pid;
2659 if (!m_teletext_parser)
2661 eDebug("enable teletext subtitles.. no parser !!!");
2665 entry = PyTuple_GET_ITEM(tuple, 1);
2666 if (!PyInt_Check(entry))
2668 pid = PyInt_AsLong(entry);
2670 entry = PyTuple_GET_ITEM(tuple, 2);
2671 if (!PyInt_Check(entry))
2673 page = PyInt_AsLong(entry);
2675 entry = PyTuple_GET_ITEM(tuple, 3);
2676 if (!PyInt_Check(entry))
2678 magazine = PyInt_AsLong(entry);
2680 m_subtitle_widget = new eSubtitleWidget(parent);
2681 m_subtitle_widget->resize(parent->size()); /* full size */
2682 m_teletext_parser->setPageAndMagazine(page, magazine);
2684 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2688 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2689 if (!m_subtitle_parser)
2691 eDebug("enable dvb subtitles.. no parser !!!");
2697 entry = PyTuple_GET_ITEM(tuple, 1);
2698 if (!PyInt_Check(entry))
2700 pid = PyInt_AsLong(entry);
2702 entry = PyTuple_GET_ITEM(tuple, 2);
2703 if (!PyInt_Check(entry))
2705 composition_page_id = PyInt_AsLong(entry);
2707 entry = PyTuple_GET_ITEM(tuple, 3);
2708 if (!PyInt_Check(entry))
2710 ancillary_page_id = PyInt_AsLong(entry);
2712 m_subtitle_widget = new eSubtitleWidget(parent);
2713 m_subtitle_widget->resize(parent->size()); /* full size */
2714 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2716 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2722 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2723 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2724 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2728 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2730 delete m_subtitle_widget;
2731 m_subtitle_widget = 0;
2732 if (m_subtitle_parser)
2734 m_subtitle_parser->stop();
2735 m_dvb_subtitle_pages.clear();
2737 if (m_teletext_parser)
2739 m_teletext_parser->setPageAndMagazine(-1, -1);
2740 m_subtitle_pages.clear();
2743 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2747 PyObject *eDVBServicePlay::getCachedSubtitle()
2751 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2754 unsigned int data = (unsigned int)tmp;
2755 int pid = (data&0xFFFF0000)>>16;
2756 ePyObject tuple = PyTuple_New(4);
2757 eDVBServicePMTHandler::program program;
2758 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2759 if (!h.getProgramInfo(program))
2761 if (program.textPid==pid) // teletext
2762 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2764 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2765 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2766 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2767 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2775 PyObject *eDVBServicePlay::getSubtitleList()
2777 if (!m_teletext_parser)
2780 ePyObject l = PyList_New(0);
2781 std::set<int> added_ttx_pages;
2783 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2784 m_teletext_parser->m_found_subtitle_pages;
2786 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2787 eDVBServicePMTHandler::program program;
2788 if (h.getProgramInfo(program))
2789 eDebug("getting program info failed.");
2792 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2793 it != program.subtitleStreams.end(); ++it)
2795 switch(it->subtitling_type)
2797 case 0x01: // ebu teletext subtitles
2799 int page_number = it->teletext_page_number & 0xFF;
2800 int magazine_number = it->teletext_magazine_number & 7;
2801 int hash = magazine_number << 8 | page_number;
2802 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2804 ePyObject tuple = PyTuple_New(5);
2805 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2806 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2807 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2808 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2809 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2810 PyList_Append(l, tuple);
2812 added_ttx_pages.insert(hash);
2817 case 0x20 ... 0x23: // dvb subtitles
2819 ePyObject tuple = PyTuple_New(5);
2820 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2821 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2822 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2823 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2824 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2825 PyList_Insert(l, 0, tuple);
2833 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2834 it != subs.end(); ++it)
2836 int page_number = it->teletext_page_number & 0xFF;
2837 int magazine_number = it->teletext_magazine_number & 7;
2838 int hash = magazine_number << 8 | page_number;
2839 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2841 ePyObject tuple = PyTuple_New(5);
2842 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2843 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2844 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2845 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2846 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2847 PyList_Append(l, tuple);
2855 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2857 if (m_subtitle_widget)
2861 m_decoder->getPTS(0, pos);
2862 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2863 m_subtitle_pages.push_back(page);
2864 checkSubtitleTiming();
2868 void eDVBServicePlay::checkSubtitleTiming()
2870 eDebug("checkSubtitleTiming");
2871 if (!m_subtitle_widget)
2875 enum { TELETEXT, DVB } type;
2876 eDVBTeletextSubtitlePage page;
2877 eDVBSubtitlePage dvb_page;
2879 if (!m_subtitle_pages.empty())
2881 page = m_subtitle_pages.front();
2883 show_time = page.m_pts;
2885 else if (!m_dvb_subtitle_pages.empty())
2887 dvb_page = m_dvb_subtitle_pages.front();
2889 show_time = dvb_page.m_show_time;
2897 m_decoder->getPTS(0, pos);
2899 eDebug("%lld %lld", pos, show_time);
2900 int diff = show_time - pos;
2903 eDebug("[late (%d ms)]", -diff / 90);
2906 // if (diff > 900000)
2908 // eDebug("[invalid]");
2914 if (type == TELETEXT)
2916 eDebug("display teletext subtitle page %lld", show_time);
2917 m_subtitle_widget->setPage(page);
2918 m_subtitle_pages.pop_front();
2922 eDebug("display dvb subtitle Page %lld", show_time);
2923 m_subtitle_widget->setPage(dvb_page);
2924 m_dvb_subtitle_pages.pop_front();
2928 eDebug("start subtitle delay %d", diff / 90);
2929 m_subtitle_sync_timer->start(diff / 90, 1);
2935 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2937 if (m_subtitle_widget)
2941 m_decoder->getPTS(0, pos);
2942 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2943 m_dvb_subtitle_pages.push_back(p);
2944 checkSubtitleTiming();
2948 int eDVBServicePlay::getAC3Delay()
2951 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2953 return m_decoder->getAC3Delay();
2958 int eDVBServicePlay::getPCMDelay()
2961 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2963 return m_decoder->getPCMDelay();
2968 void eDVBServicePlay::setAC3Delay(int delay)
2971 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2973 m_decoder->setAC3Delay(delay);
2976 void eDVBServicePlay::setPCMDelay(int delay)
2979 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2981 m_decoder->setPCMDelay(delay);
2984 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2986 switch(event.type) {
2987 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2988 m_event((iPlayableService*)this, evVideoSizeChanged);
2990 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2991 m_event((iPlayableService*)this, evVideoFramerateChanged);
2993 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2994 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3001 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3007 PyObject *eDVBServicePlay::getStreamingData()
3009 eDVBServicePMTHandler::program program;
3010 if (m_service_handler.getProgramInfo(program))
3015 ePyObject r = program.createPythonObject();
3016 ePtr<iDVBDemux> demux;
3017 if (!m_service_handler.getDataDemux(demux))
3020 if (!demux->getCADemuxID(demux_id))
3021 PutToDict(r, "demux", demux_id);
3028 DEFINE_REF(eDVBServicePlay)
3030 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3034 case iServiceInformation::sTransponderData:
3035 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3039 return iStaticServiceInformation::getInfoObject(ref, w);
3042 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");