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