0c36b7ccf961139dab9558ad0173c889011170fa
[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         }
1430 }
1431
1432 void eDVBChannel::cueSheetEvent(int event)
1433 {
1434                 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1435         if (!m_pvr_thread)
1436                 return;
1437         switch (event)
1438         {
1439         case eCueSheet::evtSeek:
1440                 eDebug("seek.");
1441                 flushPVR(m_cue->m_decoding_demux);
1442                 break;
1443         case eCueSheet::evtSkipmode:
1444         {
1445                 {
1446                         m_cue->m_lock.WrLock();
1447                         m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1448                         m_cue->m_lock.Unlock();
1449                         eRdLocker l(m_cue->m_lock);
1450                         if (m_cue->m_skipmode_ratio)
1451                         {
1452                                 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1453                                 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1454                                                 /* i agree that this might look a bit like black magic. */
1455                                 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1456                                 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1457                                 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1458                                 m_skipmode_frames_remainder = 0;
1459
1460                                 if (m_cue->m_skipmode_ratio < 0)
1461                                         m_skipmode_m -= m_skipmode_n;
1462
1463                                 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1464
1465                                 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1466                                 {
1467                                         eWarning("something is wrong with this calculation");
1468                                         m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1469                                 }
1470                         } else
1471                         {
1472                                 eDebug("skipmode ratio is 0, normal play");
1473                                 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1474                         }
1475                 }
1476                 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1477                 if (m_cue->m_skipmode_ratio != 0)
1478                         m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1479                 else
1480                         m_pvr_thread->setTimebaseChange(0); /* normal playback */
1481                 eDebug("flush pvr");
1482                 flushPVR(m_cue->m_decoding_demux);
1483                 eDebug("done");
1484                 break;
1485         }
1486         case eCueSheet::evtSpanChanged:
1487         {
1488                 m_source_span.clear();
1489                 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1490                 {
1491                         off_t offset_in, offset_out;
1492                         pts_t pts_in = i->first, pts_out = i->second;
1493                         if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1494                         {
1495                                 eDebug("span translation failed.\n");
1496                                 continue;
1497                         }
1498                         eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1499                         m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1500                 }
1501                 break;
1502         }
1503         }
1504 }
1505
1506         /* align toward zero */
1507 static inline long long align(long long x, int align)
1508 {
1509         int sign = x < 0;
1510
1511         if (sign)
1512                 x = -x;
1513
1514         x -= x % align;
1515
1516         if (sign)
1517                 x = -x;
1518
1519         return x;
1520 }
1521
1522         /* align toward zero */
1523 static inline long long align_with_len(long long x, int align, size_t &len)
1524 {
1525         int sign = x < 0;
1526
1527         if (sign)
1528                 x = -x;
1529
1530         int r = x % align;
1531         x -= r;
1532         len += r;
1533
1534         if (sign)
1535                 x = -x;
1536
1537         return x;
1538 }
1539
1540         /* remember, this gets called from another thread. */
1541 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1542 {
1543         const int blocksize = 188;
1544         unsigned int max = align(10*1024*1024, blocksize);
1545         current_offset = align(current_offset, blocksize);
1546
1547         if (!m_cue)
1548         {
1549                 eDebug("no cue sheet. forcing normal play");
1550                 start = current_offset;
1551                 size = max;
1552                 return;
1553         }
1554
1555         if (m_skipmode_n)
1556         {
1557                 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1558                 max = align(m_skipmode_n, blocksize);
1559         }
1560
1561         eDebug("getNextSourceSpan, current offset is %08lld, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1562         int frame_skip_success = 0;
1563
1564         if (m_skipmode_m)
1565         {
1566                 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1567                 eDebug("we are at %lld, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1568                 size_t iframe_len;
1569                 off_t iframe_start = current_offset;
1570                 int frames_skipped = frames_to_skip;
1571                 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1572                 {
1573                         m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1574                         eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1575                         current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1576                         max = align(iframe_len + 187, blocksize);
1577                         frame_skip_success = 1;
1578                 } else
1579                 {
1580                         m_skipmode_frames_remainder = 0;
1581                         eDebug("frame skipping failed, reverting to byte-skipping");
1582                 }
1583         }
1584         
1585         if (!frame_skip_success)
1586         {
1587                 current_offset += align(m_skipmode_m, blocksize);
1588                 if(current_offset < 0)
1589                         current_offset = 0;
1590                 else
1591                 {
1592                         if (m_skipmode_m)
1593                         {
1594                                 eDebug("we are at %lld, and we try to find the iframe here:", current_offset);
1595                                 size_t iframe_len;
1596                                 off_t start_offset = current_offset;
1597                                 off_t new_offset = start_offset;
1598                                 int direction = (m_skipmode_m < 0) ? -1 : +1;
1599                                 if (m_tstools.findFrame(start_offset, new_offset, iframe_len, direction))
1600                                         eDebug("failed");
1601                                 else
1602                                 {
1603                                         current_offset = align_with_len(new_offset, blocksize, iframe_len);
1604                                         max = align(iframe_len, blocksize);
1605                                 }
1606                         }
1607                 }
1608         }
1609
1610         m_cue->m_lock.RdLock();
1611
1612         while (!m_cue->m_seek_requests.empty())
1613         {
1614                 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1615                 m_cue->m_lock.Unlock();
1616                 m_cue->m_lock.WrLock();
1617                 m_cue->m_seek_requests.pop_front();
1618                 m_cue->m_lock.Unlock();
1619                 m_cue->m_lock.RdLock();
1620                 int relative = seek.first;
1621                 pts_t pts = seek.second;
1622
1623                 pts_t now = 0;
1624                 if (relative)
1625                 {
1626                         if (!m_cue->m_decoder)
1627                         {
1628                                 eDebug("no decoder - can't seek relative");
1629                                 continue;
1630                         }
1631                         if (m_cue->m_decoder->getPTS(0, now))
1632                         {
1633                                 eDebug("decoder getPTS failed, can't seek relative");
1634                                 continue;
1635                         }
1636                         if (!m_cue->m_decoding_demux)
1637                         {
1638                                 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1639                                 start = current_offset;
1640                                 size = max;
1641                                 continue;
1642                         }
1643                         if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1644                         {
1645                                 eDebug("seekTo: getCurrentPosition failed!");
1646                                 continue;
1647                         }
1648                 } else if (pts < 0) /* seek relative to end */
1649                 {
1650                         pts_t len;
1651                         if (!getLength(len))
1652                         {
1653                                 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1654                                 pts += len;
1655                         } else
1656                         {
1657                                 eWarning("getLength failed - can't seek relative to end!");
1658                                 continue;
1659                         }
1660                 }
1661
1662                 if (relative == 1) /* pts relative */
1663                 {
1664                         pts += now;
1665                         if (pts < 0)
1666                                 pts = 0;
1667                 }
1668
1669                 if (relative != 2)
1670                         if (pts < 0)
1671                                 pts = 0;
1672
1673                 if (relative == 2) /* AP relative */
1674                 {
1675                         eDebug("AP relative seeking: %lld, at %lld", pts, now);
1676                         pts_t nextap;
1677                         if (m_tstools.getNextAccessPoint(nextap, now, pts))
1678                         {
1679                                 pts = now - 90000; /* approx. 1s */
1680                                 eDebug("AP relative seeking failed!");
1681                         } else
1682                         {
1683                                 pts = nextap;
1684                                 eDebug("next ap is %llx\n", pts);
1685                         }
1686                 }
1687
1688                 off_t offset = 0;
1689                 if (m_tstools.getOffset(offset, pts, -1))
1690                 {
1691                         eDebug("get offset for pts=%lld failed!", pts);
1692                         continue;
1693                 }
1694                 
1695                 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1696                 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1697         }
1698
1699         m_cue->m_lock.Unlock();
1700
1701         for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1702         {
1703                 long long aligned_start = align(i->first, blocksize);
1704                 long long aligned_end = align(i->second, blocksize);
1705
1706                 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1707                 {
1708                         start = current_offset;
1709                                 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1710                         if ((aligned_end - current_offset) > max)
1711                                 size = max;
1712                         else
1713                                 size = aligned_end - current_offset;
1714                         eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1715                         return;
1716                 }
1717                 if (current_offset < aligned_start)
1718                 {
1719                                 /* ok, our current offset is in an 'out' zone. */
1720                         if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1721                         {
1722                                         /* in normal playback, just start at the next zone. */
1723                                 start = i->first;
1724
1725                                         /* size is not 64bit! */
1726                                 if ((i->second - i->first) > max)
1727                                         size = max;
1728                                 else
1729                                         size = aligned_end - aligned_start;
1730
1731                                 eDebug("skip");
1732                                 if (m_skipmode_m < 0)
1733                                 {
1734                                         eDebug("reached SOF");
1735                                                 /* reached SOF */
1736                                         m_skipmode_m = 0;
1737                                         m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1738                                 }
1739                         } else
1740                         {
1741                                         /* when skipping reverse, however, choose the zone before. */
1742                                 --i;
1743                                 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1744                                 size_t len;
1745
1746                                 aligned_start = align(i->first, blocksize);
1747                                 aligned_end = align(i->second, blocksize);
1748
1749                                 if ((aligned_end - aligned_start) > max)
1750                                         len = max;
1751                                 else
1752                                         len = aligned_end - aligned_start;
1753
1754                                 start = aligned_end - len;
1755                                 eDebug("skipping to %llx, %zd", start, len);
1756                         }
1757
1758                         eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1759                         return;
1760                 }
1761         }
1762
1763         if(current_offset <0)
1764                 current_offset =0;
1765         if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1766         {
1767                 eDebug("reached SOF");
1768                 m_skipmode_m = 0;
1769                 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1770         }
1771         if (m_source_span.empty())
1772         {
1773                 start = current_offset;
1774                 size = max;
1775                 eDebug("NO CUESHEET. (%08lld, %zd)", start, size);
1776         } else
1777         {
1778                 start = current_offset;
1779                 size = 0;
1780         }
1781         return;
1782 }
1783
1784 void eDVBChannel::AddUse()
1785 {
1786         if (++m_use_count > 1 && m_state == state_last_instance)
1787         {
1788                 m_state = state_ok;
1789                 m_stateChanged(this);
1790         }
1791 }
1792
1793 void eDVBChannel::ReleaseUse()
1794 {
1795         if (!--m_use_count)
1796         {
1797                 m_state = state_release;
1798                 m_stateChanged(this);
1799         }
1800         else if (m_use_count == 1)
1801         {
1802                 m_state = state_last_instance;
1803                 m_stateChanged(this);
1804         }
1805 }
1806
1807 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1808 {
1809         if (m_channel_id)
1810                 m_mgr->removeChannel(this);
1811
1812         if (!channelid)
1813                 return 0;
1814
1815         m_channel_id = channelid;
1816         m_mgr->addChannel(channelid, this);
1817
1818         if (!m_frontend)
1819         {
1820                 /* no frontend, no need to tune (must be a streamed service) */
1821                 return 0;
1822         }
1823
1824         m_state = state_tuning;
1825                         /* if tuning fails, shutdown the channel immediately. */
1826         int res;
1827         res = m_frontend->get().tune(*feparm);
1828         m_current_frontend_parameters = feparm;
1829
1830         if (res)
1831         {
1832                 m_state = state_release;
1833                 m_stateChanged(this);
1834                 return res;
1835         }
1836
1837         return 0;
1838 }
1839
1840 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1841 {
1842         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1843         return 0;
1844 }
1845
1846 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1847 {
1848         connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1849         return 0;
1850 }
1851
1852 RESULT eDVBChannel::getState(int &state)
1853 {
1854         state = m_state;
1855         return 0;
1856 }
1857
1858 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1859 {
1860         return -1;
1861 }
1862
1863 void eDVBChannel::SDTready(int result)
1864 {
1865         ePyObject args = PyTuple_New(2), ret;
1866         bool ok=false;
1867         if (!result)
1868         {
1869                 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1870                 {
1871                         ok = true;
1872                         PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1873                         PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1874                         break;
1875                 }
1876         }
1877         if (!ok)
1878         {
1879                 PyTuple_SET_ITEM(args, 0, Py_None);
1880                 PyTuple_SET_ITEM(args, 1, Py_None);
1881                 Py_INCREF(Py_None);
1882                 Py_INCREF(Py_None);
1883         }
1884         ret = PyObject_CallObject(m_tsid_onid_callback, args);
1885         if (ret)
1886                 Py_DECREF(ret);
1887         Py_DECREF(args);
1888         Py_DECREF(m_tsid_onid_callback);
1889         m_tsid_onid_callback = ePyObject();
1890         m_tsid_onid_demux = 0;
1891         m_SDT = 0;
1892 }
1893
1894 int eDVBChannel::reserveDemux()
1895 {
1896         ePtr<iDVBDemux> dmx;
1897         if (!getDemux(dmx, 0))
1898         {
1899                 uint8_t id;
1900                 if (!dmx->getCADemuxID(id))
1901                         return id;
1902         }
1903         return -1;
1904 }
1905
1906 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1907 {
1908         if (PyCallable_Check(callback))
1909         {
1910                 if (!getDemux(m_tsid_onid_demux, 0))
1911                 {
1912                         m_SDT = new eTable<ServiceDescriptionSection>;
1913                         CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1914                         if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1915                         {
1916                                 m_tsid_onid_demux = 0;
1917                                 m_SDT = 0;
1918                         }
1919                         else
1920                         {
1921                                 Py_INCREF(callback);
1922                                 m_tsid_onid_callback = callback;
1923                                 return 0;
1924                         }
1925                 }
1926         }
1927         return -1;
1928 }
1929
1930 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1931 {
1932         ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1933
1934         if (m_frontend == NULL)
1935         {
1936                 /* in dvr mode, we have to stick to a single demux (the one connected to our dvr device) */
1937                 our_demux = m_decoder_demux ? m_decoder_demux : m_demux;
1938         }
1939
1940         if (!our_demux)
1941         {
1942                 demux = 0;
1943
1944                 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1945                         return -1;
1946
1947                 demux = *our_demux;
1948
1949                 /* don't hold a reference to the decoding demux, we don't need it. */
1950
1951                 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1952                    the refcount is lost. thus, decoding demuxes are never allocated.
1953
1954                    this poses a big problem for PiP. */
1955
1956                 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1957                         ;
1958                 else if (cap & capDecode)
1959                         our_demux = 0;
1960         }
1961         else
1962                 demux = *our_demux;
1963
1964         return 0;
1965 }
1966
1967 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1968 {
1969         frontend = 0;
1970         if (!m_frontend)
1971                 return -ENODEV;
1972         frontend = &m_frontend->get();
1973         if (frontend)
1974                 return 0;
1975         return -ENODEV;
1976 }
1977
1978 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> &param)
1979 {
1980         param = m_current_frontend_parameters;
1981         return 0;
1982 }
1983
1984 RESULT eDVBChannel::playFile(const char *file)
1985 {
1986         eRawFile *f = new eRawFile();
1987         ePtr<iTsSource> source = f;
1988
1989         if (f->open(file) < 0)
1990         {
1991                 eDebug("can't open PVR file %s (%m)", file);
1992                 return -ENOENT;
1993         }
1994
1995         return playSource(source, file);
1996 }
1997
1998 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
1999 {
2000         ASSERT(!m_frontend);
2001         if (m_pvr_thread)
2002         {
2003                 m_pvr_thread->stop();
2004                 delete m_pvr_thread;
2005                 m_pvr_thread = 0;
2006         }
2007
2008         if (!source->valid() && !source->isStream())
2009         {
2010                 eDebug("PVR source is not valid!");
2011                 return -ENOENT;
2012         }
2013
2014         m_tstools.setSource(source, streaminfo_file);
2015
2016                 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
2017                    THEN DO A REAL FIX HERE! */
2018
2019         if (m_pvr_fd_dst < 0)
2020         {
2021                 /* (this codepath needs to be improved anyway.) */
2022 #if HAVE_DVB_API_VERSION < 3
2023                 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
2024                 if (m_pvr_fd_dst < 0)
2025                 {
2026                         eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
2027                         return -ENODEV;
2028                 }
2029 #else
2030                 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
2031                 if (demux)
2032                 {
2033                         m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
2034                         if (m_pvr_fd_dst < 0)
2035                         {
2036                                 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
2037                                 return -ENODEV;
2038                         }
2039                 }
2040                 else
2041                 {
2042                         eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
2043                         return -ENODEV;
2044                 }
2045 #endif
2046         }
2047
2048         m_pvr_thread = new eDVBChannelFilePush();
2049         m_pvr_thread->enablePVRCommit(1);
2050         /* If the source specifies a length, it's a file. If not, it's a stream */
2051         m_pvr_thread->setStreamMode(source->isStream());
2052         m_pvr_thread->setScatterGather(this);
2053
2054         m_event(this, evtPreStart);
2055
2056         m_pvr_thread->start(source, m_pvr_fd_dst);
2057         CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
2058
2059         m_state = state_ok;
2060         m_stateChanged(this);
2061
2062         return 0;
2063 }
2064
2065 void eDVBChannel::stopSource()
2066 {
2067         if (m_pvr_thread)
2068         {
2069                 m_pvr_thread->stop();
2070                 delete m_pvr_thread;
2071                 m_pvr_thread = 0;
2072         }
2073         if (m_pvr_fd_dst >= 0)
2074         {
2075                 ::close(m_pvr_fd_dst);
2076                 m_pvr_fd_dst = -1;
2077         }
2078         ePtr<iTsSource> d;
2079         m_tstools.setSource(d);
2080 }
2081
2082 void eDVBChannel::stopFile()
2083 {
2084         stopSource();
2085 }
2086
2087 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
2088 {
2089         m_conn_cueSheetEvent = 0;
2090         m_cue = cuesheet;
2091         if (m_cue)
2092                 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
2093 }
2094
2095 RESULT eDVBChannel::getLength(pts_t &len)
2096 {
2097         return m_tstools.calcLen(len);
2098 }
2099
2100 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
2101 {
2102         if (!decoding_demux)
2103                 return -1;
2104
2105         pts_t now;
2106
2107         int r;
2108
2109         if (mode == 0) /* demux */
2110         {
2111                 r = decoding_demux->getSTC(now, 0);
2112                 if (r)
2113                 {
2114                         eDebug("demux getSTC failed");
2115                         return -1;
2116                 }
2117         } else
2118                 now = pos; /* fixup supplied */
2119
2120         off_t off = 0; /* TODO: fixme */
2121         r = m_tstools.fixupPTS(off, now);
2122         if (r)
2123         {
2124                 eDebug("fixup PTS failed");
2125                 return -1;
2126         }
2127
2128         pos = now;
2129
2130         return 0;
2131 }
2132
2133 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
2134 {
2135                         /* when seeking, we have to ensure that all buffers are flushed.
2136                            there are basically 3 buffers:
2137                            a.) the filepush's internal buffer
2138                            b.) the PVR buffer (before demux)
2139                            c.) the ratebuffer (after demux)
2140
2141                            it's important to clear them in the correct order, otherwise
2142                            the ratebuffer (for example) would immediately refill from
2143                            the not-yet-flushed PVR buffer.
2144                         */
2145
2146         m_pvr_thread->pause();
2147                 /* flush internal filepush buffer */
2148         m_pvr_thread->flush();
2149                 /* HACK: flush PVR buffer */
2150         ::ioctl(m_pvr_fd_dst, 0);
2151
2152                 /* flush ratebuffers (video, audio) */
2153         if (decoding_demux)
2154                 decoding_demux->flush();
2155
2156                 /* demux will also flush all decoder.. */
2157                 /* resume will re-query the SG */
2158         m_pvr_thread->resume();
2159 }
2160
2161 DEFINE_REF(eCueSheet);
2162
2163 eCueSheet::eCueSheet()
2164 {
2165         m_skipmode_ratio = 0;
2166 }
2167
2168 void eCueSheet::seekTo(int relative, const pts_t &pts)
2169 {
2170         m_lock.WrLock();
2171         m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
2172         m_lock.Unlock();
2173         m_event(evtSeek);
2174 }
2175
2176 void eCueSheet::clear()
2177 {
2178         m_lock.WrLock();
2179         m_spans.clear();
2180         m_lock.Unlock();
2181 }
2182
2183 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
2184 {
2185         ASSERT(begin < end);
2186         m_lock.WrLock();
2187         m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
2188         m_lock.Unlock();
2189 }
2190
2191 void eCueSheet::commitSpans()
2192 {
2193         m_event(evtSpanChanged);
2194 }
2195
2196 void eCueSheet::setSkipmode(const pts_t &ratio)
2197 {
2198         m_lock.WrLock();
2199         m_skipmode_ratio = ratio;
2200         m_lock.Unlock();
2201         m_event(evtSkipmode);
2202 }
2203
2204 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
2205 {
2206         m_decoding_demux = demux;
2207         m_decoder = decoder;
2208 }
2209
2210 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
2211 {
2212         connection = new eConnection(this, m_event.connect(event));
2213         return 0;
2214 }