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