bc793064aeb5b690a9d6927ac469e49aa7d2c0ba
[vuplus_dvbapp] / lib / dvb / dvb.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/base/filepush.h>
3 #include <lib/dvb/idvb.h>
4 #include <lib/dvb/dvb.h>
5 #include <lib/dvb/pmt.h>
6 #include <lib/dvb/sec.h>
7 #include <lib/dvb/specs.h>
8
9 #include <lib/dvb/fbc.h>
10 #include <lib/dvb/fcc.h>
11
12 #include <errno.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <sys/ioctl.h>
18
19 DEFINE_REF(eDVBRegisteredFrontend);
20 DEFINE_REF(eDVBRegisteredDemux);
21
22 DEFINE_REF(eDVBAllocatedFrontend);
23
24 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
25 {
26         m_fe->inc_use();
27 }
28
29 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
30 {
31         m_fe->dec_use();
32         if (m_fe->m_frontend->is_FBCTuner())
33         {
34                 eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
35                 if (fbcmng)
36                 {
37                         fbcmng->unLink(m_fe);
38                 }
39         }
40 }
41
42 DEFINE_REF(eDVBAllocatedDemux);
43
44 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
45 {
46         m_demux->m_inuse++;
47 }
48
49 eDVBAllocatedDemux::~eDVBAllocatedDemux()
50 {
51         --m_demux->m_inuse;
52 }
53
54 DEFINE_REF(eDVBResourceManager);
55
56 eDVBResourceManager *eDVBResourceManager::instance;
57
58 RESULT eDVBResourceManager::getInstance(ePtr<eDVBResourceManager> &ptr)
59 {
60         if (instance)
61         {
62                 ptr = instance;
63                 return 0;
64         }
65         return -1;
66 }
67
68 ePtr<eDVBResourceManager> NewResourceManagerPtr(void)
69 {
70         ePtr<eDVBResourceManager> ptr;
71         eDVBResourceManager::getInstance(ptr);
72         return ptr;
73 }
74
75 eDVBResourceManager::eDVBResourceManager()
76         :m_releaseCachedChannelTimer(eTimer::create(eApp))
77 {
78         avail = 1;
79         busy = 0;
80         m_sec = new eDVBSatelliteEquipmentControl(m_frontend, m_simulate_frontend);
81
82         if (!instance)
83                 instance = this;
84
85                 /* search available adapters... */
86
87                 // add linux devices
88
89         int num_adapter = 0;
90         while (eDVBAdapterLinux::exist(num_adapter))
91         {
92                 addAdapter(new eDVBAdapterLinux(num_adapter));
93                 num_adapter++;
94         }
95
96         int fd = open("/proc/stb/info/model", O_RDONLY);
97         char tmp[255];
98         int rd = fd >= 0 ? read(fd, tmp, 255) : 0;
99         if (fd >= 0)
100                 close(fd);
101
102         if (!strncmp(tmp, "dm7025\n", rd))
103                 m_boxtype = DM7025;
104         else if (!strncmp(tmp, "dm8000\n", rd))
105                 m_boxtype = DM8000;
106         else if (!strncmp(tmp, "dm800\n", rd))
107                 m_boxtype = DM800;
108         else if (!strncmp(tmp, "dm500hd\n", rd))
109                 m_boxtype = DM500HD;
110         else if (!strncmp(tmp, "dm800se\n", rd))
111                 m_boxtype = DM800SE;
112         else if (!strncmp(tmp, "dm7020hd\n", rd))
113                 m_boxtype = DM7020HD;
114         else {
115                 eDebug("boxtype detection via /proc/stb/info not possible... use fallback via demux count!\n");
116                 if (m_demux.size() == 3)
117                         m_boxtype = DM800;
118                 else if (m_demux.size() < 5)
119                         m_boxtype = DM7025;
120                 else
121                         m_boxtype = DM8000;
122         }
123
124         eDebug("found %zd adapter, %zd frontends(%zd sim) and %zd demux, boxtype %d",
125                 m_adapter.size(), m_frontend.size(), m_simulate_frontend.size(), m_demux.size(), m_boxtype);
126
127         eDVBCAService::registerChannelCallback(this);
128
129         m_fbc_mng = new eFBCTunerManager(this);
130
131         CONNECT(m_releaseCachedChannelTimer->timeout, eDVBResourceManager::releaseCachedChannel);
132 }
133
134 void eDVBResourceManager::feStateChanged()
135 {
136         int mask=0;
137         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
138                 if (i->m_inuse)
139                         mask |= ( 1 << i->m_frontend->getSlotID() );
140         /* emit */ frontendUseMaskChanged(mask);
141 }
142
143 DEFINE_REF(eDVBAdapterLinux);
144 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
145 {
146                 // scan frontends
147         int num_fe = 0;
148
149         eDebug("scanning for frontends..");
150         while (1)
151         {
152                 struct stat s;
153                 char filename[128];
154 #if HAVE_DVB_API_VERSION < 3
155                 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
156 #else
157                 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
158 #endif
159                 if (stat(filename, &s))
160                         break;
161                 eDVBFrontend *fe;
162
163                 {
164                         int ok = 0;
165                         fe = new eDVBFrontend(m_nr, num_fe, ok, true);
166                         if (ok)
167                                 m_simulate_frontend.push_back(ePtr<eDVBFrontend>(fe));
168                 }
169
170                 {
171                         int ok = 0;
172                         fe = new eDVBFrontend(m_nr, num_fe, ok, false, fe);
173                         if (ok)
174                                 m_frontend.push_back(ePtr<eDVBFrontend>(fe));
175                 }
176                 ++num_fe;
177         }
178
179                 // scan demux
180         int num_demux = 0;
181         while (1)
182         {
183                 struct stat s;
184                 char filename[128];
185 #if HAVE_DVB_API_VERSION < 3
186                 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
187 #else
188                 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
189 #endif
190                 if (stat(filename, &s))
191                         break;
192                 ePtr<eDVBDemux> demux;
193
194                 demux = new eDVBDemux(m_nr, num_demux);
195                 m_demux.push_back(demux);
196
197                 ++num_demux;
198         }
199 }
200
201 int eDVBAdapterLinux::getNumDemux()
202 {
203         return m_demux.size();
204 }
205
206 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
207 {
208         eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
209         while (nr && (i != m_demux.end()))
210         {
211                 --nr;
212                 ++i;
213         }
214
215         if (i != m_demux.end())
216                 demux = *i;
217         else
218                 return -1;
219
220         return 0;
221 }
222
223 int eDVBAdapterLinux::getNumFrontends()
224 {
225         return m_frontend.size();
226 }
227
228 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr, bool simulate)
229 {
230         eSmartPtrList<eDVBFrontend>::iterator i(simulate ? m_simulate_frontend.begin() : m_frontend.begin());
231         while (nr && (i != m_frontend.end()))
232         {
233                 --nr;
234                 ++i;
235         }
236
237         if (i != m_frontend.end())
238                 fe = *i;
239         else
240                 return -1;
241
242         return 0;
243 }
244
245 int eDVBAdapterLinux::exist(int nr)
246 {
247         struct stat s;
248         char filename[128];
249 #if HAVE_DVB_API_VERSION < 3
250         sprintf(filename, "/dev/dvb/card%d", nr);
251 #else
252         sprintf(filename, "/dev/dvb/adapter%d", nr);
253 #endif
254         if (!stat(filename, &s))
255                 return 1;
256         return 0;
257 }
258
259 eDVBResourceManager::~eDVBResourceManager()
260 {
261         if (instance == this)
262                 instance = 0;
263 }
264
265 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
266 {
267         int num_fe = adapter->getNumFrontends();
268         int num_demux = adapter->getNumDemux();
269
270         m_adapter.push_back(adapter);
271
272         int i;
273         for (i=0; i<num_demux; ++i)
274         {
275                 ePtr<eDVBDemux> demux;
276                 if (!adapter->getDemux(demux, i))
277                         m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
278         }
279
280         ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
281         for (i=0; i<num_fe; ++i)
282         {
283                 ePtr<eDVBFrontend> frontend;
284                 if (!adapter->getFrontend(frontend, i))
285                 {
286                         eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
287                         CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
288                         m_frontend.push_back(new_fe);
289                         frontend->setSEC(m_sec);
290                         // we must link all dvb-t frontends ( for active antenna voltage )
291                         if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
292                         {
293                                 if (prev_dvbt_frontend)
294                                 {
295                                         prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
296                                         frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
297                                 }
298                                 prev_dvbt_frontend = new_fe;
299                         }
300                 }
301         }
302
303         prev_dvbt_frontend = 0;
304         for (i=0; i<num_fe; ++i)
305         {
306                 ePtr<eDVBFrontend> frontend;
307                 if (!adapter->getFrontend(frontend, i, true))
308                 {
309                         eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
310 //                      CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
311                         m_simulate_frontend.push_back(new_fe);
312                         frontend->setSEC(m_sec);
313                         // we must link all dvb-t frontends ( for active antenna voltage )
314                         if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
315                         {
316                                 if (prev_dvbt_frontend)
317                                 {
318                                         prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
319                                         frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
320                                 }
321                                 prev_dvbt_frontend = new_fe;
322                         }
323                 }
324         }
325
326 }
327
328 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
329 {
330         if (!PyList_Check(list))
331         {
332                 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
333                 return NULL;
334         }
335         unsigned int assigned=0;
336         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
337         {
338                 int pos=0;
339                 while (pos < PyList_Size(list)) {
340                         ePyObject obj = PyList_GET_ITEM(list, pos++);
341                         if (!i->m_frontend->setSlotInfo(obj))
342                                 continue;
343                         ++assigned;
344                         break;
345                 }
346         }
347         if (assigned != m_frontend.size()) {
348                 char blasel[256];
349                 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations .. assigned %zd socket informations, but %d registered frontends!",
350                         m_frontend.size(), assigned);
351                 PyErr_SetString(PyExc_StandardError, blasel);
352                 return NULL;
353         }
354         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i)
355         {
356                 int pos=0;
357                 while (pos < PyList_Size(list)) {
358                         ePyObject obj = PyList_GET_ITEM(list, pos++);
359                         if (!i->m_frontend->setSlotInfo(obj))
360                                 continue;
361                         break;
362                 }
363         }
364         Py_RETURN_NONE;
365 }
366
367 bool eDVBResourceManager::frontendIsCompatible(int index, const char *type)
368 {
369         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
370         {
371                 if (i->m_frontend->getSlotID() == index)
372                 {
373                         if (!strcmp(type, "DVB-S2"))
374                         {
375                                 return i->m_frontend->supportsDeliverySystem(SYS_DVBS2, false);
376                         }
377                         else if (!strcmp(type, "DVB-S"))
378                         {
379                                 return i->m_frontend->supportsDeliverySystem(SYS_DVBS, false);
380                         }
381                         else if (!strcmp(type, "DVB-T2"))
382                         {
383                                 return i->m_frontend->supportsDeliverySystem(SYS_DVBT2, false);
384                         }
385                         else if (!strcmp(type, "DVB-T"))
386                         {
387                                 return i->m_frontend->supportsDeliverySystem(SYS_DVBT, false);
388                         }
389                         else if (!strcmp(type, "DVB-C"))
390                         {
391 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
392                                 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_A, false);
393 #else
394                                 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_AC, false);
395 #endif
396                         }
397                 }
398         }
399         return false;
400 }
401
402 void eDVBResourceManager::setFrontendType(int index, const char *type)
403 {
404         eDebug("[eDVBResourceManager::setFrontendType] index : %d, type : %s", index, type);
405
406         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
407         {
408                 if (i->m_frontend->getSlotID() == index)
409                 {
410                         std::vector<fe_delivery_system_t> whitelist;
411                         if (!strcmp(type, "DVB-S2") || !strcmp(type, "DVB-S"))
412                         {
413                                 whitelist.push_back(SYS_DVBS);
414                                 whitelist.push_back(SYS_DVBS2);
415                         }
416                         else if (!strcmp(type, "DVB-T2") || !strcmp(type, "DVB-T"))
417                         {
418                                 whitelist.push_back(SYS_DVBT);
419                                 whitelist.push_back(SYS_DVBT2);
420                         }
421                         else if (!strcmp(type, "DVB-C"))
422                         {
423 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
424                                 whitelist.push_back(SYS_DVBC_ANNEX_A);
425 #else
426                                 whitelist.push_back(SYS_DVBC_ANNEX_AC);
427 #endif
428                         }
429                         i->m_frontend->setDeliverySystemWhitelist(whitelist);
430                         break;
431                 }
432         }
433 }
434
435 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
436 {
437         eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
438         eDVBRegisteredFrontend *best = NULL;
439         int bestval = 0;
440         int foundone = 0;
441
442         int check_fbc_leaf_linkable = 0;
443         int current_fbc_setid = -1;
444         eDVBRegisteredFrontend *fbc_fe = NULL;
445         eDVBRegisteredFrontend *best_fbc_fe = NULL;
446
447         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
448         {
449                 int c = 0;
450                 fbc_fe = NULL;
451                 if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
452                 {
453                         int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
454                         if (fbc_setid != current_fbc_setid)
455                         {
456                                 current_fbc_setid = fbc_setid;
457                                 check_fbc_leaf_linkable = 0;
458                         }
459
460                         if (!check_fbc_leaf_linkable)
461                         {
462                                 c = m_fbc_mng->isCompatibleWith(feparm, *i, fbc_fe, simulate);
463                                 check_fbc_leaf_linkable = 1;
464                                 eDebug("[eDVBResourceManager::allocateFrontend] m_fbc_mng->isCompatibleWith slotid : %p (%d), fbc_fe : %p (%d), score : %d", (eDVBRegisteredFrontend *)*i,  i->m_frontend->getSlotID(), fbc_fe, fbc_fe?fbc_fe->m_frontend->getSlotID():-1, c);
465                         }
466                 }
467                 else
468                 {
469                         c = i->m_frontend->isCompatibleWith(feparm);
470                 }
471
472                 if (c)  /* if we have at least one frontend which is compatible with the source, flag this. */
473                         foundone = 1;
474
475                 if (!i->m_inuse)
476                 {
477                         eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
478                         if (c > bestval)
479                         {
480                                 bestval = c;
481                                 best = *i;
482                                 best_fbc_fe = fbc_fe;
483                         }
484                 }
485                 else
486                 {
487                         eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
488                 }
489
490                 eDVBRegisteredFrontend *tmp = *i;
491         }
492
493         if (best)
494         {
495                 if (best_fbc_fe)
496                 {
497                         m_fbc_mng->addLink(best, best_fbc_fe, simulate);
498                 }
499
500                 fe = new eDVBAllocatedFrontend(best);
501                 return 0;
502         }
503
504         fe = 0;
505
506         if (foundone)
507                 return errAllSourcesBusy;
508         else
509                 return errNoSourceFound;
510 }
511
512 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
513 {
514         int err = errNoSourceFound;
515         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
516                 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
517                 {
518                         // check if another slot linked to this is in use
519                         long tmp;
520                         i->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp);
521                         if ( tmp != -1 )
522                         {
523                                 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend *)tmp;
524                                 if (satpos_depends_to_fe->m_inuse)
525                                 {
526                                         eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
527                                         err = errAllSourcesBusy;
528                                         goto alloc_fe_by_id_not_possible;
529                                 }
530                         }
531                         else // check linked tuners
532                         {
533                                 i->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
534                                 while ( tmp != -1 )
535                                 {
536                                         eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) tmp;
537                                         if (next->m_inuse)
538                                         {
539                                                 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
540                                                 err = errAllSourcesBusy;
541                                                 goto alloc_fe_by_id_not_possible;
542                                         }
543                                         next->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
544                                 }
545                                 i->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
546                                 while ( tmp != -1 )
547                                 {
548                                         eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) tmp;
549                                         if (prev->m_inuse)
550                                         {
551                                                 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
552                                                 err = errAllSourcesBusy;
553                                                 goto alloc_fe_by_id_not_possible;
554                                         }
555                                         prev->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
556                                 }
557                         }
558                         fe = new eDVBAllocatedFrontend(i);
559                         return 0;
560                 }
561 alloc_fe_by_id_not_possible:
562         fe = 0;
563         return err;
564 }
565
566 #define capHoldDecodeReference 64
567
568 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int &cap)
569 {
570                 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
571                    never use the first one unless we need a decoding demux. */
572
573         eDebug("allocate demux");
574         eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
575
576         int n=0;
577
578         if (i == m_demux.end())
579                 return -1;
580
581         ePtr<eDVBRegisteredDemux> unused;
582
583         if (m_boxtype == DM800) // dm800
584         {
585                 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
586                 for (; i != m_demux.end(); ++i, ++n)
587                 {
588                         if (!i->m_inuse)
589                         {
590                                 if (!unused)
591                                         unused = i;
592                         }
593                         else
594                         {
595                                 if (fe)
596                                 {
597                                         if (i->m_adapter == fe->m_adapter && 
598                                             i->m_demux->getSource() == fe->m_frontend->getDVBID())
599                                         {
600                                                 demux = new eDVBAllocatedDemux(i);
601                                                 return 0;
602                                         }
603                                 }
604                                 else if (i->m_demux->getSource() == -1) // PVR
605                                 {
606                                         demux = new eDVBAllocatedDemux(i);
607                                         return 0;
608                                 }
609                         }
610                 }
611         }
612         else if (m_boxtype == DM7025) // ATI
613         {
614                 /* FIXME: hardware demux policy */
615                 if (!(cap & iDVBChannel::capDecode))
616                 {
617                         if (m_demux.size() > 2)  /* assumed to be true, otherwise we have lost anyway */
618                         {
619                                 ++i, ++n;
620                                 ++i, ++n;
621                         }
622                 }
623
624                 for (; i != m_demux.end(); ++i, ++n)
625                 {
626                         int is_decode = n < 2;
627
628                         int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
629
630                         if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
631                         {
632                                 if ((cap & iDVBChannel::capDecode) && !is_decode)
633                                         continue;
634                                 unused = i;
635                                 break;
636                         }
637                 }
638         }
639         else if (m_boxtype == DM8000 || m_boxtype == DM500HD || m_boxtype == DM800SE || m_boxtype == DM7020HD)
640         {
641                 iDVBAdapter *adapter = fe ? fe->m_adapter : m_adapter.begin(); /* look for a demux on the same adapter as the frontend, or the first adapter for dvr playback */
642                 int source = fe ? fe->m_frontend->getDVBID() : -1;
643                 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
644                 if (!fe)
645                 {
646                         /*
647                          * For pvr playback, start with the last demux.
648                          * On some hardware, we have less ca devices than demuxes,
649                          * so we should try to leave the first demuxes for live tv,
650                          * and start with the last for pvr playback
651                          */
652                         i = m_demux.end();
653                         --i;
654                 }
655                 while (i != m_demux.end())
656                 {
657                         if (i->m_adapter == adapter)
658                         {
659                                 if (!i->m_inuse)
660                                 {
661                                         /* mark the first unused demux, we'll use that when we do not find a better match */
662                                         if (!unused) unused = i;
663                                 }
664                                 else
665                                 {
666                                         /* demux is in use, see if we can share it */
667                                         if (source >= 0 && i->m_demux->getSource() == source)
668                                         {
669                                                 demux = new eDVBAllocatedDemux(i);
670                                                 return 0;
671                                         }
672                                 }
673                         }
674                         if (fe)
675                         {
676                                 ++i;
677                         }
678                         else
679                         {
680                                 --i;
681                         }
682                 }
683         }
684
685         if (unused)
686         {
687                 demux = new eDVBAllocatedDemux(unused);
688                 if (fe)
689                         demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
690                 else
691                         demux->get().setSourcePVR(0);
692                 return 0;
693         }
694
695         eDebug("demux not found");
696         return -1;
697 }
698
699 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
700 {
701         m_list = list;
702         return 0;
703 }
704
705 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
706 {
707         list = m_list;
708         if (list)
709                 return 0;
710         else
711                 return -ENOENT;
712 }
713
714 #define eDebugNoSimulate(x...) \
715         do { \
716                 if (!simulate) \
717                         eDebug(x); \
718         } while(0)
719
720 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
721 {
722                 /* first, check if a channel is already existing. */
723         std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
724
725         if (!simulate && m_cached_channel)
726         {
727                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
728                 if(channelid==cache_chan->getChannelID())
729                 {
730                         eDebug("use cached_channel");
731                         channel = m_cached_channel;
732                         return 0;
733                 }
734                 m_cached_channel_state_changed_conn.disconnect();
735                 m_cached_channel=0;
736                 m_releaseCachedChannelTimer->stop();
737         }
738
739         eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
740         for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
741         {
742                 eDebugNoSimulate("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
743                 if (i->m_channel_id == channelid)
744                 {
745                         eDebugNoSimulate("found shared channel..");
746                         channel = i->m_channel;
747                         return 0;
748                 }
749         }
750
751         /* no currently available channel is tuned to this channelid. create a new one, if possible. */
752
753         if (!m_list)
754         {
755                 eDebugNoSimulate("no channel list set!");
756                 return errNoChannelList;
757         }
758
759         ePtr<iDVBFrontendParameters> feparm;
760         if (m_list->getChannelFrontendData(channelid, feparm))
761         {
762                 eDebugNoSimulate("channel not found!");
763                 return errChannelNotInList;
764         }
765
766         /* allocate a frontend. */
767
768         ePtr<eDVBAllocatedFrontend> fe;
769
770         int err = allocateFrontend(fe, feparm, simulate);
771         if (err)
772                 return err;
773
774         RESULT res;
775         ePtr<eDVBChannel> ch = new eDVBChannel(this, fe);
776
777         res = ch->setChannel(channelid, feparm);
778         if (res)
779         {
780                 channel = 0;
781                 return errChidNotFound;
782         }
783
784         if (simulate)
785                 channel = ch;
786         else
787         {
788                 m_cached_channel = channel = ch;
789                 m_cached_channel_state_changed_conn =
790                         CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
791         }
792
793         return 0;
794 }
795
796 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
797 {
798         int state=0;
799         chan->getState(state);
800         switch (state)
801         {
802                 case iDVBChannel::state_release:
803                 case iDVBChannel::state_ok:
804                 {
805                         eDebug("stop release channel timer");
806                         m_releaseCachedChannelTimer->stop();
807                         break;
808                 }
809                 case iDVBChannel::state_last_instance:
810                 {
811                         eDebug("start release channel timer");
812                         m_releaseCachedChannelTimer->start(3000, true);
813                         break;
814                 }
815                 default: // ignore all other events
816                         break;
817         }
818 }
819
820 void eDVBResourceManager::releaseCachedChannel()
821 {
822         eDebug("release cached channel (timer timeout)");
823         m_cached_channel=0;
824 }
825
826 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
827 {
828         ePtr<eDVBAllocatedFrontend> fe;
829
830         if (m_cached_channel)
831         {
832                 m_cached_channel_state_changed_conn.disconnect();
833                 m_cached_channel=0;
834                 m_releaseCachedChannelTimer->stop();
835         }
836
837         int err = allocateFrontendByIndex(fe, slot_index);
838         if (err)
839                 return err;
840
841         channel = new eDVBChannel(this, fe);
842         return 0;
843 }
844
845 RESULT eDVBResourceManager::allocatePVRChannel(const eDVBChannelID &channelid, eUsePtr<iDVBPVRChannel> &channel)
846 {
847         ePtr<eDVBAllocatedDemux> demux;
848
849         if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
850         {
851                 m_cached_channel_state_changed_conn.disconnect();
852                 m_cached_channel=0;
853                 m_releaseCachedChannelTimer->stop();
854         }
855
856         ePtr<eDVBChannel> ch = new eDVBChannel(this, 0);
857         if (channelid)
858         {
859                 /*
860                  * user provided a channelid, with the clear intention for
861                  * this channel to be registered at the resource manager.
862                  * (allowing e.g. epgcache to be started)
863                  */
864                 ePtr<iDVBFrontendParameters> feparm;
865                 ch->setChannel(channelid, feparm);
866         }
867         channel = ch;
868         return 0;
869 }
870
871 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
872 {
873         ePtr<iDVBFrontend> fe;
874         if (!ch->getFrontend(fe))
875         {
876                 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
877                 if (frontend->is_simulate())
878                         m_active_simulate_channels.push_back(active_channel(chid, ch));
879                 else
880                 {
881                         m_active_channels.push_back(active_channel(chid, ch));
882                         /* emit */ m_channelAdded(ch);
883                 }
884         }
885         return 0;
886 }
887
888 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
889 {
890         ePtr<iDVBFrontend> fe;
891         if (!ch->getFrontend(fe))
892         {
893                 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
894                 std::list<active_channel> &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels;
895                 int cnt = 0;
896                 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end();)
897                 {
898                         if (i->m_channel == ch)
899                         {
900                                 i = active_channels.erase(i);
901                                 ++cnt;
902                         } else
903                                 ++i;
904                 }
905                 ASSERT(cnt == 1);
906                 if (cnt == 1)
907                         return 0;
908         }
909         return -ENOENT;
910 }
911
912 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
913 {
914         connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
915         return 0;
916 }
917
918 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
919 {
920         eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
921         ePtr<eDVBRegisteredFrontend> best;
922         int bestval = 0;
923         int check_fbc_leaf_linkable = 0;
924         int current_fbc_setid = -1;
925
926         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
927         {
928                 if (!i->m_inuse)
929                 {
930                         int c = 0;
931                         if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
932                         {
933                                 int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
934                                 if (fbc_setid != current_fbc_setid)
935                                 {
936                                         current_fbc_setid = fbc_setid;
937                                         check_fbc_leaf_linkable = 0;
938                                 }
939
940                                 if (!check_fbc_leaf_linkable)
941                                 {
942                                         eDVBRegisteredFrontend *dummy;
943                                         c = m_fbc_mng->isCompatibleWith(feparm, *i, dummy, simulate);
944                                         check_fbc_leaf_linkable = 1;
945                                 }
946                         }
947                         else
948                         {
949                                 c = i->m_frontend->isCompatibleWith(feparm);
950                         }
951                         if (c > bestval)
952                                 bestval = c;
953                 }
954         }
955         return bestval;
956 }
957
958 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid, int &system)
959 {
960         system = iDVBFrontend::feSatellite;
961         if (channellist)
962         {
963                 ePtr<iDVBFrontendParameters> feparm;
964                 if (!channellist->getChannelFrontendData(chid, feparm))
965                 {
966                         if (!feparm->getSystem(system))
967                         {
968                                 switch (system)
969                                 {
970                                         case iDVBFrontend::feSatellite:
971                                                 return 50000;
972                                         case iDVBFrontend::feCable:
973                                                 return 40000;
974                                         case iDVBFrontend::feTerrestrial:
975                                                 return 30000;
976                                         default:
977                                                 break;
978                                 }
979                         }
980                 }
981         }
982         return 0;
983 }
984
985 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, int &system, bool simulate)
986 {
987         std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
988         int ret = 0;
989         system = iDVBFrontend::feSatellite;
990         if (!simulate && m_cached_channel)
991         {
992                 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
993                 if(channelid==cache_chan->getChannelID())
994                         return tuner_type_channel_default(m_list, channelid, system);
995         }
996
997                 /* first, check if a channel is already existing. */
998 //      eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
999         for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
1000         {
1001 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
1002                 if (i->m_channel_id == channelid)
1003                 {
1004 //                      eDebug("found shared channel..");
1005                         return tuner_type_channel_default(m_list, channelid, system);
1006                 }
1007         }
1008
1009         int *decremented_cached_channel_fe_usecount=NULL,
1010                 *decremented_fe_usecount=NULL;
1011
1012         /* check FCC channels */
1013         std::vector<int*> fcc_decremented_fe_usecounts;
1014         std::map<eDVBChannelID, int> fcc_chids;
1015         int apply_to_ignore = 0;
1016         if (!eFCCServiceManager::getFCCChannelID(fcc_chids))
1017         {
1018                 for (std::map<eDVBChannelID, int>::iterator i(fcc_chids.begin()); i != fcc_chids.end(); ++i)
1019                 {
1020                         //eDebug("[eDVBResourceManager::canAllocateChannel] FCC NS : %08x, TSID : %04x, ONID : %04x", i->first.dvbnamespace.get(), i->first.transport_stream_id.get(), i->first.original_network_id.get());
1021                         if (ignore == i->first)
1022                         {
1023                                 apply_to_ignore = i->second;
1024                                 continue;
1025                         }
1026                         for (std::list<active_channel>::iterator ii(active_channels.begin()); ii != active_channels.end(); ++ii)
1027                         {
1028                                 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1029                                 if (ii->m_channel_id == i->first)
1030                                 {
1031                                         eDVBChannel *channel = (eDVBChannel*) &(*ii->m_channel);
1032
1033                                         int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
1034                                         check_usecount += i->second * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
1035                                         //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
1036                                         if (channel->getUseCount() == check_usecount)
1037                                         {
1038                                                 ePtr<iDVBFrontend> fe;
1039                                                 if (!ii->m_channel->getFrontend(fe))
1040                                                 {
1041                                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator iii(frontends.begin()); iii != frontends.end(); ++iii)
1042                                                         {
1043                                                                 if ( &(*fe) == &(*iii->m_frontend) )
1044                                                                 {
1045                                                                         //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : decrease fcc fe use_count! feid : %d (%d -> %d)", iii->m_frontend->getSlotID(), iii->m_inuse, iii->m_inuse-1);
1046                                                                         --iii->m_inuse;
1047                                                                         int *tmp_decremented_fe_usecount = &iii->m_inuse;
1048                                                                         fcc_decremented_fe_usecounts.push_back(tmp_decremented_fe_usecount);
1049                                                                         if (channel == &(*m_cached_channel))
1050                                                                                 decremented_cached_channel_fe_usecount = tmp_decremented_fe_usecount;
1051                                                                         break;
1052                                                                 }
1053                                                         }
1054                                                 }
1055                                         }
1056                                         break;
1057                                 }
1058                         }
1059                 }
1060         }
1061
1062         for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
1063         {
1064                 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1065 //              eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
1066                 if (i->m_channel_id == ignore)
1067                 {
1068                         eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
1069                         // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
1070                         // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
1071                         // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
1072                         // or 2 when the cached channel is not equal to the compared channel
1073                         int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
1074                         check_usecount += (apply_to_ignore+1) * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
1075                         //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
1076                         if (channel->getUseCount() == check_usecount)  // channel only used once..(except fcc)
1077                         {
1078                                 ePtr<iDVBFrontend> fe;
1079                                 if (!i->m_channel->getFrontend(fe))
1080                                 {
1081                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
1082                                         {
1083                                                 if ( &(*fe) == &(*ii->m_frontend) )
1084                                                 {
1085                                                         //eDebug("[eDVBResourceManager::canAllocateChannel] ignore : decrease fcc fe use_count! feid : %d (%d -> %d)", ii->m_frontend->getSlotID(), ii->m_inuse, ii->m_inuse-1);
1086                                                         --ii->m_inuse;
1087                                                         decremented_fe_usecount = &ii->m_inuse;
1088                                                         if (channel == &(*m_cached_channel))
1089                                                                 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
1090                                                         break;
1091                                                 }
1092                                         }
1093                                 }
1094                         }
1095                         break;
1096                 }
1097         }
1098
1099         if (!decremented_cached_channel_fe_usecount)
1100         {
1101                 if (m_cached_channel)
1102                 {
1103                         eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
1104                         if (channel->getUseCount() == 1)
1105                         {
1106                                 ePtr<iDVBFrontend> fe;
1107                                 if (!channel->getFrontend(fe))
1108                                 {
1109                                         eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1110                                         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
1111                                         {
1112                                                 if ( &(*fe) == &(*ii->m_frontend) )
1113                                                 {
1114                                                         --ii->m_inuse;
1115                                                         decremented_cached_channel_fe_usecount = &ii->m_inuse;
1116                                                         break;
1117                                                 }
1118                                         }
1119                                 }
1120                         }
1121                 }
1122         }
1123         else
1124                 decremented_cached_channel_fe_usecount=NULL;
1125
1126         ePtr<iDVBFrontendParameters> feparm;
1127
1128         if (!m_list)
1129         {
1130                 eDebug("no channel list set!");
1131                 goto error;
1132         }
1133
1134         if (m_list->getChannelFrontendData(channelid, feparm))
1135         {
1136                 eDebug("channel not found!");
1137                 goto error;
1138         }
1139         feparm->getSystem(system);
1140
1141         ret = canAllocateFrontend(feparm, simulate);
1142
1143 error:
1144         if (decremented_fe_usecount)
1145                 ++(*decremented_fe_usecount);
1146         if (decremented_cached_channel_fe_usecount)
1147                 ++(*decremented_cached_channel_fe_usecount);
1148         if (fcc_decremented_fe_usecounts.size())
1149         {
1150                 for (std::vector<int*>::iterator i(fcc_decremented_fe_usecounts.begin()); i != fcc_decremented_fe_usecounts.end(); ++i)
1151                 {
1152                         //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : increase fcc fe use_count!");
1153                         ++(**i);
1154                 }
1155         }
1156
1157         return ret;
1158 }
1159
1160 bool eDVBResourceManager::canMeasureFrontendInputPower()
1161 {
1162         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
1163         {
1164                 return i->m_frontend->readInputpower() >= 0;
1165         }
1166         return false;
1167 }
1168
1169 class eDVBChannelFilePush: public eFilePushThread
1170 {
1171 public:
1172         eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
1173         void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
1174
1175                         /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
1176                         /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
1177         void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
1178 protected:
1179         int m_iframe_search, m_iframe_state, m_pid;
1180         int m_timebase_change;
1181         int filterRecordData(const unsigned char *data, int len, size_t &current_span_remaining);
1182 };
1183
1184 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t &current_span_remaining)
1185 {
1186 #if 0
1187         if (m_timebase_change)
1188         {
1189                 eDebug("timebase change: %d", m_timebase_change);
1190                 int offset;
1191                 for (offset = 0; offset < len; offset += 188)
1192                 {
1193                         unsigned char *pkt = (unsigned char*)_data + offset;
1194                         if (pkt[1] & 0x40) /* pusi */
1195                         {
1196                                 if (pkt[3] & 0x20) // adaption field present?
1197                                         pkt += pkt[4] + 4 + 1;  /* skip adaption field and header */
1198                                 else
1199                                         pkt += 4; /* skip header */
1200                                 if (pkt[0] || pkt[1] || (pkt[2] != 1))
1201                                 {
1202                                         eWarning("broken startcode");
1203                                         continue;
1204                                 }
1205
1206                                 pts_t pts = 0;
1207
1208                                 if (pkt[7] & 0x80) // PTS present?
1209                                 {
1210                                         pts  = ((unsigned long long)(pkt[ 9]&0xE))  << 29;
1211                                         pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
1212                                         pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
1213                                         pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
1214                                         pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
1215
1216 #if 0
1217                                         off_t off = 0;
1218                                         RESULT r = m_tstools.fixupPTS(off, pts);
1219                                         if (r)
1220                                                 eWarning("fixup PTS while trickmode playback failed.\n");
1221 #endif
1222
1223                                         int sec = pts / 90000;
1224                                         int frm = pts % 90000;
1225                                         int min = sec / 60;
1226                                         sec %= 60;
1227                                         int hr = min / 60;
1228                                         min %= 60;
1229                                         int d = hr / 24;
1230                                         hr %= 24;
1231
1232 //                                      eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1233
1234                                         pts += 0x80000000LL;
1235                                         pts *= m_timebase_change;
1236                                         pts >>= 16;
1237
1238                                         sec = pts / 90000;
1239                                         frm = pts % 90000;
1240                                         min = sec / 60;
1241                                         sec %= 60;
1242                                         hr = min / 60;
1243                                         min %= 60;
1244                                         d = hr / 24;
1245                                         hr %= 24;
1246
1247 //                                      eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1248
1249                                         pkt[9] &= ~0xE;
1250                                         pkt[10] = 0;
1251                                         pkt[11] &= ~1;
1252                                         pkt[12] = 0;
1253                                         pkt[13] &= ~1;
1254
1255                                         pkt[9]  |= (pts >> 29) & 0xE;
1256                                         pkt[10] |= (pts >> 22) & 0xFF;
1257                                         pkt[11] |= (pts >> 14) & 0xFE;
1258                                         pkt[12] |= (pts >> 7) & 0xFF;
1259                                         pkt[13] |= (pts << 1) & 0xFE;
1260                                 }
1261                         }
1262                 }
1263         }
1264 #endif
1265
1266 #if 0
1267         if (!m_iframe_search)
1268                 return len;
1269
1270         unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
1271
1272 //      eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
1273
1274         unsigned char *d = data;
1275         while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
1276         {
1277                 int offset = d - data;
1278                 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
1279                 unsigned char *ts = data + ts_offset;
1280                 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
1281
1282                 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid))  /* picture start */
1283                 {
1284                         int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
1285                         d += 4;
1286
1287 //                      eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
1288
1289                         if (m_iframe_state == 1)
1290                         {
1291                                         /* we are allowing data, and stop allowing data on the next frame.
1292                                            we now found a frame. so stop here. */
1293                                 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1294                                 current_span_remaining = 0;
1295                                 m_iframe_state = 0;
1296                                 unsigned char *fts = ts + 188;
1297                                 while (fts < (data + len))
1298                                 {
1299                                         fts[1] |= 0x1f;
1300                                         fts[2] |= 0xff; /* drop packet */
1301                                         fts += 188;
1302                                 }
1303
1304                                 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1305                         } else
1306                         {
1307                                 if (picture_type != 1) /* we are only interested in I frames */
1308                                         continue;
1309
1310                                 unsigned char *fts = data;
1311                                 while (fts < ts)
1312                                 {
1313                                         fts[1] |= 0x1f;
1314                                         fts[2] |= 0xff; /* drop packet */
1315
1316                                         fts += 188;
1317                                 }
1318
1319                                 m_iframe_state = 1;
1320                         }
1321                 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1322                 {
1323                                 /* verify that this is actually a PES header, not just some ES data */
1324                         if (ts[1] & 0x40) /* PUSI set */
1325                         {
1326                                 int payload_start = 4;
1327                                 if (ts[3] & 0x20) /* adaptation field present */
1328                                         payload_start += ts[4] + 1; /* skip AF */
1329                                 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1330                                 {
1331                                         if (m_pid != pid)
1332                                         {
1333                                                 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1334                                                 m_pid = pid;
1335                                         }
1336                                 }
1337                         }
1338 //                      m_pid = 0x6e;
1339                         d += 4;
1340                 } else
1341                         d += 4; /* ignore */
1342         }
1343
1344         if (m_iframe_state == 1)
1345                 return len;
1346         else
1347                 return 0; /* we need find an iframe first */
1348 #else
1349         return len;
1350 #endif
1351 }
1352
1353 DEFINE_REF(eDVBChannel);
1354
1355 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1356 {
1357         m_frontend = frontend;
1358
1359         m_pvr_thread = 0;
1360         m_pvr_fd_dst = -1;
1361
1362         m_skipmode_n = m_skipmode_m = m_skipmode_frames = 0;
1363
1364         if (m_frontend)
1365                 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1366 }
1367
1368 eDVBChannel::~eDVBChannel()
1369 {
1370         if (m_channel_id)
1371                 m_mgr->removeChannel(this);
1372
1373         stopFile();
1374 }
1375
1376 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1377 {
1378         int state, ourstate = 0;
1379
1380                 /* if we are already in shutdown, don't change state. */
1381         if (m_state == state_release)
1382                 return;
1383
1384         if (fe->getState(state))
1385                 return;
1386
1387         if (state == iDVBFrontend::stateLock)
1388         {
1389                 eDebug("OURSTATE: ok");
1390                 ourstate = state_ok;
1391         } else if (state == iDVBFrontend::stateTuning)
1392         {
1393                 eDebug("OURSTATE: tuning");
1394                 ourstate = state_tuning;
1395         } else if (state == iDVBFrontend::stateLostLock)
1396         {
1397                         /* on managed channels, we try to retune in order to re-acquire lock. */
1398                 if (m_current_frontend_parameters)
1399                 {
1400                         eDebug("OURSTATE: lost lock, trying to retune");
1401                         ourstate = state_tuning;
1402                         m_frontend->get().tune(*m_current_frontend_parameters);
1403                 } else
1404                         /* on unmanaged channels, we don't do this. the client will do this. */
1405                 {
1406                         eDebug("OURSTATE: lost lock, unavailable now.");
1407                         ourstate = state_unavailable;
1408                 }
1409         } else if (state == iDVBFrontend::stateFailed)
1410         {
1411 #ifdef BUILD_VUPLUS
1412                 if (m_current_frontend_parameters)
1413                 {
1414                         eDebug("OURSTATE: lost lock, trying to retune");
1415                         ourstate = state_tuning;
1416                         m_frontend->get().tune(*m_current_frontend_parameters);
1417                 } 
1418                 else
1419                 {
1420                         eDebug("OURSTATE: failed");
1421                         ourstate = state_failed;
1422                 }
1423 #else
1424                 eDebug("OURSTATE: failed");
1425                 ourstate = state_failed;
1426 #endif          
1427         } else
1428                 eFatal("state unknown");
1429
1430         if (ourstate != m_state)
1431         {
1432                 m_state = ourstate;
1433                 m_stateChanged(this);
1434         }
1435 }
1436
1437 void eDVBChannel::pvrEvent(int event)
1438 {
1439         switch (event)
1440         {
1441         case eFilePushThread::evtEOF:
1442                 eDebug("eDVBChannel: End of file!");
1443                 m_event(this, evtEOF);
1444                 break;
1445         case eFilePushThread::evtUser: /* start */
1446                 eDebug("SOF");
1447                 m_event(this, evtSOF);
1448                 break;
1449         case eFilePushThread::evtUser+3: /* limit space */
1450                 eDebug("Too large file");
1451                 m_event(this, evtFailed+3);
1452                 break;
1453         }
1454 }
1455
1456 void eDVBChannel::cueSheetEvent(int event)
1457 {
1458                 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1459         if (!m_pvr_thread)
1460                 return;
1461         switch (event)
1462         {
1463         case eCueSheet::evtSeek:
1464                 eDebug("seek.");
1465                 flushPVR(m_cue->m_decoding_demux);
1466                 break;
1467         case eCueSheet::evtSkipmode:
1468         {
1469                 {
1470                         m_cue->m_lock.WrLock();
1471                         m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1472                         m_cue->m_lock.Unlock();
1473                         eRdLocker l(m_cue->m_lock);
1474                         if (m_cue->m_skipmode_ratio)
1475                         {
1476                                 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1477                                 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1478                                                 /* i agree that this might look a bit like black magic. */
1479                                 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1480                                 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1481                                 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1482                                 m_skipmode_frames_remainder = 0;
1483
1484                                 if (m_cue->m_skipmode_ratio < 0)
1485                                         m_skipmode_m -= m_skipmode_n;
1486
1487                                 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1488
1489                                 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1490                                 {
1491                                         eWarning("something is wrong with this calculation");
1492                                         m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1493                                 }
1494                         } else
1495                         {
1496                                 eDebug("skipmode ratio is 0, normal play");
1497                                 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1498                         }
1499                 }
1500                 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1501                 if (m_cue->m_skipmode_ratio != 0)
1502                         m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1503                 else
1504                         m_pvr_thread->setTimebaseChange(0); /* normal playback */
1505                 eDebug("flush pvr");
1506                 flushPVR(m_cue->m_decoding_demux);
1507                 eDebug("done");
1508                 break;
1509         }
1510         case eCueSheet::evtSpanChanged:
1511         {
1512                 m_source_span.clear();
1513                 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1514                 {
1515                         off_t offset_in, offset_out;
1516                         pts_t pts_in = i->first, pts_out = i->second;
1517                         if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1518                         {
1519                                 eDebug("span translation failed.\n");
1520                                 continue;
1521                         }
1522                         eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1523                         m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1524                 }
1525                 break;
1526         }
1527         }
1528 }
1529
1530         /* align toward zero */
1531 static inline long long align(long long x, int align)
1532 {
1533         int sign = x < 0;
1534
1535         if (sign)
1536                 x = -x;
1537
1538         x -= x % align;
1539
1540         if (sign)
1541                 x = -x;
1542
1543         return x;
1544 }
1545
1546         /* align toward zero */
1547 static inline long long align_with_len(long long x, int align, size_t &len)
1548 {
1549         int sign = x < 0;
1550
1551         if (sign)
1552                 x = -x;
1553
1554         int r = x % align;
1555         x -= r;
1556         len += r;
1557
1558         if (sign)
1559                 x = -x;
1560
1561         return x;
1562 }
1563
1564         /* remember, this gets called from another thread. */
1565 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1566 {
1567         const int blocksize = 188;
1568         unsigned int max = align(10*1024*1024, blocksize);
1569         current_offset = align(current_offset, blocksize);
1570
1571         if (!m_cue)
1572         {
1573                 eDebug("no cue sheet. forcing normal play");
1574                 start = current_offset;
1575                 size = max;
1576                 return;
1577         }
1578
1579         if (m_skipmode_n)
1580         {
1581                 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1582                 max = align(m_skipmode_n, blocksize);
1583         }
1584
1585         eDebug("getNextSourceSpan, current offset is %08lld, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1586         int frame_skip_success = 0;
1587
1588         if (m_skipmode_m)
1589         {
1590                 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1591                 eDebug("we are at %lld, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1592                 size_t iframe_len;
1593                 off_t iframe_start = current_offset;
1594                 int frames_skipped = frames_to_skip;
1595                 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1596                 {
1597                         m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1598                         eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1599                         current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1600                         max = align(iframe_len + 187, blocksize);
1601                         frame_skip_success = 1;
1602                 } else
1603                 {
1604                         m_skipmode_frames_remainder = 0;
1605                         eDebug("frame skipping failed, reverting to byte-skipping");
1606                 }
1607         }
1608         
1609         if (!frame_skip_success)
1610         {
1611                 current_offset += align(m_skipmode_m, blocksize);
1612                 if(current_offset < 0)
1613                         current_offset = 0;
1614                 else
1615                 {
1616                         if (m_skipmode_m)
1617                         {
1618                                 eDebug("we are at %lld, and we try to find the iframe here:", current_offset);
1619                                 size_t iframe_len;
1620                                 off_t start_offset = current_offset;
1621                                 off_t new_offset = start_offset;
1622                                 int direction = (m_skipmode_m < 0) ? -1 : +1;
1623                                 if (m_tstools.findFrame(start_offset, new_offset, iframe_len, direction))
1624                                         eDebug("failed");
1625                                 else
1626                                 {
1627                                         current_offset = align_with_len(new_offset, blocksize, iframe_len);
1628                                         max = align(iframe_len, blocksize);
1629                                 }
1630                         }
1631                 }
1632         }
1633
1634         m_cue->m_lock.RdLock();
1635
1636         while (!m_cue->m_seek_requests.empty())
1637         {
1638                 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1639                 m_cue->m_lock.Unlock();
1640                 m_cue->m_lock.WrLock();
1641                 m_cue->m_seek_requests.pop_front();
1642                 m_cue->m_lock.Unlock();
1643                 m_cue->m_lock.RdLock();
1644                 int relative = seek.first;
1645                 pts_t pts = seek.second;
1646
1647                 pts_t now = 0;
1648                 if (relative)
1649                 {
1650                         if (!m_cue->m_decoder)
1651                         {
1652                                 eDebug("no decoder - can't seek relative");
1653                                 continue;
1654                         }
1655                         if (m_cue->m_decoder->getPTS(0, now))
1656                         {
1657                                 eDebug("decoder getPTS failed, can't seek relative");
1658                                 continue;
1659                         }
1660                         if (!m_cue->m_decoding_demux)
1661                         {
1662                                 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1663                                 start = current_offset;
1664                                 size = max;
1665                                 continue;
1666                         }
1667                         if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1668                         {
1669                                 eDebug("seekTo: getCurrentPosition failed!");
1670                                 continue;
1671                         }
1672                 } else if (pts < 0) /* seek relative to end */
1673                 {
1674                         pts_t len;
1675                         if (!getLength(len))
1676                         {
1677                                 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1678                                 pts += len;
1679                         } else
1680                         {
1681                                 eWarning("getLength failed - can't seek relative to end!");
1682                                 continue;
1683                         }
1684                 }
1685
1686                 if (relative == 1) /* pts relative */
1687                 {
1688                         pts += now;
1689                         if (pts < 0)
1690                                 pts = 0;
1691                 }
1692
1693                 if (relative != 2)
1694                         if (pts < 0)
1695                                 pts = 0;
1696
1697                 if (relative == 2) /* AP relative */
1698                 {
1699                         eDebug("AP relative seeking: %lld, at %lld", pts, now);
1700                         pts_t nextap;
1701                         if (m_tstools.getNextAccessPoint(nextap, now, pts))
1702                         {
1703                                 pts = now - 90000; /* approx. 1s */
1704                                 eDebug("AP relative seeking failed!");
1705                         } else
1706                         {
1707                                 pts = nextap;
1708                                 eDebug("next ap is %llx\n", pts);
1709                         }
1710                 }
1711
1712                 off_t offset = 0;
1713                 if (m_tstools.getOffset(offset, pts, -1))
1714                 {
1715                         eDebug("get offset for pts=%lld failed!", pts);
1716                         continue;
1717                 }
1718                 
1719                 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1720                 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1721         }
1722
1723         m_cue->m_lock.Unlock();
1724
1725         for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1726         {
1727                 long long aligned_start = align(i->first, blocksize);
1728                 long long aligned_end = align(i->second, blocksize);
1729
1730                 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1731                 {
1732                         start = current_offset;
1733                                 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1734                         if ((aligned_end - current_offset) > max)
1735                                 size = max;
1736                         else
1737                                 size = aligned_end - current_offset;
1738                         eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1739                         return;
1740                 }
1741                 if (current_offset < aligned_start)
1742                 {
1743                                 /* ok, our current offset is in an 'out' zone. */
1744                         if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1745                         {
1746                                         /* in normal playback, just start at the next zone. */
1747                                 start = i->first;
1748
1749                                         /* size is not 64bit! */
1750                                 if ((i->second - i->first) > max)
1751                                         size = max;
1752                                 else
1753                                         size = aligned_end - aligned_start;
1754
1755                                 eDebug("skip");
1756                                 if (m_skipmode_m < 0)
1757                                 {
1758                                         eDebug("reached SOF");
1759                                                 /* reached SOF */
1760                                         m_skipmode_m = 0;
1761                                         m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1762                                 }
1763                         } else
1764                         {
1765                                         /* when skipping reverse, however, choose the zone before. */
1766                                 --i;
1767                                 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1768                                 size_t len;
1769
1770                                 aligned_start = align(i->first, blocksize);
1771                                 aligned_end = align(i->second, blocksize);
1772
1773                                 if ((aligned_end - aligned_start) > max)
1774                                         len = max;
1775                                 else
1776                                         len = aligned_end - aligned_start;
1777
1778                                 start = aligned_end - len;
1779                                 eDebug("skipping to %llx, %zd", start, len);
1780                         }
1781
1782                         eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1783                         return;
1784                 }
1785         }
1786
1787         if(current_offset <0)
1788                 current_offset =0;
1789         if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1790         {
1791                 eDebug("reached SOF");
1792                 m_skipmode_m = 0;
1793                 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1794         }
1795         if (m_source_span.empty())
1796         {
1797                 start = current_offset;
1798                 size = max;
1799                 eDebug("NO CUESHEET. (%08lld, %zd)", start, size);
1800         } else
1801         {
1802                 start = current_offset;
1803                 size = 0;
1804         }
1805         return;
1806 }
1807
1808 void eDVBChannel::AddUse()
1809 {
1810         if (++m_use_count > 1 && m_state == state_last_instance)
1811         {
1812                 m_state = state_ok;
1813                 m_stateChanged(this);
1814         }
1815 }
1816
1817 void eDVBChannel::ReleaseUse()
1818 {
1819         if (!--m_use_count)
1820         {
1821                 m_state = state_release;
1822                 m_stateChanged(this);
1823         }
1824         else if (m_use_count == 1)
1825         {
1826                 m_state = state_last_instance;
1827                 m_stateChanged(this);
1828         }
1829 }
1830
1831 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1832 {
1833         if (m_channel_id)
1834                 m_mgr->removeChannel(this);
1835
1836         if (!channelid)
1837                 return 0;
1838
1839         m_channel_id = channelid;
1840         m_mgr->addChannel(channelid, this);
1841
1842         if (!m_frontend)
1843         {
1844                 /* no frontend, no need to tune (must be a streamed service) */
1845                 return 0;
1846         }
1847
1848         m_state = state_tuning;
1849                         /* if tuning fails, shutdown the channel immediately. */
1850         int res;
1851         res = m_frontend->get().tune(*feparm);
1852         m_current_frontend_parameters = feparm;
1853
1854         if (res)
1855         {
1856                 m_state = state_release;
1857                 m_stateChanged(this);
1858                 return res;
1859         }
1860
1861         return 0;
1862 }
1863
1864 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1865 {
1866         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1867         return 0;
1868 }
1869
1870 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1871 {
1872         connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1873         return 0;
1874 }
1875
1876 RESULT eDVBChannel::getState(int &state)
1877 {
1878         state = m_state;
1879         return 0;
1880 }
1881
1882 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1883 {
1884         return -1;
1885 }
1886
1887 void eDVBChannel::SDTready(int result)
1888 {
1889         ePyObject args = PyTuple_New(2), ret;
1890         bool ok=false;
1891         if (!result)
1892         {
1893                 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1894                 {
1895                         ok = true;
1896                         PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1897                         PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1898                         break;
1899                 }
1900         }
1901         if (!ok)
1902         {
1903                 PyTuple_SET_ITEM(args, 0, Py_None);
1904                 PyTuple_SET_ITEM(args, 1, Py_None);
1905                 Py_INCREF(Py_None);
1906                 Py_INCREF(Py_None);
1907         }
1908         ret = PyObject_CallObject(m_tsid_onid_callback, args);
1909         if (ret)
1910                 Py_DECREF(ret);
1911         Py_DECREF(args);
1912         Py_DECREF(m_tsid_onid_callback);
1913         m_tsid_onid_callback = ePyObject();
1914         m_tsid_onid_demux = 0;
1915         m_SDT = 0;
1916 }
1917
1918 int eDVBChannel::reserveDemux()
1919 {
1920         ePtr<iDVBDemux> dmx;
1921         if (!getDemux(dmx, 0))
1922         {
1923                 uint8_t id;
1924                 if (!dmx->getCADemuxID(id))
1925                         return id;
1926         }
1927         return -1;
1928 }
1929
1930 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1931 {
1932         if (PyCallable_Check(callback))
1933         {
1934                 if (!getDemux(m_tsid_onid_demux, 0))
1935                 {
1936                         m_SDT = new eTable<ServiceDescriptionSection>;
1937                         CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1938                         if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1939                         {
1940                                 m_tsid_onid_demux = 0;
1941                                 m_SDT = 0;
1942                         }
1943                         else
1944                         {
1945                                 Py_INCREF(callback);
1946                                 m_tsid_onid_callback = callback;
1947                                 return 0;
1948                         }
1949                 }
1950         }
1951         return -1;
1952 }
1953
1954 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1955 {
1956         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1957
1958         if (m_frontend == NULL)
1959         {
1960                 /* in dvr mode, we have to stick to a single demux (the one connected to our dvr device) */
1961                 our_demux = m_decoder_demux ? m_decoder_demux : m_demux;
1962         }
1963
1964         if (!our_demux)
1965         {
1966                 demux = 0;
1967
1968                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1969                         return -1;
1970
1971                 demux = *our_demux;
1972
1973                 /* don't hold a reference to the decoding demux, we don't need it. */
1974
1975                 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1976                    the refcount is lost. thus, decoding demuxes are never allocated.
1977
1978                    this poses a big problem for PiP. */
1979
1980                 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1981                         ;
1982                 else if (cap & capDecode)
1983                         our_demux = 0;
1984         }
1985         else
1986                 demux = *our_demux;
1987
1988         return 0;
1989 }
1990
1991 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1992 {
1993         frontend = 0;
1994         if (!m_frontend)
1995                 return -ENODEV;
1996         frontend = &m_frontend->get();
1997         if (frontend)
1998                 return 0;
1999         return -ENODEV;
2000 }
2001
2002 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> &param)
2003 {
2004         param = m_current_frontend_parameters;
2005         return 0;
2006 }
2007
2008 RESULT eDVBChannel::playFile(const char *file)
2009 {
2010         eRawFile *f = new eRawFile();
2011         ePtr<iTsSource> source = f;
2012
2013         if (f->open(file) < 0)
2014         {
2015                 eDebug("can't open PVR file %s (%m)", file);
2016                 return -ENOENT;
2017         }
2018
2019         return playSource(source, file);
2020 }
2021
2022 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
2023 {
2024         ASSERT(!m_frontend);
2025         if (m_pvr_thread)
2026         {
2027                 m_pvr_thread->stop();
2028                 delete m_pvr_thread;
2029                 m_pvr_thread = 0;
2030         }
2031
2032         if (!source->valid() && !source->isStream())
2033         {
2034                 eDebug("PVR source is not valid!");
2035                 return -ENOENT;
2036         }
2037
2038         m_source = source;
2039         m_tstools.setSource(m_source, streaminfo_file);
2040
2041                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
2042                    THEN DO A REAL FIX HERE! */
2043
2044         if (m_pvr_fd_dst < 0)
2045         {
2046                 /* (this codepath needs to be improved anyway.) */
2047 #if HAVE_DVB_API_VERSION < 3
2048                 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
2049                 if (m_pvr_fd_dst < 0)
2050                 {
2051                         eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
2052                         return -ENODEV;
2053                 }
2054 #else
2055                 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
2056                 if (demux)
2057                 {
2058                         m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
2059                         if (m_pvr_fd_dst < 0)
2060                         {
2061                                 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
2062                                 return -ENODEV;
2063                         }
2064                 }
2065                 else
2066                 {
2067                         eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
2068                         return -ENODEV;
2069                 }
2070 #endif
2071         }
2072
2073         m_pvr_thread = new eDVBChannelFilePush();
2074         m_pvr_thread->enablePVRCommit(1);
2075         /* If the source specifies a length, it's a file. If not, it's a stream */
2076         m_pvr_thread->setStreamMode(m_source->isStream());
2077         m_pvr_thread->setScatterGather(this);
2078
2079         m_event(this, evtPreStart);
2080
2081         m_pvr_thread->start(m_source, m_pvr_fd_dst);
2082         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
2083
2084         m_state = state_ok;
2085         m_stateChanged(this);
2086
2087         return 0;
2088 }
2089
2090 void eDVBChannel::stopSource()
2091 {
2092         if (m_pvr_thread)
2093         {
2094                 m_pvr_thread->stop();
2095                 delete m_pvr_thread;
2096                 m_pvr_thread = 0;
2097         }
2098         if (m_pvr_fd_dst >= 0)
2099         {
2100                 ::close(m_pvr_fd_dst);
2101                 m_pvr_fd_dst = -1;
2102         }
2103
2104         m_source = NULL;
2105         m_tstools.setSource(m_source);
2106 }
2107
2108 void eDVBChannel::stopFile()
2109 {
2110         stopSource();
2111 }
2112
2113 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
2114 {
2115         m_conn_cueSheetEvent = 0;
2116         m_cue = cuesheet;
2117         if (m_cue)
2118                 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
2119 }
2120
2121 RESULT eDVBChannel::getLength(pts_t &len)
2122 {
2123         return m_tstools.calcLen(len);
2124 }
2125
2126 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
2127 {
2128         if (!decoding_demux)
2129                 return -1;
2130
2131         pts_t now;
2132
2133         int r;
2134
2135         if (mode == 0) /* demux */
2136         {
2137                 r = decoding_demux->getSTC(now, 0);
2138                 if (r)
2139                 {
2140                         eDebug("demux getSTC failed");
2141                         return -1;
2142                 }
2143         } else
2144                 now = pos; /* fixup supplied */
2145
2146         r = m_tstools.fixupPTS(m_source ? m_source->offset() : 0, now);
2147         if (r)
2148         {
2149                 eDebug("fixup PTS failed");
2150                 return -1;
2151         }
2152
2153         pos = now;
2154
2155         return 0;
2156 }
2157
2158 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
2159 {
2160                         /* when seeking, we have to ensure that all buffers are flushed.
2161                            there are basically 3 buffers:
2162                            a.) the filepush's internal buffer
2163                            b.) the PVR buffer (before demux)
2164                            c.) the ratebuffer (after demux)
2165
2166                            it's important to clear them in the correct order, otherwise
2167                            the ratebuffer (for example) would immediately refill from
2168                            the not-yet-flushed PVR buffer.
2169                         */
2170
2171         m_pvr_thread->pause();
2172                 /* flush internal filepush buffer */
2173         m_pvr_thread->flush();
2174                 /* HACK: flush PVR buffer */
2175         ::ioctl(m_pvr_fd_dst, 0);
2176
2177                 /* flush ratebuffers (video, audio) */
2178         if (decoding_demux)
2179                 decoding_demux->flush();
2180
2181                 /* demux will also flush all decoder.. */
2182                 /* resume will re-query the SG */
2183         m_pvr_thread->resume();
2184 }
2185
2186 DEFINE_REF(eCueSheet);
2187
2188 eCueSheet::eCueSheet()
2189 {
2190         m_skipmode_ratio = 0;
2191 }
2192
2193 void eCueSheet::seekTo(int relative, const pts_t &pts)
2194 {
2195         m_lock.WrLock();
2196         m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
2197         m_lock.Unlock();
2198         m_event(evtSeek);
2199 }
2200
2201 void eCueSheet::clear()
2202 {
2203         m_lock.WrLock();
2204         m_spans.clear();
2205         m_lock.Unlock();
2206 }
2207
2208 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
2209 {
2210         ASSERT(begin < end);
2211         m_lock.WrLock();
2212         m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
2213         m_lock.Unlock();
2214 }
2215
2216 void eCueSheet::commitSpans()
2217 {
2218         m_event(evtSpanChanged);
2219 }
2220
2221 void eCueSheet::setSkipmode(const pts_t &ratio)
2222 {
2223         m_lock.WrLock();
2224         m_skipmode_ratio = ratio;
2225         m_lock.Unlock();
2226         m_event(evtSkipmode);
2227 }
2228
2229 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
2230 {
2231         m_decoding_demux = demux;
2232         m_decoder = decoder;
2233 }
2234
2235 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
2236 {
2237         connection = new eConnection(this, m_event.connect(event));
2238         return 0;
2239 }