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