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