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 #define TSPATH "/media/hdd"
36 class eStaticServiceDVBInformation: public iStaticServiceInformation
38 DECLARE_REF(eStaticServiceDVBInformation);
40 RESULT getName(const eServiceReference &ref, std::string &name);
41 int getLength(const eServiceReference &ref);
42 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
43 PyObject *getInfoObject(const eServiceReference &ref, int);
46 DEFINE_REF(eStaticServiceDVBInformation);
48 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
50 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
51 if ( !ref.name.empty() )
53 if (service.getParentTransportStreamID().get()) // linkage subservice
55 ePtr<iServiceHandler> service_center;
56 if (!eServiceCenter::getInstance(service_center))
58 eServiceReferenceDVB parent = service;
59 parent.setTransportStreamID( service.getParentTransportStreamID() );
60 parent.setServiceID( service.getParentServiceID() );
61 parent.setParentTransportStreamID(eTransportStreamID(0));
62 parent.setParentServiceID(eServiceID(0));
64 ePtr<iStaticServiceInformation> service_info;
65 if (!service_center->info(parent, service_info))
67 if (!service_info->getName(parent, name))
68 name=buildShortName(name) + " - ";
81 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
86 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
88 ePtr<eDVBResourceManager> res_mgr;
89 if ( eDVBResourceManager::getInstance( res_mgr ) )
90 eDebug("isPlayable... no res manager!!");
93 eDVBChannelID chid, chid_ignore;
94 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
95 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
96 return res_mgr->canAllocateChannel(chid, chid_ignore);
101 static void PutToDict(ePyObject &dict, const char*key, long value)
103 ePyObject item = PyString_FromFormat("%d", value);
106 if (PyDict_SetItemString(dict, key, item))
107 eDebug("put %s to dict failed", key);
111 eDebug("could not create PyObject for %s", key);
114 extern void PutToDict(ePyObject &dict, const char*key, const char *value);
116 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
119 PutToDict(dict, "type", "Satellite");
120 PutToDict(dict, "frequency", feparm.frequency);
121 PutToDict(dict, "symbolrate", feparm.symbol_rate);
122 PutToDict(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 PutToDict(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 PutToDict(dict, "frequency", feparm.frequency);
279 PutToDict(dict, "symbolrate", feparm.symbol_rate);
280 switch (feparm.modulation)
282 case eDVBFrontendParametersCable::Modulation::QAM16: tmp="QAM16"; break;
283 case eDVBFrontendParametersCable::Modulation::QAM32: tmp="QAM32"; break;
284 case eDVBFrontendParametersCable::Modulation::QAM64: tmp="QAM64"; break;
285 case eDVBFrontendParametersCable::Modulation::QAM128: tmp="QAM128"; break;
286 case eDVBFrontendParametersCable::Modulation::QAM256: tmp="QAM256"; break;
288 case eDVBFrontendParametersCable::Modulation::Auto: tmp="AUTO"; break;
290 PutToDict(dict, "modulation", tmp);
291 switch (feparm.inversion)
293 case eDVBFrontendParametersCable::Inversion::On: tmp="ON"; break;
294 case eDVBFrontendParametersCable::Inversion::Off: tmp="OFF"; break;
296 case eDVBFrontendParametersCable::Inversion::Unknown: tmp="AUTO"; break;
298 PutToDict(dict, "inversion", tmp);
299 switch (feparm.fec_inner)
301 case eDVBFrontendParametersCable::FEC::fNone: tmp="NONE"; break;
302 case eDVBFrontendParametersCable::FEC::f1_2: tmp="1/2"; break;
303 case eDVBFrontendParametersCable::FEC::f2_3: tmp="2/3"; break;
304 case eDVBFrontendParametersCable::FEC::f3_4: tmp="3/4"; break;
305 case eDVBFrontendParametersCable::FEC::f5_6: tmp="5/6"; break;
306 case eDVBFrontendParametersCable::FEC::f7_8: tmp="7/8"; break;
307 case eDVBFrontendParametersCable::FEC::f8_9: tmp="8/9"; break;
309 case eDVBFrontendParametersCable::FEC::fAuto: tmp="AUTO"; break;
311 PutToDict(dict, "fec inner", tmp);
314 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
316 if (r.type == eServiceReference::idDVB)
318 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
321 case iServiceInformation::sTransponderData:
323 ePtr<eDVBResourceManager> res;
324 if (!eDVBResourceManager::getInstance(res))
326 ePtr<iDVBChannelList> db;
327 if (!res->getChannelList(db))
330 ref.getChannelID(chid);
331 ePtr<iDVBFrontendParameters> feparm;
332 if (!db->getChannelFrontendData(chid, feparm))
335 if (!feparm->getSystem(system))
337 ePyObject dict = PyDict_New();
340 case iDVBFrontend::feSatellite:
342 eDVBFrontendParametersSatellite s;
344 PutSatelliteDataToDict(dict, s);
347 case iDVBFrontend::feTerrestrial:
349 eDVBFrontendParametersTerrestrial t;
351 PutTerrestrialDataToDict(dict, t);
354 case iDVBFrontend::feCable:
356 eDVBFrontendParametersCable c;
358 PutCableDataToDict(dict, c);
362 eDebug("unknown frontend type %d", system);
377 DEFINE_REF(eStaticServiceDVBBouquetInformation);
379 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
381 ePtr<iDVBChannelList> db;
382 ePtr<eDVBResourceManager> res;
385 if ((err = eDVBResourceManager::getInstance(res)) != 0)
387 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
390 if ((err = res->getChannelList(db)) != 0)
392 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
397 if ((err = db->getBouquet(ref, bouquet)) != 0)
399 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
403 if ( bouquet && bouquet->m_bouquet_name.length() )
405 name = bouquet->m_bouquet_name;
412 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
414 if (ref.flags & eServiceReference::isGroup)
416 ePtr<iDVBChannelList> db;
417 ePtr<eDVBResourceManager> res;
419 if (eDVBResourceManager::getInstance(res))
421 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
425 if (res->getChannelList(db))
427 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
432 if (db->getBouquet(ref, bouquet))
434 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
438 int prio_order = eDVBFrontend::getTypePriorityOrder();
440 eDVBChannelID chid, chid_ignore;
441 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
442 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
444 static unsigned char prio_map[6][3] = {
445 { 3, 2, 1 }, // -S -C -T
446 { 3, 1, 2 }, // -S -T -C
447 { 2, 3, 1 }, // -C -S -T
448 { 1, 3, 2 }, // -C -T -S
449 { 1, 2, 3 }, // -T -C -S
450 { 2, 1, 3 } // -T -S -C
452 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
453 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
458 case 30000: // cached DVB-T channel
459 case 1: // DVB-T frontend
460 tmp = prio_map[prio_order][2];
462 case 40000: // cached DVB-C channel
464 tmp = prio_map[prio_order][1];
467 tmp = prio_map[prio_order][0];
472 m_playable_service = *it;
479 m_playable_service = eServiceReference();
483 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
488 #include <lib/dvb/epgcache.h>
490 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
492 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
495 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
497 DECLARE_REF(eStaticServiceDVBPVRInformation);
498 eServiceReference m_ref;
499 eDVBMetaParser m_parser;
501 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
502 RESULT getName(const eServiceReference &ref, std::string &name);
503 int getLength(const eServiceReference &ref);
504 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
505 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
506 int getInfo(const eServiceReference &ref, int w);
507 std::string getInfoString(const eServiceReference &ref,int w);
510 DEFINE_REF(eStaticServiceDVBPVRInformation);
512 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
515 m_parser.parseFile(ref.path);
518 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
520 ASSERT(ref == m_ref);
521 if (m_parser.m_name.size())
522 name = m_parser.m_name;
526 size_t n = name.rfind('/');
527 if (n != std::string::npos)
528 name = name.substr(n + 1);
533 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
535 ASSERT(ref == m_ref);
539 if (tstools.openFile(ref.path.c_str()))
543 if (tstools.calcLen(len))
549 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
553 case iServiceInformation::sDescription:
554 return iServiceInformation::resIsString;
555 case iServiceInformation::sServiceref:
556 return iServiceInformation::resIsString;
557 case iServiceInformation::sTimeCreate:
558 if (m_parser.m_time_create)
559 return m_parser.m_time_create;
561 return iServiceInformation::resNA;
563 return iServiceInformation::resNA;
567 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
571 case iServiceInformation::sDescription:
572 return m_parser.m_description;
573 case iServiceInformation::sServiceref:
574 return m_parser.m_ref.toString();
575 case iServiceInformation::sTags:
576 return m_parser.m_tags;
582 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
584 if (!ref.path.empty())
586 ePtr<eServiceEvent> event = new eServiceEvent;
587 std::string filename = ref.path;
588 filename.erase(filename.length()-2, 2);
590 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
600 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
602 DECLARE_REF(eDVBPVRServiceOfflineOperations);
603 eServiceReferenceDVB m_ref;
605 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
607 RESULT deleteFromDisk(int simulate);
608 RESULT getListOfFilenames(std::list<std::string> &);
611 DEFINE_REF(eDVBPVRServiceOfflineOperations);
613 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
617 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
623 std::list<std::string> res;
624 if (getListOfFilenames(res))
627 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
629 eDebug("FATAL !! can't get background file eraser");
631 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
633 eDebug("Removing %s...", i->c_str());
635 eraser->erase(i->c_str());
637 ::unlink(i->c_str());
644 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
647 res.push_back(m_ref.path);
649 // handling for old splitted recordings (enigma 1)
654 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
656 if (stat(buf, &s) < 0)
661 res.push_back(m_ref.path + ".meta");
662 res.push_back(m_ref.path + ".ap");
663 res.push_back(m_ref.path + ".cuts");
664 std::string tmp = m_ref.path;
665 tmp.erase(m_ref.path.length()-3);
666 res.push_back(tmp + ".eit");
670 DEFINE_REF(eServiceFactoryDVB)
672 eServiceFactoryDVB::eServiceFactoryDVB()
674 ePtr<eServiceCenter> sc;
676 eServiceCenter::getPrivInstance(sc);
679 std::list<std::string> extensions;
680 extensions.push_back("ts");
681 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
684 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
685 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
688 eServiceFactoryDVB::~eServiceFactoryDVB()
690 ePtr<eServiceCenter> sc;
692 eServiceCenter::getPrivInstance(sc);
694 sc->removeServiceFactory(eServiceFactoryDVB::id);
697 DEFINE_REF(eDVBServiceList);
699 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
703 eDVBServiceList::~eDVBServiceList()
707 RESULT eDVBServiceList::startQuery()
709 ePtr<iDVBChannelList> db;
710 ePtr<eDVBResourceManager> res;
713 if ((err = eDVBResourceManager::getInstance(res)) != 0)
715 eDebug("no resource manager");
718 if ((err = res->getChannelList(db)) != 0)
720 eDebug("no channel list");
724 ePtr<eDVBChannelQuery> q;
726 if (!m_parent.path.empty())
728 eDVBChannelQuery::compile(q, m_parent.path);
731 eDebug("compile query failed");
736 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
738 eDebug("startQuery failed");
745 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
747 eServiceReferenceDVB ref;
752 while (!m_query->getNextResult(ref))
756 list.sort(iListableServiceCompare(this));
761 // The first argument of this function is a format string to specify the order and
762 // the content of the returned list
763 // useable format options are
764 // R = Service Reference (as swig object .. this is very slow)
765 // S = Service Reference (as python string object .. same as ref.toString())
766 // C = Service Reference (as python string object .. same as ref.toCompareString())
767 // N = Service Name (as python string object)
768 // n = Short Service Name (short name brakets used) (as python string object)
769 // when exactly one return value per service is selected in the format string,
770 // then each value is directly a list entry
771 // when more than one value is returned per service, then the list is a list of
773 // unknown format string chars are returned as python None values !
774 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
777 std::list<eServiceReference> tmplist;
780 if (!format || !(retcount=strlen(format)))
781 format = "R"; // just return service reference swig object ...
783 if (!getContent(tmplist, sorted))
785 int services=tmplist.size();
786 ePtr<iStaticServiceInformation> sptr;
787 eServiceCenterPtr service_center;
789 if (strchr(format, 'N') || strchr(format, 'n'))
790 eServiceCenter::getPrivInstance(service_center);
792 ret = PyList_New(services);
793 std::list<eServiceReference>::iterator it(tmplist.begin());
795 for (int cnt=0; cnt < services; ++cnt)
797 eServiceReference &ref=*it++;
798 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
799 for (int i=0; i < retcount; ++i)
804 case 'R': // service reference (swig)object
805 tmp = NEW_eServiceReference(ref);
807 case 'C': // service reference compare string
808 tmp = PyString_FromString(ref.toCompareString().c_str());
810 case 'S': // service reference string
811 tmp = PyString_FromString(ref.toString().c_str());
813 case 'N': // service name
816 service_center->info(ref, sptr);
820 sptr->getName(ref, name);
822 // filter short name brakets
824 while((pos = name.find("\xc2\x86")) != std::string::npos)
826 while((pos = name.find("\xc2\x87")) != std::string::npos)
830 tmp = PyString_FromString(name.c_str());
834 tmp = PyString_FromString("<n/a>");
836 case 'n': // short service name
839 service_center->info(ref, sptr);
843 sptr->getName(ref, name);
844 name = buildShortName(name);
846 tmp = PyString_FromString(name.c_str());
850 tmp = PyString_FromString("<n/a>");
863 PyTuple_SET_ITEM(tuple, i, tmp);
865 PyList_SET_ITEM(ret, cnt, tmp);
869 PyList_SET_ITEM(ret, cnt, tuple);
872 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
875 RESULT eDVBServiceList::getNext(eServiceReference &ref)
880 return m_query->getNextResult((eServiceReferenceDVB&)ref);
883 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
885 if (m_parent.flags & eServiceReference::canDescent) // bouquet
887 ePtr<iDVBChannelList> db;
888 ePtr<eDVBResourceManager> resm;
890 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
893 if (db->getBouquet(m_parent, m_bouquet) != 0)
904 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
908 return m_bouquet->addService(ref, before);
911 RESULT eDVBServiceList::removeService(eServiceReference &ref)
915 return m_bouquet->removeService(ref);
918 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
922 return m_bouquet->moveService(ref, pos);
925 RESULT eDVBServiceList::flushChanges()
929 return m_bouquet->flushChanges();
932 RESULT eDVBServiceList::setListName(const std::string &name)
936 return m_bouquet->setListName(name);
939 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
941 ePtr<eDVBService> service;
942 int r = lookupService(service, ref);
945 // check resources...
946 ptr = new eDVBServicePlay(ref, service);
950 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
952 if (ref.path.empty())
954 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
963 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
965 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
966 if (list->startQuery())
976 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
978 /* is a listable service? */
979 if (ref.flags & eServiceReference::canDescent) // bouquet
981 if ( !ref.name.empty() ) // satellites or providers list
982 ptr = m_StaticServiceDVBInfo;
983 else // a dvb bouquet
984 ptr = m_StaticServiceDVBBouquetInfo;
986 else if (!ref.path.empty()) /* do we have a PVR service? */
987 ptr = new eStaticServiceDVBPVRInformation(ref);
988 else // normal dvb service
990 ePtr<eDVBService> service;
991 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
992 ptr = m_StaticServiceDVBInfo;
994 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
1000 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
1002 if (ref.path.empty())
1008 ptr = new eDVBPVRServiceOfflineOperations(ref);
1013 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
1015 // TODO: handle the listing itself
1016 // if (ref.... == -1) .. return "... bouquets ...";
1017 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
1019 ePtr<iDVBChannelList> db;
1020 ePtr<eDVBResourceManager> res;
1023 if ((err = eDVBResourceManager::getInstance(res)) != 0)
1025 eDebug("no resource manager");
1028 if ((err = res->getChannelList(db)) != 0)
1030 eDebug("no channel list");
1034 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
1035 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
1037 eDebug("getService failed!");
1044 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
1045 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
1047 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
1049 m_is_pvr = !m_reference.path.empty();
1051 m_timeshift_enabled = m_timeshift_active = 0;
1054 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
1055 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
1056 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
1058 m_cuesheet_changed = 0;
1059 m_cutlist_enabled = 1;
1061 m_subtitle_widget = 0;
1065 m_subtitle_sync_timer = eTimer::create(eApp);
1067 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
1070 eDVBServicePlay::~eDVBServicePlay()
1072 delete m_subtitle_widget;
1075 void eDVBServicePlay::gotNewEvent()
1079 ePtr<eServiceEvent> m_event_now, m_event_next;
1080 getEvent(m_event_now, 0);
1081 getEvent(m_event_next, 1);
1084 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1086 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1088 m_event((iPlayableService*)this, evUpdatedEventInfo);
1091 void eDVBServicePlay::serviceEvent(int event)
1093 m_tune_state = event;
1097 case eDVBServicePMTHandler::eventTuned:
1099 ePtr<iDVBDemux> m_demux;
1100 if (!m_service_handler.getDataDemux(m_demux))
1102 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1103 int sid = ref.getParentServiceID().get();
1105 sid = ref.getServiceID().get();
1106 if ( ref.getParentTransportStreamID().get() &&
1107 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1108 m_event_handler.startOther(m_demux, sid);
1110 m_event_handler.start(m_demux, sid);
1112 m_event((iPlayableService*)this, evTunedIn);
1115 case eDVBServicePMTHandler::eventNoResources:
1116 case eDVBServicePMTHandler::eventNoPAT:
1117 case eDVBServicePMTHandler::eventNoPATEntry:
1118 case eDVBServicePMTHandler::eventNoPMT:
1119 case eDVBServicePMTHandler::eventTuneFailed:
1120 case eDVBServicePMTHandler::eventMisconfiguration:
1122 eDebug("DVB service failed to tune - error %d", event);
1123 m_event((iPlayableService*)this, evTuneFailed);
1126 case eDVBServicePMTHandler::eventNewProgramInfo:
1128 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1129 if (m_timeshift_enabled)
1130 updateTimeshiftPids();
1131 if (!m_timeshift_active)
1133 if (m_first_program_info && m_is_pvr)
1135 m_first_program_info = 0;
1138 m_event((iPlayableService*)this, evUpdatedInfo);
1141 case eDVBServicePMTHandler::eventEOF:
1142 m_event((iPlayableService*)this, evEOF);
1144 case eDVBServicePMTHandler::eventSOF:
1145 m_event((iPlayableService*)this, evSOF);
1150 void eDVBServicePlay::serviceEventTimeshift(int event)
1154 case eDVBServicePMTHandler::eventNewProgramInfo:
1155 if (m_timeshift_active)
1158 case eDVBServicePMTHandler::eventSOF:
1159 m_event((iPlayableService*)this, evSOF);
1161 case eDVBServicePMTHandler::eventEOF:
1162 if ((!m_is_paused) && (m_skipmode >= 0))
1168 RESULT eDVBServicePlay::start()
1171 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1172 two (one for decoding, one for data source), as we must be prepared
1173 to start recording from the data demux. */
1175 m_cue = new eCueSheet();
1177 m_event(this, evStart);
1179 m_first_program_info = 1;
1180 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1181 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1183 /* inject EIT if there is a stored one */
1186 std::string filename = service.path;
1187 filename.erase(filename.length()-2, 2);
1189 ePtr<eServiceEvent> event = new eServiceEvent;
1190 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1192 ePtr<eServiceEvent> empty;
1193 m_event_handler.inject(event, 0);
1194 m_event_handler.inject(empty, 1);
1201 m_event(this, evStart);
1206 RESULT eDVBServicePlay::stop()
1208 /* add bookmark for last play position */
1211 pts_t play_position, length;
1212 if (!getPlayPosition(play_position))
1214 /* remove last position */
1215 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1217 if (i->what == 3) /* current play position */
1219 m_cue_entries.erase(i);
1220 i = m_cue_entries.begin();
1226 if (getLength(length))
1231 int perc = play_position * 100LL / length;
1233 /* only store last play position when between 1% and 99% */
1234 if ((1 < perc) && (perc < 99))
1235 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1237 m_cuesheet_changed = 1;
1241 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1243 m_service_handler_timeshift.free();
1244 m_service_handler.free();
1246 if (m_is_pvr && m_cuesheet_changed)
1249 /* save cuesheet only when main file is accessible. */
1250 if (!::stat(m_reference.path.c_str(), &s))
1253 m_event((iPlayableService*)this, evStopped);
1257 RESULT eDVBServicePlay::setTarget(int target)
1259 m_is_primary = !target;
1263 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1265 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1269 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1271 /* note: we check for timeshift to be enabled,
1272 not neccessary active. if you pause when timeshift
1273 is not active, you should activate it when unpausing */
1274 if ((!m_is_pvr) && (!m_timeshift_enabled))
1284 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1287 return m_decoder->setSlowMotion(ratio);
1292 RESULT eDVBServicePlay::setFastForward(int ratio)
1294 int skipmode, ffratio;
1300 } else if (ratio > 0)
1308 } else // if (ratio < 0)
1314 if (m_skipmode != skipmode)
1316 eDebug("setting cue skipmode to %d", skipmode);
1318 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1321 m_skipmode = skipmode;
1326 return m_decoder->setFastForward(ffratio);
1329 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1331 if (m_is_pvr || m_timeshift_enabled)
1341 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1342 RESULT eDVBServicePlay::getLength(pts_t &len)
1344 ePtr<iDVBPVRChannel> pvr_channel;
1346 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1349 return pvr_channel->getLength(len);
1352 RESULT eDVBServicePlay::pause()
1354 if (!m_is_paused && m_decoder)
1357 return m_decoder->freeze(0);
1362 RESULT eDVBServicePlay::unpause()
1364 if (m_is_paused && m_decoder)
1367 return m_decoder->unfreeze();
1372 RESULT eDVBServicePlay::seekTo(pts_t to)
1374 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1376 if (!m_decode_demux)
1379 ePtr<iDVBPVRChannel> pvr_channel;
1381 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1387 m_cue->seekTo(0, to);
1388 m_dvb_subtitle_pages.clear();
1389 m_subtitle_pages.clear();
1394 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1396 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1398 if (!m_decode_demux)
1401 ePtr<iDVBPVRChannel> pvr_channel;
1403 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1408 /* HACK until we have skip-AP api */
1409 if ((to > 0) && (to < 100))
1417 m_cue->seekTo(mode, to);
1418 m_dvb_subtitle_pages.clear();
1419 m_subtitle_pages.clear();
1423 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1425 ePtr<iDVBPVRChannel> pvr_channel;
1427 if (!m_decode_demux)
1430 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1435 /* if there is a decoder, use audio or video PTS */
1438 r = m_decoder->getPTS(0, pos);
1444 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1447 RESULT eDVBServicePlay::setTrickmode(int trick)
1450 m_decoder->setTrickmode(trick);
1454 RESULT eDVBServicePlay::isCurrentlySeekable()
1456 return m_is_pvr || m_timeshift_active;
1459 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1465 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1471 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1477 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1483 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1489 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1492 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1493 (m_timeshift_enabled || !m_is_pvr))
1495 if (!m_timeshift_enabled)
1497 /* we need enough diskspace */
1499 if (statfs(TSPATH "/.", &fs) < 0)
1501 eDebug("statfs failed!");
1505 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1507 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1517 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1528 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1534 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1540 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1546 RESULT eDVBServicePlay::getName(std::string &name)
1550 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1551 return i->getName(m_reference, name);
1555 m_dvb_service->getName(m_reference, name);
1559 else if (!m_reference.name.empty())
1560 eStaticServiceDVBInformation().getName(m_reference, name);
1562 name = "DVB service";
1566 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1568 return m_event_handler.getEvent(evt, nownext);
1571 static int readMpegProc(char *str, int decoder)
1575 sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
1576 FILE *f = fopen(tmp, "r");
1579 fscanf(f, "%x", &val);
1585 int eDVBServicePlay::getInfo(int w)
1587 eDVBServicePMTHandler::program program;
1590 return resIsPyObject;
1592 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1594 int no_program_info = 0;
1596 if (h.getProgramInfo(program))
1597 no_program_info = 1;
1601 #if HAVE_DVB_API_VERSION >= 3
1603 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1604 return m_videoEventData.height;
1606 return readMpegProc("yres", !m_is_primary);
1608 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1609 return m_videoEventData.width;
1611 return readMpegProc("xres", !m_is_primary);
1613 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventFrameRateChanged)
1614 return m_videoEventData.framerate;
1616 return readMpegProc("framerate", !m_is_primary);
1618 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventProgressiveChanged)
1619 return m_videoEventData.progressive;
1620 return readMpegProc("progressive", !m_is_primary);
1622 #warning "FIXMEE implement sFrameRate, sProgressive, sVideoHeight, sVideoWidth for old DVB API"
1627 #if HAVE_DVB_API_VERSION >= 3
1628 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1629 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1630 else if ((val=readMpegProc("aspect", !m_is_primary)) != -1)
1634 #warning "FIXMEE implement sAspect for old DVB API"
1636 if (no_program_info)
1638 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1640 ePtr<eServiceEvent> evt;
1641 if (!m_event_handler.getEvent(evt, 0))
1643 ePtr<eComponentData> data;
1644 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1646 if ( data->getStreamContent() == 1 )
1648 switch(data->getComponentType())
1651 case 1: // 4:3 SD PAL
1653 case 3: // 16:9 SD PAL
1654 case 4: // > 16:9 PAL
1655 case 5: // 4:3 SD NTSC
1657 case 7: // 16:9 SD NTSC
1658 case 8: // > 16:9 NTSC
1661 case 9: // 4:3 HD PAL
1663 case 0xB: // 16:9 HD PAL
1664 case 0xC: // > 16:9 HD PAL
1665 case 0xD: // 4:3 HD NTSC
1667 case 0xF: // 16:9 HD NTSC
1668 case 0x10: // > 16:9 HD PAL
1669 return data->getComponentType();
1677 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1678 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1679 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1680 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1681 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1682 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1683 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1684 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1685 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1686 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1687 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1688 case sProvider: if (!m_dvb_service) return -1; return -2;
1689 case sServiceref: return resIsString;
1690 case sDVBState: return m_tune_state;
1696 std::string eDVBServicePlay::getInfoString(int w)
1701 if (!m_dvb_service) return "";
1702 return m_dvb_service->m_provider_name;
1704 return m_reference.toString();
1708 return iServiceInformation::getInfoString(w);
1711 PyObject *eDVBServicePlay::getInfoObject(int w)
1716 return m_service_handler.getCaIds();
1717 case sTransponderData:
1718 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1722 return iServiceInformation::getInfoObject(w);
1725 int eDVBServicePlay::getNumberOfTracks()
1727 eDVBServicePMTHandler::program program;
1728 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1729 if (h.getProgramInfo(program))
1731 return program.audioStreams.size();
1734 int eDVBServicePlay::getCurrentTrack()
1736 eDVBServicePMTHandler::program program;
1737 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1738 if (h.getProgramInfo(program))
1741 int max = program.audioStreams.size();
1744 for (i = 0; i < max; ++i)
1745 if (program.audioStreams[i].pid == m_current_audio_pid)
1751 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1753 int ret = selectAudioStream(i);
1755 if (m_decoder->start())
1761 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1763 eDVBServicePMTHandler::program program;
1764 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1766 if (h.getProgramInfo(program))
1769 if (i >= program.audioStreams.size())
1772 info.m_pid = program.audioStreams[i].pid;
1774 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1775 info.m_description = "MPEG";
1776 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1777 info.m_description = "AC3";
1778 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1779 info.m_description = "AAC";
1780 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1781 info.m_description = "DTS";
1783 info.m_description = "???";
1785 if (program.audioStreams[i].component_tag != -1)
1787 ePtr<eServiceEvent> evt;
1788 if (!m_event_handler.getEvent(evt, 0))
1790 ePtr<eComponentData> data;
1791 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1792 info.m_language = data->getText();
1796 if (info.m_language.empty())
1797 info.m_language = program.audioStreams[i].language_code;
1802 int eDVBServicePlay::selectAudioStream(int i)
1804 eDVBServicePMTHandler::program program;
1805 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1807 if (h.getProgramInfo(program))
1810 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1818 stream = program.defaultAudioStream;
1820 int apid = -1, apidtype = -1;
1822 if (((unsigned int)stream) < program.audioStreams.size())
1824 apid = program.audioStreams[stream].pid;
1825 apidtype = program.audioStreams[stream].type;
1828 m_current_audio_pid = apid;
1830 if (m_decoder->setAudioPID(apid, apidtype))
1832 eDebug("set audio pid failed");
1836 /* 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 */
1837 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1840 ePtr<iDVBDemux> data_demux;
1841 if (!h.getDataDemux(data_demux))
1843 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1844 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1848 /* if we decided that we need one, update the pid */
1850 m_rds_decoder->start(apid);
1852 /* store new pid as default only when:
1853 a.) we have an entry in the service db for the current service,
1854 b.) we are not playing back something,
1855 c.) we are not selecting the default entry. (we wouldn't change
1856 anything in the best case, or destroy the default setting in
1857 case the real default is not yet available.)
1859 if (m_dvb_service && !m_is_pvr && ((i != -1)
1860 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1862 if (apidtype == eDVBAudio::aMPEG)
1864 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1865 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1869 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1870 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1874 h.resetCachedProgram();
1879 int eDVBServicePlay::getCurrentChannel()
1881 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1884 RESULT eDVBServicePlay::selectChannel(int i)
1886 if (i < LEFT || i > RIGHT || i == STEREO)
1889 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1891 m_decoder->setAudioChannel(i);
1895 std::string eDVBServicePlay::getText(int x)
1901 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1903 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1908 void eDVBServicePlay::rdsDecoderEvent(int what)
1912 case eDVBRdsDecoder::RadioTextChanged:
1913 m_event((iPlayableService*)this, evUpdatedRadioText);
1915 case eDVBRdsDecoder::RtpTextChanged:
1916 m_event((iPlayableService*)this, evUpdatedRtpText);
1918 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1919 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1921 case eDVBRdsDecoder::RecvRassSlidePic:
1922 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1927 void eDVBServicePlay::showRassSlidePicture()
1933 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1934 if (rass_slide_pic.length())
1935 m_decoder->showSinglePic(rass_slide_pic.c_str());
1937 eDebug("empty filename for rass slide picture received!!");
1940 eDebug("no MPEG Decoder to show iframes avail");
1943 eDebug("showRassSlidePicture called.. but not decoder");
1946 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1952 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1953 if (rass_interactive_pic.length())
1954 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1956 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1959 eDebug("no MPEG Decoder to show iframes avail");
1962 eDebug("showRassInteractivePic called.. but not decoder");
1965 ePyObject eDVBServicePlay::getRassInteractiveMask()
1968 return m_rds_decoder->getRassPictureMask();
1972 int eDVBServiceBase::getFrontendInfo(int w)
1974 eUsePtr<iDVBChannel> channel;
1975 if(m_service_handler.getChannel(channel))
1977 ePtr<iDVBFrontend> fe;
1978 if(channel->getFrontend(fe))
1980 return fe->readFrontendData(w);
1983 PyObject *eDVBServiceBase::getFrontendData()
1985 ePyObject ret = PyDict_New();
1988 eUsePtr<iDVBChannel> channel;
1989 if(!m_service_handler.getChannel(channel))
1991 ePtr<iDVBFrontend> fe;
1992 if(!channel->getFrontend(fe))
1993 fe->getFrontendData(ret);
2001 PyObject *eDVBServiceBase::getFrontendStatus()
2003 ePyObject ret = PyDict_New();
2006 eUsePtr<iDVBChannel> channel;
2007 if(!m_service_handler.getChannel(channel))
2009 ePtr<iDVBFrontend> fe;
2010 if(!channel->getFrontend(fe))
2011 fe->getFrontendStatus(ret);
2019 PyObject *eDVBServiceBase::getTransponderData(bool original)
2021 ePyObject ret = PyDict_New();
2024 eUsePtr<iDVBChannel> channel;
2025 if(!m_service_handler.getChannel(channel))
2027 ePtr<iDVBFrontend> fe;
2028 if(!channel->getFrontend(fe))
2030 fe->getTransponderData(ret, original);
2031 ePtr<iDVBFrontendParameters> feparm;
2032 channel->getCurrentFrontendParameters(feparm);
2035 eDVBFrontendParametersSatellite osat;
2036 if (!feparm->getDVBS(osat))
2038 void PutToDict(ePyObject &, const char*, long);
2039 void PutToDict(ePyObject &, const char*, const char*);
2040 PutToDict(ret, "orbital_position", osat.orbital_position);
2041 const char *tmp = "UNKNOWN";
2042 switch(osat.polarisation)
2044 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2045 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2046 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2047 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2050 PutToDict(ret, "polarization", tmp);
2061 PyObject *eDVBServiceBase::getAll(bool original)
2063 ePyObject ret = getTransponderData(original);
2066 eUsePtr<iDVBChannel> channel;
2067 if(!m_service_handler.getChannel(channel))
2069 ePtr<iDVBFrontend> fe;
2070 if(!channel->getFrontend(fe))
2072 fe->getFrontendData(ret);
2073 fe->getFrontendStatus(ret);
2080 int eDVBServicePlay::getNumberOfSubservices()
2082 ePtr<eServiceEvent> evt;
2083 if (!m_event_handler.getEvent(evt, 0))
2084 return evt->getNumOfLinkageServices();
2088 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2090 ePtr<eServiceEvent> evt;
2091 if (!m_event_handler.getEvent(evt, 0))
2093 if (!evt->getLinkageService(sub, m_reference, n))
2096 sub.type=eServiceReference::idInvalid;
2100 RESULT eDVBServicePlay::startTimeshift()
2102 ePtr<iDVBDemux> demux;
2104 eDebug("Start timeshift!");
2106 if (m_timeshift_enabled)
2109 /* start recording with the data demux. */
2110 if (m_service_handler.getDataDemux(demux))
2113 demux->createTSRecorder(m_record);
2117 char templ[]=TSPATH "/timeshift.XXXXXX";
2118 m_timeshift_fd = mkstemp(templ);
2119 m_timeshift_file = templ;
2121 eDebug("recording to %s", templ);
2123 if (m_timeshift_fd < 0)
2129 m_record->setTargetFD(m_timeshift_fd);
2131 m_timeshift_enabled = 1;
2133 updateTimeshiftPids();
2139 RESULT eDVBServicePlay::stopTimeshift()
2141 if (!m_timeshift_enabled)
2146 m_timeshift_enabled = 0;
2151 close(m_timeshift_fd);
2152 eDebug("remove timeshift file");
2153 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2158 int eDVBServicePlay::isTimeshiftActive()
2160 return m_timeshift_enabled && m_timeshift_active;
2163 RESULT eDVBServicePlay::activateTimeshift()
2165 if (!m_timeshift_enabled)
2168 if (!m_timeshift_active)
2170 switchToTimeshift();
2177 PyObject *eDVBServicePlay::getCutList()
2179 ePyObject list = PyList_New(0);
2181 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2183 ePyObject tuple = PyTuple_New(2);
2184 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2185 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2186 PyList_Append(list, tuple);
2193 void eDVBServicePlay::setCutList(ePyObject list)
2195 if (!PyList_Check(list))
2197 int size = PyList_Size(list);
2200 m_cue_entries.clear();
2202 for (i=0; i<size; ++i)
2204 ePyObject tuple = PyList_GET_ITEM(list, i);
2205 if (!PyTuple_Check(tuple))
2207 eDebug("non-tuple in cutlist");
2210 if (PyTuple_Size(tuple) != 2)
2212 eDebug("cutlist entries need to be a 2-tuple");
2215 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2216 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2218 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2221 pts_t pts = PyLong_AsLongLong(ppts);
2222 int type = PyInt_AsLong(ptype);
2223 m_cue_entries.insert(cueEntry(pts, type));
2224 eDebug("adding %08llx, %d", pts, type);
2226 m_cuesheet_changed = 1;
2228 cutlistToCuesheet();
2229 m_event((iPlayableService*)this, evCuesheetChanged);
2232 void eDVBServicePlay::setCutListEnable(int enable)
2234 m_cutlist_enabled = enable;
2235 cutlistToCuesheet();
2238 void eDVBServicePlay::updateTimeshiftPids()
2243 eDVBServicePMTHandler::program program;
2244 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2246 if (h.getProgramInfo(program))
2250 std::set<int> pids_to_record;
2251 pids_to_record.insert(0); // PAT
2252 if (program.pmtPid != -1)
2253 pids_to_record.insert(program.pmtPid); // PMT
2255 if (program.textPid != -1)
2256 pids_to_record.insert(program.textPid); // Videotext
2258 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2259 i(program.videoStreams.begin());
2260 i != program.videoStreams.end(); ++i)
2261 pids_to_record.insert(i->pid);
2263 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2264 i(program.audioStreams.begin());
2265 i != program.audioStreams.end(); ++i)
2266 pids_to_record.insert(i->pid);
2268 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2269 i(program.subtitleStreams.begin());
2270 i != program.subtitleStreams.end(); ++i)
2271 pids_to_record.insert(i->pid);
2273 std::set<int> new_pids, obsolete_pids;
2275 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2276 m_pids_active.begin(), m_pids_active.end(),
2277 std::inserter(new_pids, new_pids.begin()));
2279 std::set_difference(
2280 m_pids_active.begin(), m_pids_active.end(),
2281 pids_to_record.begin(), pids_to_record.end(),
2282 std::inserter(new_pids, new_pids.begin())
2285 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2286 m_record->addPID(*i);
2288 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2289 m_record->removePID(*i);
2293 void eDVBServicePlay::switchToLive()
2295 if (!m_timeshift_active)
2301 m_teletext_parser = 0;
2303 m_subtitle_parser = 0;
2304 m_new_dvb_subtitle_page_connection = 0;
2305 m_new_subtitle_page_connection = 0;
2306 m_rds_decoder_event_connection = 0;
2307 m_video_event_connection = 0;
2309 /* free the timeshift service handler, we need the resources */
2310 m_service_handler_timeshift.free();
2311 m_timeshift_active = 0;
2313 m_event((iPlayableService*)this, evSeekableStatusChanged);
2318 void eDVBServicePlay::switchToTimeshift()
2320 if (m_timeshift_active)
2325 m_teletext_parser = 0;
2327 m_subtitle_parser = 0;
2328 m_new_subtitle_page_connection = 0;
2329 m_new_dvb_subtitle_page_connection = 0;
2330 m_rds_decoder_event_connection = 0;
2331 m_video_event_connection = 0;
2333 m_timeshift_active = 1;
2335 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2336 r.path = m_timeshift_file;
2338 m_cue = new eCueSheet();
2339 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2341 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2343 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2345 m_event((iPlayableService*)this, evSeekableStatusChanged);
2348 void eDVBServicePlay::updateDecoder()
2350 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2352 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2354 eDVBServicePMTHandler::program program;
2355 if (h.getProgramInfo(program))
2356 eDebug("getting program info failed.");
2359 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2360 if (!program.videoStreams.empty())
2362 eDebugNoNewLine(" (");
2363 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2364 i(program.videoStreams.begin());
2365 i != program.videoStreams.end(); ++i)
2372 if (i != program.videoStreams.begin())
2373 eDebugNoNewLine(", ");
2374 eDebugNoNewLine("%04x", i->pid);
2376 eDebugNoNewLine(")");
2378 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2379 if (!program.audioStreams.empty())
2381 eDebugNoNewLine(" (");
2382 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2383 i(program.audioStreams.begin());
2384 i != program.audioStreams.end(); ++i)
2386 if (i != program.audioStreams.begin())
2387 eDebugNoNewLine(", ");
2388 eDebugNoNewLine("%04x", i->pid);
2390 eDebugNoNewLine(")");
2392 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2393 pcrpid = program.pcrPid;
2394 eDebug(", and the text pid is %04x", program.textPid);
2395 tpid = program.textPid;
2400 h.getDecodeDemux(m_decode_demux);
2403 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2405 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2406 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2407 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2408 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2409 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2412 m_teletext_parser = 0;
2413 m_subtitle_parser = 0;
2417 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2424 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2425 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2426 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2428 else // subservice or recording
2430 eServiceReferenceDVB ref;
2431 m_service_handler.getServiceReference(ref);
2432 eServiceReferenceDVB parent = ref.getParentServiceReference();
2437 ePtr<eDVBResourceManager> res_mgr;
2438 if (!eDVBResourceManager::getInstance(res_mgr))
2440 ePtr<iDVBChannelList> db;
2441 if (!res_mgr->getChannelList(db))
2443 ePtr<eDVBService> origService;
2444 if (!db->getService(parent, origService))
2446 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2447 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2453 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2454 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2456 m_decoder->setVideoPID(vpid, vpidtype);
2457 selectAudioStream();
2459 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2460 m_decoder->setSyncPCR(pcrpid);
2462 m_decoder->setSyncPCR(-1);
2464 m_decoder->setTextPID(tpid);
2466 m_teletext_parser->start(program.textPid);
2469 m_decoder->setTrickmode(1);
2472 m_decoder->preroll();
2476 if (vpid > 0 && vpid < 0x2000)
2480 std::string radio_pic;
2481 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2482 m_decoder->setRadioPic(radio_pic);
2485 m_decoder->setAudioChannel(achannel);
2487 /* don't worry about non-existing services, nor pvr services */
2488 if (m_dvb_service && !m_is_pvr)
2490 /* (audio pid will be set in selectAudioTrack */
2491 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2492 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2493 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2494 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2497 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2500 void eDVBServicePlay::loadCuesheet()
2502 std::string filename = m_reference.path + ".cuts";
2504 m_cue_entries.clear();
2506 FILE *f = fopen(filename.c_str(), "rb");
2510 eDebug("loading cuts..");
2513 unsigned long long where;
2516 if (!fread(&where, sizeof(where), 1, f))
2518 if (!fread(&what, sizeof(what), 1, f))
2521 #if BYTE_ORDER == LITTLE_ENDIAN
2522 where = bswap_64(where);
2529 m_cue_entries.insert(cueEntry(where, what));
2532 eDebug("%d entries", m_cue_entries.size());
2534 eDebug("cutfile not found!");
2536 m_cuesheet_changed = 0;
2537 cutlistToCuesheet();
2538 m_event((iPlayableService*)this, evCuesheetChanged);
2541 void eDVBServicePlay::saveCuesheet()
2543 std::string filename = m_reference.path + ".cuts";
2545 FILE *f = fopen(filename.c_str(), "wb");
2549 unsigned long long where;
2552 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2554 #if BYTE_ORDER == BIG_ENDIAN
2557 where = bswap_64(i->where);
2559 what = htonl(i->what);
2560 fwrite(&where, sizeof(where), 1, f);
2561 fwrite(&what, sizeof(what), 1, f);
2567 m_cuesheet_changed = 0;
2570 void eDVBServicePlay::cutlistToCuesheet()
2574 eDebug("no cue sheet");
2579 if (!m_cutlist_enabled)
2581 m_cue->commitSpans();
2582 eDebug("cutlists were disabled");
2586 pts_t in = 0, out = 0, length = 0;
2590 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2594 if (i == m_cue_entries.end())
2597 if (i->what == 0) /* in */
2601 } else if (i->what == 1) /* out */
2603 else /* mark (2) or last play position (3) */
2620 m_cue->addSourceSpan(in, out);
2624 if (i == m_cue_entries.end())
2627 m_cue->commitSpans();
2630 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2632 if (m_subtitle_widget)
2633 disableSubtitles(parent);
2636 int tuplesize = PyTuple_Size(tuple);
2639 if (!PyTuple_Check(tuple))
2645 entry = PyTuple_GET_ITEM(tuple, 0);
2647 if (!PyInt_Check(entry))
2650 type = PyInt_AsLong(entry);
2652 if (type == 1) // teletext subtitles
2654 int page, magazine, pid;
2658 if (!m_teletext_parser)
2660 eDebug("enable teletext subtitles.. no parser !!!");
2664 entry = PyTuple_GET_ITEM(tuple, 1);
2665 if (!PyInt_Check(entry))
2667 pid = PyInt_AsLong(entry);
2669 entry = PyTuple_GET_ITEM(tuple, 2);
2670 if (!PyInt_Check(entry))
2672 page = PyInt_AsLong(entry);
2674 entry = PyTuple_GET_ITEM(tuple, 3);
2675 if (!PyInt_Check(entry))
2677 magazine = PyInt_AsLong(entry);
2679 m_subtitle_widget = new eSubtitleWidget(parent);
2680 m_subtitle_widget->resize(parent->size()); /* full size */
2681 m_teletext_parser->setPageAndMagazine(page, magazine);
2683 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2687 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2688 if (!m_subtitle_parser)
2690 eDebug("enable dvb subtitles.. no parser !!!");
2696 entry = PyTuple_GET_ITEM(tuple, 1);
2697 if (!PyInt_Check(entry))
2699 pid = PyInt_AsLong(entry);
2701 entry = PyTuple_GET_ITEM(tuple, 2);
2702 if (!PyInt_Check(entry))
2704 composition_page_id = PyInt_AsLong(entry);
2706 entry = PyTuple_GET_ITEM(tuple, 3);
2707 if (!PyInt_Check(entry))
2709 ancillary_page_id = PyInt_AsLong(entry);
2711 m_subtitle_widget = new eSubtitleWidget(parent);
2712 m_subtitle_widget->resize(parent->size()); /* full size */
2713 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2715 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2721 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2722 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2723 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2727 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2729 delete m_subtitle_widget;
2730 m_subtitle_widget = 0;
2731 if (m_subtitle_parser)
2733 m_subtitle_parser->stop();
2734 m_dvb_subtitle_pages.clear();
2736 if (m_teletext_parser)
2738 m_teletext_parser->setPageAndMagazine(-1, -1);
2739 m_subtitle_pages.clear();
2742 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2746 PyObject *eDVBServicePlay::getCachedSubtitle()
2750 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2753 unsigned int data = (unsigned int)tmp;
2754 int pid = (data&0xFFFF0000)>>16;
2755 ePyObject tuple = PyTuple_New(4);
2756 eDVBServicePMTHandler::program program;
2757 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2758 if (!h.getProgramInfo(program))
2760 if (program.textPid==pid) // teletext
2761 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2763 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2764 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2765 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2766 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2774 PyObject *eDVBServicePlay::getSubtitleList()
2776 if (!m_teletext_parser)
2779 ePyObject l = PyList_New(0);
2780 std::set<int> added_ttx_pages;
2782 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2783 m_teletext_parser->m_found_subtitle_pages;
2785 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2786 eDVBServicePMTHandler::program program;
2787 if (h.getProgramInfo(program))
2788 eDebug("getting program info failed.");
2791 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2792 it != program.subtitleStreams.end(); ++it)
2794 switch(it->subtitling_type)
2796 case 0x01: // ebu teletext subtitles
2798 int page_number = it->teletext_page_number & 0xFF;
2799 int magazine_number = it->teletext_magazine_number & 7;
2800 int hash = magazine_number << 8 | page_number;
2801 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2803 ePyObject tuple = PyTuple_New(5);
2804 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2805 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2806 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2807 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2808 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2809 PyList_Append(l, tuple);
2811 added_ttx_pages.insert(hash);
2816 case 0x20 ... 0x23: // dvb subtitles
2818 ePyObject tuple = PyTuple_New(5);
2819 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2820 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2821 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2822 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2823 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2824 PyList_Insert(l, 0, tuple);
2832 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2833 it != subs.end(); ++it)
2835 int page_number = it->teletext_page_number & 0xFF;
2836 int magazine_number = it->teletext_magazine_number & 7;
2837 int hash = magazine_number << 8 | page_number;
2838 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2840 ePyObject tuple = PyTuple_New(5);
2841 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2842 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2843 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2844 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2845 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2846 PyList_Append(l, tuple);
2854 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2856 if (m_subtitle_widget)
2860 m_decoder->getPTS(0, pos);
2861 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2862 m_subtitle_pages.push_back(page);
2863 checkSubtitleTiming();
2867 void eDVBServicePlay::checkSubtitleTiming()
2869 eDebug("checkSubtitleTiming");
2870 if (!m_subtitle_widget)
2874 enum { TELETEXT, DVB } type;
2875 eDVBTeletextSubtitlePage page;
2876 eDVBSubtitlePage dvb_page;
2878 if (!m_subtitle_pages.empty())
2880 page = m_subtitle_pages.front();
2882 show_time = page.m_pts;
2884 else if (!m_dvb_subtitle_pages.empty())
2886 dvb_page = m_dvb_subtitle_pages.front();
2888 show_time = dvb_page.m_show_time;
2896 m_decoder->getPTS(0, pos);
2898 eDebug("%lld %lld", pos, show_time);
2899 int diff = show_time - pos;
2902 eDebug("[late (%d ms)]", -diff / 90);
2905 // if (diff > 900000)
2907 // eDebug("[invalid]");
2913 if (type == TELETEXT)
2915 eDebug("display teletext subtitle page %lld", show_time);
2916 m_subtitle_widget->setPage(page);
2917 m_subtitle_pages.pop_front();
2921 eDebug("display dvb subtitle Page %lld", show_time);
2922 m_subtitle_widget->setPage(dvb_page);
2923 m_dvb_subtitle_pages.pop_front();
2927 eDebug("start subtitle delay %d", diff / 90);
2928 m_subtitle_sync_timer->start(diff / 90, 1);
2934 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2936 if (m_subtitle_widget)
2940 m_decoder->getPTS(0, pos);
2941 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2942 m_dvb_subtitle_pages.push_back(p);
2943 checkSubtitleTiming();
2947 int eDVBServicePlay::getAC3Delay()
2950 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2952 return m_decoder->getAC3Delay();
2957 int eDVBServicePlay::getPCMDelay()
2960 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2962 return m_decoder->getPCMDelay();
2967 void eDVBServicePlay::setAC3Delay(int delay)
2970 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2972 m_decoder->setAC3Delay(delay);
2975 void eDVBServicePlay::setPCMDelay(int delay)
2978 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2980 m_decoder->setPCMDelay(delay);
2983 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2985 memcpy(&m_videoEventData, &event, sizeof(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))
3016 PyObject *r = program.createPythonObject();
3017 ePtr<iDVBDemux> demux;
3018 if (!m_service_handler.getDataDemux(demux))
3021 demux->getCADemuxID(demux_id);
3023 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
3030 DEFINE_REF(eDVBServicePlay)
3032 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3036 case iServiceInformation::sTransponderData:
3037 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3041 return iStaticServiceInformation::getInfoObject(ref, w);
3044 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");