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 PutToDict(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, const char *value);
114 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
117 PutToDict(dict, "type", "Satellite");
118 PutToDict(dict, "frequency", feparm.frequency);
119 PutToDict(dict, "symbolrate", feparm.symbol_rate);
120 PutToDict(dict, "orbital position", feparm.orbital_position);
121 switch (feparm.inversion)
123 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
124 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
126 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
128 PutToDict(dict, "inversion", tmp);
131 case eDVBFrontendParametersSatellite::FEC::fNone: tmp="NONE"; break;
132 case eDVBFrontendParametersSatellite::FEC::f1_2: tmp="1/2"; break;
133 case eDVBFrontendParametersSatellite::FEC::f2_3: tmp="2/3"; break;
134 case eDVBFrontendParametersSatellite::FEC::f3_4: tmp="3/4"; break;
135 case eDVBFrontendParametersSatellite::FEC::f5_6: tmp="5/6"; break;
136 case eDVBFrontendParametersSatellite::FEC::f7_8: tmp="7/8"; break;
137 case eDVBFrontendParametersSatellite::FEC::f3_5: tmp="3/5"; break;
138 case eDVBFrontendParametersSatellite::FEC::f4_5: tmp="4/5"; break;
139 case eDVBFrontendParametersSatellite::FEC::f8_9: tmp="8/9"; break;
140 case eDVBFrontendParametersSatellite::FEC::f9_10: tmp="9/10"; break;
142 case eDVBFrontendParametersSatellite::FEC::fAuto: tmp="AUTO"; break;
144 PutToDict(dict, "fec inner", tmp);
145 switch (feparm.modulation)
147 case eDVBFrontendParametersSatellite::Modulation::Auto: tmp="AUTO"; break;
148 case eDVBFrontendParametersSatellite::Modulation::QPSK: tmp="QPSK"; break;
149 case eDVBFrontendParametersSatellite::Modulation::M8PSK: tmp="8PSK"; break;
150 case eDVBFrontendParametersSatellite::Modulation::QAM_16: tmp="QAM16"; break;
152 PutToDict(dict, "modulation", tmp);
153 switch(feparm.polarisation)
155 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
156 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
157 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR LEFT"; break;
159 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR RIGHT"; break;
161 PutToDict(dict, "polarization", tmp);
162 switch(feparm.system)
165 case eDVBFrontendParametersSatellite::System::DVB_S: tmp="DVB-S"; break;
166 case eDVBFrontendParametersSatellite::System::DVB_S2:
167 switch(feparm.rolloff)
170 case eDVBFrontendParametersSatellite::RollOff::alpha_0_35: tmp="0.35"; break;
171 case eDVBFrontendParametersSatellite::RollOff::alpha_0_25: tmp="0.25"; break;
172 case eDVBFrontendParametersSatellite::RollOff::alpha_0_20: tmp="0.20"; break;
174 PutToDict(dict, "roll off", tmp);
177 case eDVBFrontendParametersSatellite::Pilot::On: tmp="ON"; break;
178 case eDVBFrontendParametersSatellite::Pilot::Off: tmp="OFF"; break;
180 case eDVBFrontendParametersSatellite::Pilot::Unknown: tmp="AUTO"; break;
182 PutToDict(dict, "pilot", tmp);
186 PutToDict(dict, "system", tmp);
189 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
191 PutToDict(dict, "type", "Terrestrial");
192 PutToDict(dict, "frequency", feparm.frequency);
194 switch (feparm.bandwidth)
196 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz: tmp="8 MHz"; break;
197 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz: tmp="7 MHz"; break;
198 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz: tmp="6 MHz"; break;
200 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto: tmp="AUTO"; break;
202 PutToDict(dict, "bandwidth", tmp);
203 switch (feparm.code_rate_LP)
205 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
206 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
207 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
208 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
209 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
211 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
213 PutToDict(dict, "code rate lp", tmp);
214 switch (feparm.code_rate_HP)
216 case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
217 case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
218 case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
219 case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
220 case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
222 case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
224 PutToDict(dict, "code rate hp", tmp);
225 switch (feparm.modulation)
227 case eDVBFrontendParametersTerrestrial::Modulation::QPSK: tmp="QPSK"; break;
228 case eDVBFrontendParametersTerrestrial::Modulation::QAM16: tmp="QAM16"; break;
229 case eDVBFrontendParametersTerrestrial::Modulation::QAM64: tmp="QAM64"; break;
231 case eDVBFrontendParametersTerrestrial::Modulation::Auto: tmp="AUTO"; break;
233 PutToDict(dict, "constellation", tmp);
234 switch (feparm.transmission_mode)
236 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k: tmp="2k"; break;
237 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k: tmp="8k"; break;
239 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto: tmp="AUTO"; break;
241 PutToDict(dict, "transmission mode", tmp);
242 switch (feparm.guard_interval)
244 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32: tmp="1/32"; break;
245 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16: tmp="1/16"; break;
246 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8: tmp="1/8"; break;
247 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4: tmp="1/4"; break;
249 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto: tmp="AUTO"; break;
251 PutToDict(dict, "guard interval", tmp);
252 switch (feparm.hierarchy)
254 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone: tmp="NONE"; break;
255 case eDVBFrontendParametersTerrestrial::Hierarchy::H1: tmp="1"; break;
256 case eDVBFrontendParametersTerrestrial::Hierarchy::H2: tmp="2"; break;
257 case eDVBFrontendParametersTerrestrial::Hierarchy::H4: tmp="4"; break;
259 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto: tmp="AUTO"; break;
261 PutToDict(dict, "hierarchy", tmp);
262 switch (feparm.inversion)
264 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
265 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
267 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
269 PutToDict(dict, "inversion", tmp);
272 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
275 PutToDict(dict, "type", "Cable");
276 PutToDict(dict, "frequency", feparm.frequency);
277 PutToDict(dict, "symbolrate", feparm.symbol_rate);
278 switch (feparm.modulation)
280 case eDVBFrontendParametersCable::Modulation::QAM16: tmp="QAM16"; break;
281 case eDVBFrontendParametersCable::Modulation::QAM32: tmp="QAM32"; break;
282 case eDVBFrontendParametersCable::Modulation::QAM64: tmp="QAM64"; break;
283 case eDVBFrontendParametersCable::Modulation::QAM128: tmp="QAM128"; break;
284 case eDVBFrontendParametersCable::Modulation::QAM256: tmp="QAM256"; break;
286 case eDVBFrontendParametersCable::Modulation::Auto: tmp="AUTO"; break;
288 PutToDict(dict, "modulation", tmp);
289 switch (feparm.inversion)
291 case eDVBFrontendParametersCable::Inversion::On: tmp="ON"; break;
292 case eDVBFrontendParametersCable::Inversion::Off: tmp="OFF"; break;
294 case eDVBFrontendParametersCable::Inversion::Unknown: tmp="AUTO"; break;
296 PutToDict(dict, "inversion", tmp);
297 switch (feparm.fec_inner)
299 case eDVBFrontendParametersCable::FEC::fNone: tmp="NONE"; break;
300 case eDVBFrontendParametersCable::FEC::f1_2: tmp="1/2"; break;
301 case eDVBFrontendParametersCable::FEC::f2_3: tmp="2/3"; break;
302 case eDVBFrontendParametersCable::FEC::f3_4: tmp="3/4"; break;
303 case eDVBFrontendParametersCable::FEC::f5_6: tmp="5/6"; break;
304 case eDVBFrontendParametersCable::FEC::f7_8: tmp="7/8"; break;
305 case eDVBFrontendParametersCable::FEC::f8_9: tmp="8/9"; break;
307 case eDVBFrontendParametersCable::FEC::fAuto: tmp="AUTO"; break;
309 PutToDict(dict, "fec inner", tmp);
312 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
314 if (r.type == eServiceReference::idDVB)
316 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
319 case iServiceInformation::sTransponderData:
321 ePtr<eDVBResourceManager> res;
322 if (!eDVBResourceManager::getInstance(res))
324 ePtr<iDVBChannelList> db;
325 if (!res->getChannelList(db))
328 ref.getChannelID(chid);
329 ePtr<iDVBFrontendParameters> feparm;
330 if (!db->getChannelFrontendData(chid, feparm))
333 if (!feparm->getSystem(system))
335 ePyObject dict = PyDict_New();
338 case iDVBFrontend::feSatellite:
340 eDVBFrontendParametersSatellite s;
342 PutSatelliteDataToDict(dict, s);
345 case iDVBFrontend::feTerrestrial:
347 eDVBFrontendParametersTerrestrial t;
349 PutTerrestrialDataToDict(dict, t);
352 case iDVBFrontend::feCable:
354 eDVBFrontendParametersCable c;
356 PutCableDataToDict(dict, c);
360 eDebug("unknown frontend type %d", system);
375 DEFINE_REF(eStaticServiceDVBBouquetInformation);
377 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
379 ePtr<iDVBChannelList> db;
380 ePtr<eDVBResourceManager> res;
383 if ((err = eDVBResourceManager::getInstance(res)) != 0)
385 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
388 if ((err = res->getChannelList(db)) != 0)
390 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
395 if ((err = db->getBouquet(ref, bouquet)) != 0)
397 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
401 if ( bouquet && bouquet->m_bouquet_name.length() )
403 name = bouquet->m_bouquet_name;
410 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
412 if (ref.flags & eServiceReference::isGroup)
414 ePtr<iDVBChannelList> db;
415 ePtr<eDVBResourceManager> res;
417 if (eDVBResourceManager::getInstance(res))
419 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
423 if (res->getChannelList(db))
425 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
430 if (db->getBouquet(ref, bouquet))
432 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
436 int prio_order = eDVBFrontend::getTypePriorityOrder();
438 eDVBChannelID chid, chid_ignore;
439 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
440 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
442 static unsigned char prio_map[6][3] = {
443 { 3, 2, 1 }, // -S -C -T
444 { 3, 1, 2 }, // -S -T -C
445 { 2, 3, 1 }, // -C -S -T
446 { 1, 3, 2 }, // -C -T -S
447 { 1, 2, 3 }, // -T -C -S
448 { 2, 1, 3 } // -T -S -C
450 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
451 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
456 case 30000: // cached DVB-T channel
457 case 1: // DVB-T frontend
458 tmp = prio_map[prio_order][2];
460 case 40000: // cached DVB-C channel
462 tmp = prio_map[prio_order][1];
465 tmp = prio_map[prio_order][0];
470 m_playable_service = *it;
477 m_playable_service = eServiceReference();
481 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
486 #include <lib/dvb/epgcache.h>
488 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
490 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
493 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
495 DECLARE_REF(eStaticServiceDVBPVRInformation);
496 eServiceReference m_ref;
497 eDVBMetaParser m_parser;
499 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
500 RESULT getName(const eServiceReference &ref, std::string &name);
501 int getLength(const eServiceReference &ref);
502 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
503 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
504 int getInfo(const eServiceReference &ref, int w);
505 std::string getInfoString(const eServiceReference &ref,int w);
508 DEFINE_REF(eStaticServiceDVBPVRInformation);
510 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
513 m_parser.parseFile(ref.path);
516 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
518 ASSERT(ref == m_ref);
519 if (m_parser.m_name.size())
520 name = m_parser.m_name;
524 size_t n = name.rfind('/');
525 if (n != std::string::npos)
526 name = name.substr(n + 1);
531 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
533 ASSERT(ref == m_ref);
537 if (tstools.openFile(ref.path.c_str()))
541 if (tstools.calcLen(len))
547 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
551 case iServiceInformation::sDescription:
552 return iServiceInformation::resIsString;
553 case iServiceInformation::sServiceref:
554 return iServiceInformation::resIsString;
555 case iServiceInformation::sTimeCreate:
556 if (m_parser.m_time_create)
557 return m_parser.m_time_create;
559 return iServiceInformation::resNA;
561 return iServiceInformation::resNA;
565 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
569 case iServiceInformation::sDescription:
570 return m_parser.m_description;
571 case iServiceInformation::sServiceref:
572 return m_parser.m_ref.toString();
573 case iServiceInformation::sTags:
574 return m_parser.m_tags;
580 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
582 if (!ref.path.empty())
584 ePtr<eServiceEvent> event = new eServiceEvent;
585 std::string filename = ref.path;
586 filename.erase(filename.length()-2, 2);
588 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
598 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
600 DECLARE_REF(eDVBPVRServiceOfflineOperations);
601 eServiceReferenceDVB m_ref;
603 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
605 RESULT deleteFromDisk(int simulate);
606 RESULT getListOfFilenames(std::list<std::string> &);
609 DEFINE_REF(eDVBPVRServiceOfflineOperations);
611 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
615 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
621 std::list<std::string> res;
622 if (getListOfFilenames(res))
625 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
627 eDebug("FATAL !! can't get background file eraser");
629 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
631 eDebug("Removing %s...", i->c_str());
633 eraser->erase(i->c_str());
635 ::unlink(i->c_str());
642 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
645 res.push_back(m_ref.path);
647 // handling for old splitted recordings (enigma 1)
652 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
654 if (stat(buf, &s) < 0)
659 res.push_back(m_ref.path + ".meta");
660 res.push_back(m_ref.path + ".ap");
661 res.push_back(m_ref.path + ".cuts");
662 std::string tmp = m_ref.path;
663 tmp.erase(m_ref.path.length()-3);
664 res.push_back(tmp + ".eit");
668 DEFINE_REF(eServiceFactoryDVB)
670 eServiceFactoryDVB::eServiceFactoryDVB()
672 ePtr<eServiceCenter> sc;
674 eServiceCenter::getPrivInstance(sc);
677 std::list<std::string> extensions;
678 extensions.push_back("ts");
679 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
682 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
683 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
686 eServiceFactoryDVB::~eServiceFactoryDVB()
688 ePtr<eServiceCenter> sc;
690 eServiceCenter::getPrivInstance(sc);
692 sc->removeServiceFactory(eServiceFactoryDVB::id);
695 DEFINE_REF(eDVBServiceList);
697 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
701 eDVBServiceList::~eDVBServiceList()
705 RESULT eDVBServiceList::startQuery()
707 ePtr<iDVBChannelList> db;
708 ePtr<eDVBResourceManager> res;
711 if ((err = eDVBResourceManager::getInstance(res)) != 0)
713 eDebug("no resource manager");
716 if ((err = res->getChannelList(db)) != 0)
718 eDebug("no channel list");
722 ePtr<eDVBChannelQuery> q;
724 if (!m_parent.path.empty())
726 eDVBChannelQuery::compile(q, m_parent.path);
729 eDebug("compile query failed");
734 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
736 eDebug("startQuery failed");
743 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
745 eServiceReferenceDVB ref;
750 while (!m_query->getNextResult(ref))
754 list.sort(iListableServiceCompare(this));
759 // The first argument of this function is a format string to specify the order and
760 // the content of the returned list
761 // useable format options are
762 // R = Service Reference (as swig object .. this is very slow)
763 // S = Service Reference (as python string object .. same as ref.toString())
764 // C = Service Reference (as python string object .. same as ref.toCompareString())
765 // N = Service Name (as python string object)
766 // n = Short Service Name (short name brakets used) (as python string object)
767 // when exactly one return value per service is selected in the format string,
768 // then each value is directly a list entry
769 // when more than one value is returned per service, then the list is a list of
771 // unknown format string chars are returned as python None values !
772 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
775 std::list<eServiceReference> tmplist;
778 if (!format || !(retcount=strlen(format)))
779 format = "R"; // just return service reference swig object ...
781 if (!getContent(tmplist, sorted))
783 int services=tmplist.size();
784 ePtr<iStaticServiceInformation> sptr;
785 eServiceCenterPtr service_center;
787 if (strchr(format, 'N') || strchr(format, 'n'))
788 eServiceCenter::getPrivInstance(service_center);
790 ret = PyList_New(services);
791 std::list<eServiceReference>::iterator it(tmplist.begin());
793 for (int cnt=0; cnt < services; ++cnt)
795 eServiceReference &ref=*it++;
796 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
797 for (int i=0; i < retcount; ++i)
802 case 'R': // service reference (swig)object
803 tmp = NEW_eServiceReference(ref);
805 case 'C': // service reference compare string
806 tmp = PyString_FromString(ref.toCompareString().c_str());
808 case 'S': // service reference string
809 tmp = PyString_FromString(ref.toString().c_str());
811 case 'N': // service name
814 service_center->info(ref, sptr);
818 sptr->getName(ref, name);
820 // filter short name brakets
822 while((pos = name.find("\xc2\x86")) != std::string::npos)
824 while((pos = name.find("\xc2\x87")) != std::string::npos)
828 tmp = PyString_FromString(name.c_str());
832 tmp = PyString_FromString("<n/a>");
834 case 'n': // short service name
837 service_center->info(ref, sptr);
841 sptr->getName(ref, name);
842 name = buildShortName(name);
844 tmp = PyString_FromString(name.c_str());
848 tmp = PyString_FromString("<n/a>");
861 PyTuple_SET_ITEM(tuple, i, tmp);
863 PyList_SET_ITEM(ret, cnt, tmp);
867 PyList_SET_ITEM(ret, cnt, tuple);
870 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
873 RESULT eDVBServiceList::getNext(eServiceReference &ref)
878 return m_query->getNextResult((eServiceReferenceDVB&)ref);
881 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
883 if (m_parent.flags & eServiceReference::canDescent) // bouquet
885 ePtr<iDVBChannelList> db;
886 ePtr<eDVBResourceManager> resm;
888 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
891 if (db->getBouquet(m_parent, m_bouquet) != 0)
902 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
906 return m_bouquet->addService(ref, before);
909 RESULT eDVBServiceList::removeService(eServiceReference &ref)
913 return m_bouquet->removeService(ref);
916 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
920 return m_bouquet->moveService(ref, pos);
923 RESULT eDVBServiceList::flushChanges()
927 return m_bouquet->flushChanges();
930 RESULT eDVBServiceList::setListName(const std::string &name)
934 return m_bouquet->setListName(name);
937 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
939 ePtr<eDVBService> service;
940 int r = lookupService(service, ref);
943 // check resources...
944 ptr = new eDVBServicePlay(ref, service);
948 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
950 if (ref.path.empty())
952 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
961 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
963 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
964 if (list->startQuery())
974 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
976 /* is a listable service? */
977 if (ref.flags & eServiceReference::canDescent) // bouquet
979 if ( !ref.name.empty() ) // satellites or providers list
980 ptr = m_StaticServiceDVBInfo;
981 else // a dvb bouquet
982 ptr = m_StaticServiceDVBBouquetInfo;
984 else if (!ref.path.empty()) /* do we have a PVR service? */
985 ptr = new eStaticServiceDVBPVRInformation(ref);
986 else // normal dvb service
988 ePtr<eDVBService> service;
989 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
990 ptr = m_StaticServiceDVBInfo;
992 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
998 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
1000 if (ref.path.empty())
1006 ptr = new eDVBPVRServiceOfflineOperations(ref);
1011 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
1013 // TODO: handle the listing itself
1014 // if (ref.... == -1) .. return "... bouquets ...";
1015 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
1017 ePtr<iDVBChannelList> db;
1018 ePtr<eDVBResourceManager> res;
1021 if ((err = eDVBResourceManager::getInstance(res)) != 0)
1023 eDebug("no resource manager");
1026 if ((err = res->getChannelList(db)) != 0)
1028 eDebug("no channel list");
1032 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
1033 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
1035 eDebug("getService failed!");
1042 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
1043 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
1045 memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
1047 m_is_pvr = !m_reference.path.empty();
1049 m_timeshift_enabled = m_timeshift_active = 0;
1052 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
1053 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
1054 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
1056 m_cuesheet_changed = 0;
1057 m_cutlist_enabled = 1;
1059 m_subtitle_widget = 0;
1063 m_subtitle_sync_timer = eTimer::create(eApp);
1065 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
1068 eDVBServicePlay::~eDVBServicePlay()
1070 delete m_subtitle_widget;
1073 void eDVBServicePlay::gotNewEvent()
1077 ePtr<eServiceEvent> m_event_now, m_event_next;
1078 getEvent(m_event_now, 0);
1079 getEvent(m_event_next, 1);
1082 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1084 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1086 m_event((iPlayableService*)this, evUpdatedEventInfo);
1089 void eDVBServicePlay::serviceEvent(int event)
1091 m_tune_state = event;
1095 case eDVBServicePMTHandler::eventTuned:
1097 ePtr<iDVBDemux> m_demux;
1098 if (!m_service_handler.getDataDemux(m_demux))
1100 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1101 int sid = ref.getParentServiceID().get();
1103 sid = ref.getServiceID().get();
1104 if ( ref.getParentTransportStreamID().get() &&
1105 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1106 m_event_handler.startOther(m_demux, sid);
1108 m_event_handler.start(m_demux, sid);
1110 m_event((iPlayableService*)this, evTunedIn);
1113 case eDVBServicePMTHandler::eventNoResources:
1114 case eDVBServicePMTHandler::eventNoPAT:
1115 case eDVBServicePMTHandler::eventNoPATEntry:
1116 case eDVBServicePMTHandler::eventNoPMT:
1117 case eDVBServicePMTHandler::eventTuneFailed:
1118 case eDVBServicePMTHandler::eventMisconfiguration:
1120 eDebug("DVB service failed to tune - error %d", event);
1121 m_event((iPlayableService*)this, evTuneFailed);
1124 case eDVBServicePMTHandler::eventNewProgramInfo:
1126 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1127 if (m_timeshift_enabled)
1128 updateTimeshiftPids();
1129 if (!m_timeshift_active)
1131 if (m_first_program_info && m_is_pvr)
1133 m_first_program_info = 0;
1136 m_event((iPlayableService*)this, evUpdatedInfo);
1139 case eDVBServicePMTHandler::eventEOF:
1140 m_event((iPlayableService*)this, evEOF);
1142 case eDVBServicePMTHandler::eventSOF:
1143 m_event((iPlayableService*)this, evSOF);
1148 void eDVBServicePlay::serviceEventTimeshift(int event)
1152 case eDVBServicePMTHandler::eventNewProgramInfo:
1153 if (m_timeshift_active)
1156 case eDVBServicePMTHandler::eventSOF:
1157 m_event((iPlayableService*)this, evSOF);
1159 case eDVBServicePMTHandler::eventEOF:
1160 if ((!m_is_paused) && (m_skipmode >= 0))
1166 RESULT eDVBServicePlay::start()
1169 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1170 two (one for decoding, one for data source), as we must be prepared
1171 to start recording from the data demux. */
1173 m_cue = new eCueSheet();
1175 m_event(this, evStart);
1177 m_first_program_info = 1;
1178 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1179 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1181 /* inject EIT if there is a stored one */
1184 std::string filename = service.path;
1185 filename.erase(filename.length()-2, 2);
1187 ePtr<eServiceEvent> event = new eServiceEvent;
1188 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1190 ePtr<eServiceEvent> empty;
1191 m_event_handler.inject(event, 0);
1192 m_event_handler.inject(empty, 1);
1199 m_event(this, evStart);
1204 RESULT eDVBServicePlay::stop()
1206 /* add bookmark for last play position */
1209 pts_t play_position, length;
1210 if (!getPlayPosition(play_position))
1212 /* remove last position */
1213 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1215 if (i->what == 3) /* current play position */
1217 m_cue_entries.erase(i);
1218 i = m_cue_entries.begin();
1224 if (getLength(length))
1229 int perc = play_position * 100LL / length;
1231 /* only store last play position when between 1% and 99% */
1232 if ((1 < perc) && (perc < 99))
1233 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1235 m_cuesheet_changed = 1;
1239 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1241 m_service_handler_timeshift.free();
1242 m_service_handler.free();
1244 if (m_is_pvr && m_cuesheet_changed)
1247 /* save cuesheet only when main file is accessible. */
1248 if (!::stat(m_reference.path.c_str(), &s))
1251 m_event((iPlayableService*)this, evStopped);
1255 RESULT eDVBServicePlay::setTarget(int target)
1257 m_is_primary = !target;
1261 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1263 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1267 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1269 /* note: we check for timeshift to be enabled,
1270 not neccessary active. if you pause when timeshift
1271 is not active, you should activate it when unpausing */
1272 if ((!m_is_pvr) && (!m_timeshift_enabled))
1282 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1285 return m_decoder->setSlowMotion(ratio);
1290 RESULT eDVBServicePlay::setFastForward(int ratio)
1292 int skipmode, ffratio;
1298 } else if (ratio > 0)
1306 } else // if (ratio < 0)
1312 if (m_skipmode != skipmode)
1314 eDebug("setting cue skipmode to %d", skipmode);
1316 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1319 m_skipmode = skipmode;
1324 return m_decoder->setFastForward(ffratio);
1327 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1329 if (m_is_pvr || m_timeshift_enabled)
1339 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1340 RESULT eDVBServicePlay::getLength(pts_t &len)
1342 ePtr<iDVBPVRChannel> pvr_channel;
1344 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1347 return pvr_channel->getLength(len);
1350 RESULT eDVBServicePlay::pause()
1352 if (!m_is_paused && m_decoder)
1355 return m_decoder->freeze(0);
1360 RESULT eDVBServicePlay::unpause()
1362 if (m_is_paused && m_decoder)
1365 return m_decoder->unfreeze();
1370 RESULT eDVBServicePlay::seekTo(pts_t to)
1372 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1374 if (!m_decode_demux)
1377 ePtr<iDVBPVRChannel> pvr_channel;
1379 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1385 m_cue->seekTo(0, to);
1386 m_dvb_subtitle_pages.clear();
1387 m_subtitle_pages.clear();
1392 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1394 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1396 if (!m_decode_demux)
1399 ePtr<iDVBPVRChannel> pvr_channel;
1401 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1406 /* HACK until we have skip-AP api */
1407 if ((to > 0) && (to < 100))
1415 m_cue->seekTo(mode, to);
1416 m_dvb_subtitle_pages.clear();
1417 m_subtitle_pages.clear();
1421 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1423 ePtr<iDVBPVRChannel> pvr_channel;
1425 if (!m_decode_demux)
1428 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1433 /* if there is a decoder, use audio or video PTS */
1436 r = m_decoder->getPTS(0, pos);
1442 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1445 RESULT eDVBServicePlay::setTrickmode(int trick)
1448 m_decoder->setTrickmode(trick);
1452 RESULT eDVBServicePlay::isCurrentlySeekable()
1454 return m_is_pvr || m_timeshift_active;
1457 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1463 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1469 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1475 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1481 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1487 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1490 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1491 (m_timeshift_enabled || !m_is_pvr))
1493 if (!m_timeshift_enabled)
1495 /* query config path */
1497 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1498 eDebug("could not query ts path from config");
1502 /* we need enough diskspace */
1504 if (statfs(tspath.c_str(), &fs) < 0)
1506 eDebug("statfs failed!");
1510 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1512 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1522 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1533 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1539 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1545 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1551 RESULT eDVBServicePlay::getName(std::string &name)
1555 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1556 return i->getName(m_reference, name);
1560 m_dvb_service->getName(m_reference, name);
1564 else if (!m_reference.name.empty())
1565 eStaticServiceDVBInformation().getName(m_reference, name);
1567 name = "DVB service";
1571 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1573 return m_event_handler.getEvent(evt, nownext);
1576 static int readMpegProc(char *str, int decoder)
1580 sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
1581 FILE *f = fopen(tmp, "r");
1584 fscanf(f, "%x", &val);
1590 int eDVBServicePlay::getInfo(int w)
1592 eDVBServicePMTHandler::program program;
1595 return resIsPyObject;
1597 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1599 int no_program_info = 0;
1601 if (h.getProgramInfo(program))
1602 no_program_info = 1;
1606 #if HAVE_DVB_API_VERSION >= 3
1608 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1609 return m_videoEventData.height;
1611 return readMpegProc("yres", !m_is_primary);
1613 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1614 return m_videoEventData.width;
1616 return readMpegProc("xres", !m_is_primary);
1618 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventFrameRateChanged)
1619 return m_videoEventData.framerate;
1621 return readMpegProc("framerate", !m_is_primary);
1623 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventProgressiveChanged)
1624 return m_videoEventData.progressive;
1625 return readMpegProc("progressive", !m_is_primary);
1627 #warning "FIXMEE implement sFrameRate, sProgressive, sVideoHeight, sVideoWidth for old DVB API"
1632 #if HAVE_DVB_API_VERSION >= 3
1633 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1634 return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1635 else if ((val=readMpegProc("aspect", !m_is_primary)) != -1)
1639 #warning "FIXMEE implement sAspect for old DVB API"
1641 if (no_program_info)
1643 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1645 ePtr<eServiceEvent> evt;
1646 if (!m_event_handler.getEvent(evt, 0))
1648 ePtr<eComponentData> data;
1649 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1651 if ( data->getStreamContent() == 1 )
1653 switch(data->getComponentType())
1656 case 1: // 4:3 SD PAL
1658 case 3: // 16:9 SD PAL
1659 case 4: // > 16:9 PAL
1660 case 5: // 4:3 SD NTSC
1662 case 7: // 16:9 SD NTSC
1663 case 8: // > 16:9 NTSC
1666 case 9: // 4:3 HD PAL
1668 case 0xB: // 16:9 HD PAL
1669 case 0xC: // > 16:9 HD PAL
1670 case 0xD: // 4:3 HD NTSC
1672 case 0xF: // 16:9 HD NTSC
1673 case 0x10: // > 16:9 HD PAL
1674 return data->getComponentType();
1682 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1683 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1684 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1685 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1686 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1687 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1688 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1689 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1690 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1691 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1692 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1693 case sProvider: if (!m_dvb_service) return -1; return -2;
1694 case sServiceref: return resIsString;
1695 case sDVBState: return m_tune_state;
1701 std::string eDVBServicePlay::getInfoString(int w)
1706 if (!m_dvb_service) return "";
1707 return m_dvb_service->m_provider_name;
1709 return m_reference.toString();
1713 return iServiceInformation::getInfoString(w);
1716 PyObject *eDVBServicePlay::getInfoObject(int w)
1721 return m_service_handler.getCaIds();
1722 case sTransponderData:
1723 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1727 return iServiceInformation::getInfoObject(w);
1730 int eDVBServicePlay::getNumberOfTracks()
1732 eDVBServicePMTHandler::program program;
1733 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1734 if (h.getProgramInfo(program))
1736 return program.audioStreams.size();
1739 int eDVBServicePlay::getCurrentTrack()
1741 eDVBServicePMTHandler::program program;
1742 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1743 if (h.getProgramInfo(program))
1746 int max = program.audioStreams.size();
1749 for (i = 0; i < max; ++i)
1750 if (program.audioStreams[i].pid == m_current_audio_pid)
1756 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1758 int ret = selectAudioStream(i);
1760 if (m_decoder->start())
1766 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1768 eDVBServicePMTHandler::program program;
1769 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1771 if (h.getProgramInfo(program))
1774 if (i >= program.audioStreams.size())
1777 info.m_pid = program.audioStreams[i].pid;
1779 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1780 info.m_description = "MPEG";
1781 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1782 info.m_description = "AC3";
1783 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1784 info.m_description = "AAC";
1785 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1786 info.m_description = "DTS";
1788 info.m_description = "???";
1790 if (program.audioStreams[i].component_tag != -1)
1792 ePtr<eServiceEvent> evt;
1793 if (!m_event_handler.getEvent(evt, 0))
1795 ePtr<eComponentData> data;
1796 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1797 info.m_language = data->getText();
1801 if (info.m_language.empty())
1802 info.m_language = program.audioStreams[i].language_code;
1807 int eDVBServicePlay::selectAudioStream(int i)
1809 eDVBServicePMTHandler::program program;
1810 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1812 if (h.getProgramInfo(program))
1815 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1823 stream = program.defaultAudioStream;
1825 int apid = -1, apidtype = -1;
1827 if (((unsigned int)stream) < program.audioStreams.size())
1829 apid = program.audioStreams[stream].pid;
1830 apidtype = program.audioStreams[stream].type;
1833 m_current_audio_pid = apid;
1835 if (m_decoder->setAudioPID(apid, apidtype))
1837 eDebug("set audio pid failed");
1841 /* 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 */
1842 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1845 ePtr<iDVBDemux> data_demux;
1846 if (!h.getDataDemux(data_demux))
1848 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1849 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1853 /* if we decided that we need one, update the pid */
1855 m_rds_decoder->start(apid);
1857 /* store new pid as default only when:
1858 a.) we have an entry in the service db for the current service,
1859 b.) we are not playing back something,
1860 c.) we are not selecting the default entry. (we wouldn't change
1861 anything in the best case, or destroy the default setting in
1862 case the real default is not yet available.)
1864 if (m_dvb_service && !m_is_pvr && ((i != -1)
1865 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1867 if (apidtype == eDVBAudio::aMPEG)
1869 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1870 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1874 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1875 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1879 h.resetCachedProgram();
1884 int eDVBServicePlay::getCurrentChannel()
1886 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1889 RESULT eDVBServicePlay::selectChannel(int i)
1891 if (i < LEFT || i > RIGHT || i == STEREO)
1894 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1896 m_decoder->setAudioChannel(i);
1900 std::string eDVBServicePlay::getText(int x)
1906 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1908 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1913 void eDVBServicePlay::rdsDecoderEvent(int what)
1917 case eDVBRdsDecoder::RadioTextChanged:
1918 m_event((iPlayableService*)this, evUpdatedRadioText);
1920 case eDVBRdsDecoder::RtpTextChanged:
1921 m_event((iPlayableService*)this, evUpdatedRtpText);
1923 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1924 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1926 case eDVBRdsDecoder::RecvRassSlidePic:
1927 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1932 void eDVBServicePlay::showRassSlidePicture()
1938 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1939 if (rass_slide_pic.length())
1940 m_decoder->showSinglePic(rass_slide_pic.c_str());
1942 eDebug("empty filename for rass slide picture received!!");
1945 eDebug("no MPEG Decoder to show iframes avail");
1948 eDebug("showRassSlidePicture called.. but not decoder");
1951 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1957 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1958 if (rass_interactive_pic.length())
1959 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1961 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1964 eDebug("no MPEG Decoder to show iframes avail");
1967 eDebug("showRassInteractivePic called.. but not decoder");
1970 ePyObject eDVBServicePlay::getRassInteractiveMask()
1973 return m_rds_decoder->getRassPictureMask();
1977 int eDVBServiceBase::getFrontendInfo(int w)
1979 eUsePtr<iDVBChannel> channel;
1980 if(m_service_handler.getChannel(channel))
1982 ePtr<iDVBFrontend> fe;
1983 if(channel->getFrontend(fe))
1985 return fe->readFrontendData(w);
1988 PyObject *eDVBServiceBase::getFrontendData()
1990 ePyObject ret = PyDict_New();
1993 eUsePtr<iDVBChannel> channel;
1994 if(!m_service_handler.getChannel(channel))
1996 ePtr<iDVBFrontend> fe;
1997 if(!channel->getFrontend(fe))
1998 fe->getFrontendData(ret);
2006 PyObject *eDVBServiceBase::getFrontendStatus()
2008 ePyObject ret = PyDict_New();
2011 eUsePtr<iDVBChannel> channel;
2012 if(!m_service_handler.getChannel(channel))
2014 ePtr<iDVBFrontend> fe;
2015 if(!channel->getFrontend(fe))
2016 fe->getFrontendStatus(ret);
2024 PyObject *eDVBServiceBase::getTransponderData(bool original)
2026 ePyObject ret = PyDict_New();
2029 eUsePtr<iDVBChannel> channel;
2030 if(!m_service_handler.getChannel(channel))
2032 ePtr<iDVBFrontend> fe;
2033 if(!channel->getFrontend(fe))
2035 fe->getTransponderData(ret, original);
2036 ePtr<iDVBFrontendParameters> feparm;
2037 channel->getCurrentFrontendParameters(feparm);
2040 eDVBFrontendParametersSatellite osat;
2041 if (!feparm->getDVBS(osat))
2043 void PutToDict(ePyObject &, const char*, long);
2044 void PutToDict(ePyObject &, const char*, const char*);
2045 PutToDict(ret, "orbital_position", osat.orbital_position);
2046 const char *tmp = "UNKNOWN";
2047 switch(osat.polarisation)
2049 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2050 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2051 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2052 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2055 PutToDict(ret, "polarization", tmp);
2066 PyObject *eDVBServiceBase::getAll(bool original)
2068 ePyObject ret = getTransponderData(original);
2071 eUsePtr<iDVBChannel> channel;
2072 if(!m_service_handler.getChannel(channel))
2074 ePtr<iDVBFrontend> fe;
2075 if(!channel->getFrontend(fe))
2077 fe->getFrontendData(ret);
2078 fe->getFrontendStatus(ret);
2085 int eDVBServicePlay::getNumberOfSubservices()
2087 ePtr<eServiceEvent> evt;
2088 if (!m_event_handler.getEvent(evt, 0))
2089 return evt->getNumOfLinkageServices();
2093 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2095 ePtr<eServiceEvent> evt;
2096 if (!m_event_handler.getEvent(evt, 0))
2098 if (!evt->getLinkageService(sub, m_reference, n))
2101 sub.type=eServiceReference::idInvalid;
2105 RESULT eDVBServicePlay::startTimeshift()
2107 ePtr<iDVBDemux> demux;
2109 eDebug("Start timeshift!");
2111 if (m_timeshift_enabled)
2114 /* start recording with the data demux. */
2115 if (m_service_handler.getDataDemux(demux))
2118 demux->createTSRecorder(m_record);
2123 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2124 eDebug("could not query ts path");
2127 tspath.append("/timeshift.XXXXXX");
2129 templ = new char[tspath.length() + 1];
2130 strcpy(templ, tspath.c_str());
2132 m_timeshift_fd = mkstemp(templ);
2133 m_timeshift_file = std::string(templ);
2135 eDebug("recording to %s", templ);
2139 if (m_timeshift_fd < 0)
2145 m_record->setTargetFD(m_timeshift_fd);
2147 m_timeshift_enabled = 1;
2149 updateTimeshiftPids();
2155 RESULT eDVBServicePlay::stopTimeshift()
2157 if (!m_timeshift_enabled)
2162 m_timeshift_enabled = 0;
2167 close(m_timeshift_fd);
2168 eDebug("remove timeshift file");
2169 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2174 int eDVBServicePlay::isTimeshiftActive()
2176 return m_timeshift_enabled && m_timeshift_active;
2179 RESULT eDVBServicePlay::activateTimeshift()
2181 if (!m_timeshift_enabled)
2184 if (!m_timeshift_active)
2186 switchToTimeshift();
2193 PyObject *eDVBServicePlay::getCutList()
2195 ePyObject list = PyList_New(0);
2197 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2199 ePyObject tuple = PyTuple_New(2);
2200 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2201 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2202 PyList_Append(list, tuple);
2209 void eDVBServicePlay::setCutList(ePyObject list)
2211 if (!PyList_Check(list))
2213 int size = PyList_Size(list);
2216 m_cue_entries.clear();
2218 for (i=0; i<size; ++i)
2220 ePyObject tuple = PyList_GET_ITEM(list, i);
2221 if (!PyTuple_Check(tuple))
2223 eDebug("non-tuple in cutlist");
2226 if (PyTuple_Size(tuple) != 2)
2228 eDebug("cutlist entries need to be a 2-tuple");
2231 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2232 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2234 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2237 pts_t pts = PyLong_AsLongLong(ppts);
2238 int type = PyInt_AsLong(ptype);
2239 m_cue_entries.insert(cueEntry(pts, type));
2240 eDebug("adding %08llx, %d", pts, type);
2242 m_cuesheet_changed = 1;
2244 cutlistToCuesheet();
2245 m_event((iPlayableService*)this, evCuesheetChanged);
2248 void eDVBServicePlay::setCutListEnable(int enable)
2250 m_cutlist_enabled = enable;
2251 cutlistToCuesheet();
2254 void eDVBServicePlay::updateTimeshiftPids()
2259 eDVBServicePMTHandler::program program;
2260 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2262 if (h.getProgramInfo(program))
2266 std::set<int> pids_to_record;
2267 pids_to_record.insert(0); // PAT
2268 if (program.pmtPid != -1)
2269 pids_to_record.insert(program.pmtPid); // PMT
2271 if (program.textPid != -1)
2272 pids_to_record.insert(program.textPid); // Videotext
2274 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2275 i(program.videoStreams.begin());
2276 i != program.videoStreams.end(); ++i)
2277 pids_to_record.insert(i->pid);
2279 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2280 i(program.audioStreams.begin());
2281 i != program.audioStreams.end(); ++i)
2282 pids_to_record.insert(i->pid);
2284 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2285 i(program.subtitleStreams.begin());
2286 i != program.subtitleStreams.end(); ++i)
2287 pids_to_record.insert(i->pid);
2289 std::set<int> new_pids, obsolete_pids;
2291 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2292 m_pids_active.begin(), m_pids_active.end(),
2293 std::inserter(new_pids, new_pids.begin()));
2295 std::set_difference(
2296 m_pids_active.begin(), m_pids_active.end(),
2297 pids_to_record.begin(), pids_to_record.end(),
2298 std::inserter(new_pids, new_pids.begin())
2301 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2302 m_record->addPID(*i);
2304 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2305 m_record->removePID(*i);
2309 void eDVBServicePlay::switchToLive()
2311 if (!m_timeshift_active)
2317 m_teletext_parser = 0;
2319 m_subtitle_parser = 0;
2320 m_new_dvb_subtitle_page_connection = 0;
2321 m_new_subtitle_page_connection = 0;
2322 m_rds_decoder_event_connection = 0;
2323 m_video_event_connection = 0;
2325 /* free the timeshift service handler, we need the resources */
2326 m_service_handler_timeshift.free();
2327 m_timeshift_active = 0;
2329 m_event((iPlayableService*)this, evSeekableStatusChanged);
2334 void eDVBServicePlay::switchToTimeshift()
2336 if (m_timeshift_active)
2341 m_teletext_parser = 0;
2343 m_subtitle_parser = 0;
2344 m_new_subtitle_page_connection = 0;
2345 m_new_dvb_subtitle_page_connection = 0;
2346 m_rds_decoder_event_connection = 0;
2347 m_video_event_connection = 0;
2349 m_timeshift_active = 1;
2351 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2352 r.path = m_timeshift_file;
2354 m_cue = new eCueSheet();
2355 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2357 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2359 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2361 m_event((iPlayableService*)this, evSeekableStatusChanged);
2364 void eDVBServicePlay::updateDecoder()
2366 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2368 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2370 eDVBServicePMTHandler::program program;
2371 if (h.getProgramInfo(program))
2372 eDebug("getting program info failed.");
2375 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2376 if (!program.videoStreams.empty())
2378 eDebugNoNewLine(" (");
2379 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2380 i(program.videoStreams.begin());
2381 i != program.videoStreams.end(); ++i)
2388 if (i != program.videoStreams.begin())
2389 eDebugNoNewLine(", ");
2390 eDebugNoNewLine("%04x", i->pid);
2392 eDebugNoNewLine(")");
2394 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2395 if (!program.audioStreams.empty())
2397 eDebugNoNewLine(" (");
2398 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2399 i(program.audioStreams.begin());
2400 i != program.audioStreams.end(); ++i)
2402 if (i != program.audioStreams.begin())
2403 eDebugNoNewLine(", ");
2404 eDebugNoNewLine("%04x", i->pid);
2406 eDebugNoNewLine(")");
2408 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2409 pcrpid = program.pcrPid;
2410 eDebug(", and the text pid is %04x", program.textPid);
2411 tpid = program.textPid;
2416 h.getDecodeDemux(m_decode_demux);
2419 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2421 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2422 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2423 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2424 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2425 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2428 m_teletext_parser = 0;
2429 m_subtitle_parser = 0;
2433 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2440 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2441 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2442 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2444 else // subservice or recording
2446 eServiceReferenceDVB ref;
2447 m_service_handler.getServiceReference(ref);
2448 eServiceReferenceDVB parent = ref.getParentServiceReference();
2453 ePtr<eDVBResourceManager> res_mgr;
2454 if (!eDVBResourceManager::getInstance(res_mgr))
2456 ePtr<iDVBChannelList> db;
2457 if (!res_mgr->getChannelList(db))
2459 ePtr<eDVBService> origService;
2460 if (!db->getService(parent, origService))
2462 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2463 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2469 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2470 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2472 m_decoder->setVideoPID(vpid, vpidtype);
2473 selectAudioStream();
2475 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2476 m_decoder->setSyncPCR(pcrpid);
2478 m_decoder->setSyncPCR(-1);
2480 m_decoder->setTextPID(tpid);
2482 m_teletext_parser->start(program.textPid);
2485 m_decoder->setTrickmode(1);
2488 m_decoder->preroll();
2492 if (vpid > 0 && vpid < 0x2000)
2496 std::string radio_pic;
2497 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2498 m_decoder->setRadioPic(radio_pic);
2501 m_decoder->setAudioChannel(achannel);
2503 /* don't worry about non-existing services, nor pvr services */
2504 if (m_dvb_service && !m_is_pvr)
2506 /* (audio pid will be set in selectAudioTrack */
2507 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2508 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2509 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2510 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2513 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2516 void eDVBServicePlay::loadCuesheet()
2518 std::string filename = m_reference.path + ".cuts";
2520 m_cue_entries.clear();
2522 FILE *f = fopen(filename.c_str(), "rb");
2526 eDebug("loading cuts..");
2529 unsigned long long where;
2532 if (!fread(&where, sizeof(where), 1, f))
2534 if (!fread(&what, sizeof(what), 1, f))
2537 #if BYTE_ORDER == LITTLE_ENDIAN
2538 where = bswap_64(where);
2545 m_cue_entries.insert(cueEntry(where, what));
2548 eDebug("%d entries", m_cue_entries.size());
2550 eDebug("cutfile not found!");
2552 m_cuesheet_changed = 0;
2553 cutlistToCuesheet();
2554 m_event((iPlayableService*)this, evCuesheetChanged);
2557 void eDVBServicePlay::saveCuesheet()
2559 std::string filename = m_reference.path + ".cuts";
2561 FILE *f = fopen(filename.c_str(), "wb");
2565 unsigned long long where;
2568 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2570 #if BYTE_ORDER == BIG_ENDIAN
2573 where = bswap_64(i->where);
2575 what = htonl(i->what);
2576 fwrite(&where, sizeof(where), 1, f);
2577 fwrite(&what, sizeof(what), 1, f);
2583 m_cuesheet_changed = 0;
2586 void eDVBServicePlay::cutlistToCuesheet()
2590 eDebug("no cue sheet");
2595 if (!m_cutlist_enabled)
2597 m_cue->commitSpans();
2598 eDebug("cutlists were disabled");
2602 pts_t in = 0, out = 0, length = 0;
2606 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2610 if (i == m_cue_entries.end())
2613 if (i->what == 0) /* in */
2617 } else if (i->what == 1) /* out */
2619 else /* mark (2) or last play position (3) */
2636 m_cue->addSourceSpan(in, out);
2640 if (i == m_cue_entries.end())
2643 m_cue->commitSpans();
2646 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2648 if (m_subtitle_widget)
2649 disableSubtitles(parent);
2652 int tuplesize = PyTuple_Size(tuple);
2655 if (!PyTuple_Check(tuple))
2661 entry = PyTuple_GET_ITEM(tuple, 0);
2663 if (!PyInt_Check(entry))
2666 type = PyInt_AsLong(entry);
2668 if (type == 1) // teletext subtitles
2670 int page, magazine, pid;
2674 if (!m_teletext_parser)
2676 eDebug("enable teletext subtitles.. no parser !!!");
2680 entry = PyTuple_GET_ITEM(tuple, 1);
2681 if (!PyInt_Check(entry))
2683 pid = PyInt_AsLong(entry);
2685 entry = PyTuple_GET_ITEM(tuple, 2);
2686 if (!PyInt_Check(entry))
2688 page = PyInt_AsLong(entry);
2690 entry = PyTuple_GET_ITEM(tuple, 3);
2691 if (!PyInt_Check(entry))
2693 magazine = PyInt_AsLong(entry);
2695 m_subtitle_widget = new eSubtitleWidget(parent);
2696 m_subtitle_widget->resize(parent->size()); /* full size */
2697 m_teletext_parser->setPageAndMagazine(page, magazine);
2699 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2703 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2704 if (!m_subtitle_parser)
2706 eDebug("enable dvb subtitles.. no parser !!!");
2712 entry = PyTuple_GET_ITEM(tuple, 1);
2713 if (!PyInt_Check(entry))
2715 pid = PyInt_AsLong(entry);
2717 entry = PyTuple_GET_ITEM(tuple, 2);
2718 if (!PyInt_Check(entry))
2720 composition_page_id = PyInt_AsLong(entry);
2722 entry = PyTuple_GET_ITEM(tuple, 3);
2723 if (!PyInt_Check(entry))
2725 ancillary_page_id = PyInt_AsLong(entry);
2727 m_subtitle_widget = new eSubtitleWidget(parent);
2728 m_subtitle_widget->resize(parent->size()); /* full size */
2729 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2731 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2737 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2738 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2739 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2743 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2745 delete m_subtitle_widget;
2746 m_subtitle_widget = 0;
2747 if (m_subtitle_parser)
2749 m_subtitle_parser->stop();
2750 m_dvb_subtitle_pages.clear();
2752 if (m_teletext_parser)
2754 m_teletext_parser->setPageAndMagazine(-1, -1);
2755 m_subtitle_pages.clear();
2758 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2762 PyObject *eDVBServicePlay::getCachedSubtitle()
2766 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2769 unsigned int data = (unsigned int)tmp;
2770 int pid = (data&0xFFFF0000)>>16;
2771 ePyObject tuple = PyTuple_New(4);
2772 eDVBServicePMTHandler::program program;
2773 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2774 if (!h.getProgramInfo(program))
2776 if (program.textPid==pid) // teletext
2777 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2779 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2780 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2781 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2782 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2790 PyObject *eDVBServicePlay::getSubtitleList()
2792 if (!m_teletext_parser)
2795 ePyObject l = PyList_New(0);
2796 std::set<int> added_ttx_pages;
2798 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2799 m_teletext_parser->m_found_subtitle_pages;
2801 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2802 eDVBServicePMTHandler::program program;
2803 if (h.getProgramInfo(program))
2804 eDebug("getting program info failed.");
2807 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2808 it != program.subtitleStreams.end(); ++it)
2810 switch(it->subtitling_type)
2812 case 0x01: // ebu teletext subtitles
2814 int page_number = it->teletext_page_number & 0xFF;
2815 int magazine_number = it->teletext_magazine_number & 7;
2816 int hash = magazine_number << 8 | page_number;
2817 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2819 ePyObject tuple = PyTuple_New(5);
2820 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2821 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2822 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2823 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2824 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2825 PyList_Append(l, tuple);
2827 added_ttx_pages.insert(hash);
2832 case 0x20 ... 0x23: // dvb subtitles
2834 ePyObject tuple = PyTuple_New(5);
2835 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2836 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2837 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2838 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2839 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2840 PyList_Insert(l, 0, tuple);
2848 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2849 it != subs.end(); ++it)
2851 int page_number = it->teletext_page_number & 0xFF;
2852 int magazine_number = it->teletext_magazine_number & 7;
2853 int hash = magazine_number << 8 | page_number;
2854 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2856 ePyObject tuple = PyTuple_New(5);
2857 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2858 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2859 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2860 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2861 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2862 PyList_Append(l, tuple);
2870 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2872 if (m_subtitle_widget)
2876 m_decoder->getPTS(0, pos);
2877 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2878 m_subtitle_pages.push_back(page);
2879 checkSubtitleTiming();
2883 void eDVBServicePlay::checkSubtitleTiming()
2885 eDebug("checkSubtitleTiming");
2886 if (!m_subtitle_widget)
2890 enum { TELETEXT, DVB } type;
2891 eDVBTeletextSubtitlePage page;
2892 eDVBSubtitlePage dvb_page;
2894 if (!m_subtitle_pages.empty())
2896 page = m_subtitle_pages.front();
2898 show_time = page.m_pts;
2900 else if (!m_dvb_subtitle_pages.empty())
2902 dvb_page = m_dvb_subtitle_pages.front();
2904 show_time = dvb_page.m_show_time;
2912 m_decoder->getPTS(0, pos);
2914 eDebug("%lld %lld", pos, show_time);
2915 int diff = show_time - pos;
2918 eDebug("[late (%d ms)]", -diff / 90);
2921 // if (diff > 900000)
2923 // eDebug("[invalid]");
2929 if (type == TELETEXT)
2931 eDebug("display teletext subtitle page %lld", show_time);
2932 m_subtitle_widget->setPage(page);
2933 m_subtitle_pages.pop_front();
2937 eDebug("display dvb subtitle Page %lld", show_time);
2938 m_subtitle_widget->setPage(dvb_page);
2939 m_dvb_subtitle_pages.pop_front();
2943 eDebug("start subtitle delay %d", diff / 90);
2944 m_subtitle_sync_timer->start(diff / 90, 1);
2950 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2952 if (m_subtitle_widget)
2956 m_decoder->getPTS(0, pos);
2957 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2958 m_dvb_subtitle_pages.push_back(p);
2959 checkSubtitleTiming();
2963 int eDVBServicePlay::getAC3Delay()
2966 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2968 return m_decoder->getAC3Delay();
2973 int eDVBServicePlay::getPCMDelay()
2976 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2978 return m_decoder->getPCMDelay();
2983 void eDVBServicePlay::setAC3Delay(int delay)
2986 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2988 m_decoder->setAC3Delay(delay);
2991 void eDVBServicePlay::setPCMDelay(int delay)
2994 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2996 m_decoder->setPCMDelay(delay);
2999 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3001 memcpy(&m_videoEventData, &event, sizeof(event));
3002 switch(event.type) {
3003 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3004 m_event((iPlayableService*)this, evVideoSizeChanged);
3006 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3007 m_event((iPlayableService*)this, evVideoFramerateChanged);
3009 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3010 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3017 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3023 PyObject *eDVBServicePlay::getStreamingData()
3025 eDVBServicePMTHandler::program program;
3026 if (m_service_handler.getProgramInfo(program))
3032 PyObject *r = program.createPythonObject();
3033 ePtr<iDVBDemux> demux;
3034 if (!m_service_handler.getDataDemux(demux))
3037 demux->getCADemuxID(demux_id);
3039 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
3046 DEFINE_REF(eDVBServicePlay)
3048 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3052 case iServiceInformation::sTransponderData:
3053 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3057 return iStaticServiceInformation::getInfoObject(ref, w);
3060 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");