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