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_None: tmp="NONE"; break;
134 case eDVBFrontendParametersSatellite::FEC_1_2: tmp="1/2"; break;
135 case eDVBFrontendParametersSatellite::FEC_2_3: tmp="2/3"; break;
136 case eDVBFrontendParametersSatellite::FEC_3_4: tmp="3/4"; break;
137 case eDVBFrontendParametersSatellite::FEC_5_6: tmp="5/6"; break;
138 case eDVBFrontendParametersSatellite::FEC_7_8: tmp="7/8"; break;
139 case eDVBFrontendParametersSatellite::FEC_3_5: tmp="3/5"; break;
140 case eDVBFrontendParametersSatellite::FEC_4_5: tmp="4/5"; break;
141 case eDVBFrontendParametersSatellite::FEC_8_9: tmp="8/9"; break;
142 case eDVBFrontendParametersSatellite::FEC_9_10: tmp="9/10"; break;
144 case eDVBFrontendParametersSatellite::FEC_Auto: 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_8PSK: tmp="8PSK"; break;
152 case eDVBFrontendParametersSatellite::Modulation_QAM16: 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_8MHz: tmp="8 MHz"; break;
199 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz: tmp="7 MHz"; break;
200 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz: tmp="6 MHz"; break;
202 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto: tmp="AUTO"; break;
204 PutToDict(dict, "bandwidth", tmp);
205 switch (feparm.code_rate_LP)
207 case eDVBFrontendParametersTerrestrial::FEC_1_2: tmp="1/2"; break;
208 case eDVBFrontendParametersTerrestrial::FEC_2_3: tmp="2/3"; break;
209 case eDVBFrontendParametersTerrestrial::FEC_3_4: tmp="3/4"; break;
210 case eDVBFrontendParametersTerrestrial::FEC_5_6: tmp="5/6"; break;
211 case eDVBFrontendParametersTerrestrial::FEC_7_8: tmp="7/8"; break;
213 case eDVBFrontendParametersTerrestrial::FEC_Auto: tmp="AUTO"; break;
215 PutToDict(dict, "code rate lp", tmp);
216 switch (feparm.code_rate_HP)
218 case eDVBFrontendParametersTerrestrial::FEC_1_2: tmp="1/2"; break;
219 case eDVBFrontendParametersTerrestrial::FEC_2_3: tmp="2/3"; break;
220 case eDVBFrontendParametersTerrestrial::FEC_3_4: tmp="3/4"; break;
221 case eDVBFrontendParametersTerrestrial::FEC_5_6: tmp="5/6"; break;
222 case eDVBFrontendParametersTerrestrial::FEC_7_8: tmp="7/8"; break;
224 case eDVBFrontendParametersTerrestrial::FEC_Auto: 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_2k: tmp="2k"; break;
239 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k: tmp="8k"; break;
241 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto: tmp="AUTO"; break;
243 PutToDict(dict, "transmission mode", tmp);
244 switch (feparm.guard_interval)
246 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32: tmp="1/32"; break;
247 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16: tmp="1/16"; break;
248 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8: tmp="1/8"; break;
249 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4: tmp="1/4"; break;
251 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto: tmp="AUTO"; break;
253 PutToDict(dict, "guard interval", tmp);
254 switch (feparm.hierarchy)
256 case eDVBFrontendParametersTerrestrial::Hierarchy_None: tmp="NONE"; break;
257 case eDVBFrontendParametersTerrestrial::Hierarchy_1: tmp="1"; break;
258 case eDVBFrontendParametersTerrestrial::Hierarchy_2: tmp="2"; break;
259 case eDVBFrontendParametersTerrestrial::Hierarchy_4: tmp="4"; break;
261 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto: 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_None: tmp="NONE"; break;
302 case eDVBFrontendParametersCable::FEC_1_2: tmp="1/2"; break;
303 case eDVBFrontendParametersCable::FEC_2_3: tmp="2/3"; break;
304 case eDVBFrontendParametersCable::FEC_3_4: tmp="3/4"; break;
305 case eDVBFrontendParametersCable::FEC_5_6: tmp="5/6"; break;
306 case eDVBFrontendParametersCable::FEC_7_8: tmp="7/8"; break;
307 case eDVBFrontendParametersCable::FEC_8_9: tmp="8/9"; break;
309 case eDVBFrontendParametersCable::FEC_Auto: 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 PutToDict(ret, "polarization", osat.polarisation);
2042 PyObject *eDVBServiceBase::getAll(bool original)
2044 ePyObject ret = getTransponderData(original);
2047 eUsePtr<iDVBChannel> channel;
2048 if(!m_service_handler.getChannel(channel))
2050 ePtr<iDVBFrontend> fe;
2051 if(!channel->getFrontend(fe))
2053 fe->getFrontendData(ret);
2054 fe->getFrontendStatus(ret);
2061 int eDVBServicePlay::getNumberOfSubservices()
2063 ePtr<eServiceEvent> evt;
2064 if (!m_event_handler.getEvent(evt, 0))
2065 return evt->getNumOfLinkageServices();
2069 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2071 ePtr<eServiceEvent> evt;
2072 if (!m_event_handler.getEvent(evt, 0))
2074 if (!evt->getLinkageService(sub, m_reference, n))
2077 sub.type=eServiceReference::idInvalid;
2081 RESULT eDVBServicePlay::startTimeshift()
2083 ePtr<iDVBDemux> demux;
2085 eDebug("Start timeshift!");
2087 if (m_timeshift_enabled)
2090 /* start recording with the data demux. */
2091 if (m_service_handler.getDataDemux(demux))
2094 demux->createTSRecorder(m_record);
2099 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2100 eDebug("could not query ts path");
2103 tspath.append("/timeshift.XXXXXX");
2105 templ = new char[tspath.length() + 1];
2106 strcpy(templ, tspath.c_str());
2108 m_timeshift_fd = mkstemp(templ);
2109 m_timeshift_file = std::string(templ);
2111 eDebug("recording to %s", templ);
2115 if (m_timeshift_fd < 0)
2121 m_record->setTargetFD(m_timeshift_fd);
2123 m_timeshift_enabled = 1;
2125 updateTimeshiftPids();
2131 RESULT eDVBServicePlay::stopTimeshift()
2133 if (!m_timeshift_enabled)
2138 m_timeshift_enabled = 0;
2143 close(m_timeshift_fd);
2144 eDebug("remove timeshift file");
2145 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2150 int eDVBServicePlay::isTimeshiftActive()
2152 return m_timeshift_enabled && m_timeshift_active;
2155 RESULT eDVBServicePlay::activateTimeshift()
2157 if (!m_timeshift_enabled)
2160 if (!m_timeshift_active)
2162 switchToTimeshift();
2169 PyObject *eDVBServicePlay::getCutList()
2171 ePyObject list = PyList_New(0);
2173 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2175 ePyObject tuple = PyTuple_New(2);
2176 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2177 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2178 PyList_Append(list, tuple);
2185 void eDVBServicePlay::setCutList(ePyObject list)
2187 if (!PyList_Check(list))
2189 int size = PyList_Size(list);
2192 m_cue_entries.clear();
2194 for (i=0; i<size; ++i)
2196 ePyObject tuple = PyList_GET_ITEM(list, i);
2197 if (!PyTuple_Check(tuple))
2199 eDebug("non-tuple in cutlist");
2202 if (PyTuple_Size(tuple) != 2)
2204 eDebug("cutlist entries need to be a 2-tuple");
2207 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2208 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2210 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2213 pts_t pts = PyLong_AsLongLong(ppts);
2214 int type = PyInt_AsLong(ptype);
2215 m_cue_entries.insert(cueEntry(pts, type));
2216 eDebug("adding %08llx, %d", pts, type);
2218 m_cuesheet_changed = 1;
2220 cutlistToCuesheet();
2221 m_event((iPlayableService*)this, evCuesheetChanged);
2224 void eDVBServicePlay::setCutListEnable(int enable)
2226 m_cutlist_enabled = enable;
2227 cutlistToCuesheet();
2230 void eDVBServicePlay::updateTimeshiftPids()
2235 eDVBServicePMTHandler::program program;
2236 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2238 if (h.getProgramInfo(program))
2242 std::set<int> pids_to_record;
2243 pids_to_record.insert(0); // PAT
2244 if (program.pmtPid != -1)
2245 pids_to_record.insert(program.pmtPid); // PMT
2247 if (program.textPid != -1)
2248 pids_to_record.insert(program.textPid); // Videotext
2250 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2251 i(program.videoStreams.begin());
2252 i != program.videoStreams.end(); ++i)
2253 pids_to_record.insert(i->pid);
2255 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2256 i(program.audioStreams.begin());
2257 i != program.audioStreams.end(); ++i)
2258 pids_to_record.insert(i->pid);
2260 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2261 i(program.subtitleStreams.begin());
2262 i != program.subtitleStreams.end(); ++i)
2263 pids_to_record.insert(i->pid);
2265 std::set<int> new_pids, obsolete_pids;
2267 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2268 m_pids_active.begin(), m_pids_active.end(),
2269 std::inserter(new_pids, new_pids.begin()));
2271 std::set_difference(
2272 m_pids_active.begin(), m_pids_active.end(),
2273 pids_to_record.begin(), pids_to_record.end(),
2274 std::inserter(new_pids, new_pids.begin())
2277 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2278 m_record->addPID(*i);
2280 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2281 m_record->removePID(*i);
2285 void eDVBServicePlay::switchToLive()
2287 if (!m_timeshift_active)
2293 m_teletext_parser = 0;
2295 m_subtitle_parser = 0;
2296 m_new_dvb_subtitle_page_connection = 0;
2297 m_new_subtitle_page_connection = 0;
2298 m_rds_decoder_event_connection = 0;
2299 m_video_event_connection = 0;
2301 /* free the timeshift service handler, we need the resources */
2302 m_service_handler_timeshift.free();
2303 m_timeshift_active = 0;
2305 m_event((iPlayableService*)this, evSeekableStatusChanged);
2310 void eDVBServicePlay::switchToTimeshift()
2312 if (m_timeshift_active)
2317 m_teletext_parser = 0;
2319 m_subtitle_parser = 0;
2320 m_new_subtitle_page_connection = 0;
2321 m_new_dvb_subtitle_page_connection = 0;
2322 m_rds_decoder_event_connection = 0;
2323 m_video_event_connection = 0;
2325 m_timeshift_active = 1;
2327 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2328 r.path = m_timeshift_file;
2330 m_cue = new eCueSheet();
2331 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2333 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2335 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2337 m_event((iPlayableService*)this, evSeekableStatusChanged);
2340 void eDVBServicePlay::updateDecoder()
2342 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2344 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2346 eDVBServicePMTHandler::program program;
2347 if (h.getProgramInfo(program))
2348 eDebug("getting program info failed.");
2351 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2352 if (!program.videoStreams.empty())
2354 eDebugNoNewLine(" (");
2355 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2356 i(program.videoStreams.begin());
2357 i != program.videoStreams.end(); ++i)
2364 if (i != program.videoStreams.begin())
2365 eDebugNoNewLine(", ");
2366 eDebugNoNewLine("%04x", i->pid);
2368 eDebugNoNewLine(")");
2370 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2371 if (!program.audioStreams.empty())
2373 eDebugNoNewLine(" (");
2374 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2375 i(program.audioStreams.begin());
2376 i != program.audioStreams.end(); ++i)
2378 if (i != program.audioStreams.begin())
2379 eDebugNoNewLine(", ");
2380 eDebugNoNewLine("%04x", i->pid);
2382 eDebugNoNewLine(")");
2384 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2385 pcrpid = program.pcrPid;
2386 eDebug(", and the text pid is %04x", program.textPid);
2387 tpid = program.textPid;
2392 h.getDecodeDemux(m_decode_demux);
2395 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2397 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2398 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2399 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2400 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2401 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2404 m_teletext_parser = 0;
2405 m_subtitle_parser = 0;
2409 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2416 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2417 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2418 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2420 else // subservice or recording
2422 eServiceReferenceDVB ref;
2423 m_service_handler.getServiceReference(ref);
2424 eServiceReferenceDVB parent = ref.getParentServiceReference();
2429 ePtr<eDVBResourceManager> res_mgr;
2430 if (!eDVBResourceManager::getInstance(res_mgr))
2432 ePtr<iDVBChannelList> db;
2433 if (!res_mgr->getChannelList(db))
2435 ePtr<eDVBService> origService;
2436 if (!db->getService(parent, origService))
2438 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2439 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2445 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2446 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2448 m_decoder->setVideoPID(vpid, vpidtype);
2449 selectAudioStream();
2451 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2452 m_decoder->setSyncPCR(pcrpid);
2454 m_decoder->setSyncPCR(-1);
2456 m_decoder->setTextPID(tpid);
2458 m_teletext_parser->start(program.textPid);
2461 m_decoder->setTrickmode(1);
2464 m_decoder->preroll();
2468 if (vpid > 0 && vpid < 0x2000)
2472 std::string radio_pic;
2473 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2474 m_decoder->setRadioPic(radio_pic);
2477 m_decoder->setAudioChannel(achannel);
2479 /* don't worry about non-existing services, nor pvr services */
2480 if (m_dvb_service && !m_is_pvr)
2482 /* (audio pid will be set in selectAudioTrack */
2483 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2484 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2485 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2486 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2489 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2492 void eDVBServicePlay::loadCuesheet()
2494 std::string filename = m_reference.path + ".cuts";
2496 m_cue_entries.clear();
2498 FILE *f = fopen(filename.c_str(), "rb");
2502 eDebug("loading cuts..");
2505 unsigned long long where;
2508 if (!fread(&where, sizeof(where), 1, f))
2510 if (!fread(&what, sizeof(what), 1, f))
2513 #if BYTE_ORDER == LITTLE_ENDIAN
2514 where = bswap_64(where);
2521 m_cue_entries.insert(cueEntry(where, what));
2524 eDebug("%d entries", m_cue_entries.size());
2526 eDebug("cutfile not found!");
2528 m_cuesheet_changed = 0;
2529 cutlistToCuesheet();
2530 m_event((iPlayableService*)this, evCuesheetChanged);
2533 void eDVBServicePlay::saveCuesheet()
2535 std::string filename = m_reference.path + ".cuts";
2537 FILE *f = fopen(filename.c_str(), "wb");
2541 unsigned long long where;
2544 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2546 #if BYTE_ORDER == BIG_ENDIAN
2549 where = bswap_64(i->where);
2551 what = htonl(i->what);
2552 fwrite(&where, sizeof(where), 1, f);
2553 fwrite(&what, sizeof(what), 1, f);
2559 m_cuesheet_changed = 0;
2562 void eDVBServicePlay::cutlistToCuesheet()
2566 eDebug("no cue sheet");
2571 if (!m_cutlist_enabled)
2573 m_cue->commitSpans();
2574 eDebug("cutlists were disabled");
2578 pts_t in = 0, out = 0, length = 0;
2582 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2586 if (i == m_cue_entries.end())
2589 if (i->what == 0) /* in */
2593 } else if (i->what == 1) /* out */
2595 else /* mark (2) or last play position (3) */
2612 m_cue->addSourceSpan(in, out);
2616 if (i == m_cue_entries.end())
2619 m_cue->commitSpans();
2622 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2624 if (m_subtitle_widget)
2625 disableSubtitles(parent);
2628 int tuplesize = PyTuple_Size(tuple);
2631 if (!PyTuple_Check(tuple))
2637 entry = PyTuple_GET_ITEM(tuple, 0);
2639 if (!PyInt_Check(entry))
2642 type = PyInt_AsLong(entry);
2644 if (type == 1) // teletext subtitles
2646 int page, magazine, pid;
2650 if (!m_teletext_parser)
2652 eDebug("enable teletext subtitles.. no parser !!!");
2656 entry = PyTuple_GET_ITEM(tuple, 1);
2657 if (!PyInt_Check(entry))
2659 pid = PyInt_AsLong(entry);
2661 entry = PyTuple_GET_ITEM(tuple, 2);
2662 if (!PyInt_Check(entry))
2664 page = PyInt_AsLong(entry);
2666 entry = PyTuple_GET_ITEM(tuple, 3);
2667 if (!PyInt_Check(entry))
2669 magazine = PyInt_AsLong(entry);
2671 m_subtitle_widget = new eSubtitleWidget(parent);
2672 m_subtitle_widget->resize(parent->size()); /* full size */
2673 m_teletext_parser->setPageAndMagazine(page, magazine);
2675 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2679 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2680 if (!m_subtitle_parser)
2682 eDebug("enable dvb subtitles.. no parser !!!");
2688 entry = PyTuple_GET_ITEM(tuple, 1);
2689 if (!PyInt_Check(entry))
2691 pid = PyInt_AsLong(entry);
2693 entry = PyTuple_GET_ITEM(tuple, 2);
2694 if (!PyInt_Check(entry))
2696 composition_page_id = PyInt_AsLong(entry);
2698 entry = PyTuple_GET_ITEM(tuple, 3);
2699 if (!PyInt_Check(entry))
2701 ancillary_page_id = PyInt_AsLong(entry);
2703 m_subtitle_widget = new eSubtitleWidget(parent);
2704 m_subtitle_widget->resize(parent->size()); /* full size */
2705 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2707 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2713 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2714 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2715 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2719 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2721 delete m_subtitle_widget;
2722 m_subtitle_widget = 0;
2723 if (m_subtitle_parser)
2725 m_subtitle_parser->stop();
2726 m_dvb_subtitle_pages.clear();
2728 if (m_teletext_parser)
2730 m_teletext_parser->setPageAndMagazine(-1, -1);
2731 m_subtitle_pages.clear();
2734 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2738 PyObject *eDVBServicePlay::getCachedSubtitle()
2742 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2745 unsigned int data = (unsigned int)tmp;
2746 int pid = (data&0xFFFF0000)>>16;
2747 ePyObject tuple = PyTuple_New(4);
2748 eDVBServicePMTHandler::program program;
2749 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2750 if (!h.getProgramInfo(program))
2752 if (program.textPid==pid) // teletext
2753 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2755 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2756 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2757 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2758 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2766 PyObject *eDVBServicePlay::getSubtitleList()
2768 if (!m_teletext_parser)
2771 ePyObject l = PyList_New(0);
2772 std::set<int> added_ttx_pages;
2774 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2775 m_teletext_parser->m_found_subtitle_pages;
2777 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2778 eDVBServicePMTHandler::program program;
2779 if (h.getProgramInfo(program))
2780 eDebug("getting program info failed.");
2783 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2784 it != program.subtitleStreams.end(); ++it)
2786 switch(it->subtitling_type)
2788 case 0x01: // ebu teletext subtitles
2790 int page_number = it->teletext_page_number & 0xFF;
2791 int magazine_number = it->teletext_magazine_number & 7;
2792 int hash = magazine_number << 8 | page_number;
2793 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2795 ePyObject tuple = PyTuple_New(5);
2796 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2797 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2798 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2799 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2800 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2801 PyList_Append(l, tuple);
2803 added_ttx_pages.insert(hash);
2808 case 0x20 ... 0x23: // dvb subtitles
2810 ePyObject tuple = PyTuple_New(5);
2811 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2812 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2813 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2814 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2815 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2816 PyList_Insert(l, 0, tuple);
2824 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2825 it != subs.end(); ++it)
2827 int page_number = it->teletext_page_number & 0xFF;
2828 int magazine_number = it->teletext_magazine_number & 7;
2829 int hash = magazine_number << 8 | page_number;
2830 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2832 ePyObject tuple = PyTuple_New(5);
2833 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2834 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2835 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2836 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2837 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2838 PyList_Append(l, tuple);
2846 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2848 if (m_subtitle_widget)
2852 m_decoder->getPTS(0, pos);
2853 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2854 m_subtitle_pages.push_back(page);
2855 checkSubtitleTiming();
2859 void eDVBServicePlay::checkSubtitleTiming()
2861 eDebug("checkSubtitleTiming");
2862 if (!m_subtitle_widget)
2866 enum { TELETEXT, DVB } type;
2867 eDVBTeletextSubtitlePage page;
2868 eDVBSubtitlePage dvb_page;
2870 if (!m_subtitle_pages.empty())
2872 page = m_subtitle_pages.front();
2874 show_time = page.m_pts;
2876 else if (!m_dvb_subtitle_pages.empty())
2878 dvb_page = m_dvb_subtitle_pages.front();
2880 show_time = dvb_page.m_show_time;
2888 m_decoder->getPTS(0, pos);
2890 eDebug("%lld %lld", pos, show_time);
2891 int diff = show_time - pos;
2894 eDebug("[late (%d ms)]", -diff / 90);
2897 // if (diff > 900000)
2899 // eDebug("[invalid]");
2905 if (type == TELETEXT)
2907 eDebug("display teletext subtitle page %lld", show_time);
2908 m_subtitle_widget->setPage(page);
2909 m_subtitle_pages.pop_front();
2913 eDebug("display dvb subtitle Page %lld", show_time);
2914 m_subtitle_widget->setPage(dvb_page);
2915 m_dvb_subtitle_pages.pop_front();
2919 eDebug("start subtitle delay %d", diff / 90);
2920 m_subtitle_sync_timer->start(diff / 90, 1);
2926 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2928 if (m_subtitle_widget)
2932 m_decoder->getPTS(0, pos);
2933 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2934 m_dvb_subtitle_pages.push_back(p);
2935 checkSubtitleTiming();
2939 int eDVBServicePlay::getAC3Delay()
2942 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2944 return m_decoder->getAC3Delay();
2949 int eDVBServicePlay::getPCMDelay()
2952 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2954 return m_decoder->getPCMDelay();
2959 void eDVBServicePlay::setAC3Delay(int delay)
2962 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2964 m_decoder->setAC3Delay(delay);
2967 void eDVBServicePlay::setPCMDelay(int delay)
2970 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2972 m_decoder->setPCMDelay(delay);
2975 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2977 switch(event.type) {
2978 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2979 m_event((iPlayableService*)this, evVideoSizeChanged);
2981 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2982 m_event((iPlayableService*)this, evVideoFramerateChanged);
2984 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2985 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2992 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2998 PyObject *eDVBServicePlay::getStreamingData()
3000 eDVBServicePMTHandler::program program;
3001 if (m_service_handler.getProgramInfo(program))
3006 ePyObject r = program.createPythonObject();
3007 ePtr<iDVBDemux> demux;
3008 if (!m_service_handler.getDataDemux(demux))
3011 if (!demux->getCADemuxID(demux_id))
3012 PutToDict(r, "demux", demux_id);
3019 DEFINE_REF(eDVBServicePlay)
3021 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3025 case iServiceInformation::sTransponderData:
3026 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3030 return iStaticServiceInformation::getInfoObject(ref, w);
3033 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");