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